@pompidup/kingdomino-engine 3.2.0 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/domain/types/game.ts","../src/core/useCases/gameDebug.ts","../src/core/useCases/gameEvents.ts","../src/adapterServerside/consoleLogger.ts","../src/datasources/dominoes.json","../src/adapterServerside/jsonDominoes.ts","../src/datasources/modes.json","../src/adapterServerside/jsonModes.ts","../src/datasources/rules.json","../src/adapterServerside/jsonRules.ts","../src/adapterServerside/shuffle.ts","../src/adapterServerside/uuid.ts","../src/core/domain/errors/domainErrors.ts","../src/core/i18n/translations.ts","../src/utils/result.ts","../src/application/handlers/addExtraRulesHandler.ts","../src/application/handlers/addPlayersHandler.ts","../src/application/handlers/calculateScoreHandler.ts","../src/application/handlers/canPlaceDominoHandler.ts","../src/application/handlers/chooseDominoHandler.ts","../src/application/handlers/createGameHandler.ts","../src/application/handlers/discardDominoHandler.ts","../src/application/handlers/getDynastyResultHandler.ts","../src/application/handlers/getExtraRulesHandler.ts","../src/application/handlers/getModesHandler.ts","../src/application/handlers/getResultHandler.ts","../src/application/handlers/getValidPlacementsHandler.ts","../src/application/handlers/placeDominoHandler.ts","../src/core/useCases/serialization.ts","../src/application/handlers/serializeGameHandler.ts","../src/application/handlers/startGameHandler.ts","../src/core/domain/types/kingdom.ts","../src/core/domain/types/domino.ts","../src/core/domain/types/player.ts","../src/core/domain/entities/rule.ts","../src/utils/seededShuffle.ts","../src/core/useCases/addExtraRules.ts","../src/core/domain/entities/domino.ts","../src/core/domain/entities/kingdom.ts","../src/core/domain/entities/player.ts","../src/core/useCases/addPlayers.ts","../src/core/useCases/calculateScore.ts","../src/core/domain/entities/lord.ts","../src/core/useCases/chooseDomino.ts","../src/core/domain/entities/game.ts","../src/core/domain/entities/mode.ts","../src/core/useCases/createGame.ts","../src/core/useCases/getValidPlacements.ts","../src/core/useCases/discardDomino.ts","../src/core/useCases/getDynastyResult.ts","../src/core/useCases/getExtraRules.ts","../src/core/useCases/getModes.ts","../src/core/useCases/getResult.ts","../src/core/useCases/placeDomino.ts","../src/core/useCases/startGame.ts","../src/config.ts","../src/core/domain/entities/validateGameState.ts","../src/core/useCases/botRegistry.ts","../src/core/useCases/bot.ts","../src/core/useCases/gameActionLog.ts","../src/core/useCases/gameHistory.ts","../src/index.ts"],"sourcesContent":["import type { Result } from \"@utils/result.js\";\nimport type { Domino, RevealsDomino } from \"./domino.js\";\nimport type { Lord } from \"./lord.js\";\nimport type { GameMode } from \"./mode.js\";\nimport type { Player, PlayerActions } from \"./player.js\";\nimport type { SelectedRules } from \"./rule.js\";\nimport type { ObjectValues } from \"./utils.js\";\n\n/**\n * Represents the complete state of a Kingdomino game.\n * This is the main aggregate containing all game data.\n */\nexport type Game = {\n /** Unique identifier for the game */\n id: string;\n /** Remaining dominoes in the draw pile */\n dominoes: Domino[];\n /** Currently revealed dominoes available for picking */\n currentDominoes: RevealsDomino[];\n /** Players participating in the game with their kingdoms */\n players: Player[];\n /** Lords (player tokens) used for turn order and domino selection */\n lords: Lord[];\n /** Current turn number (1-based) */\n turn: number;\n /** Next required action or game step */\n nextAction: NextAction | NextStep;\n /** Active rules for this game */\n rules: SelectedRules;\n /** Game mode being played */\n mode: GameMode;\n /** Optional seed for deterministic shuffle (replays, sharing) */\n seed?: string;\n};\n\n/**\n * Available game steps representing phases of game setup and completion.\n */\nexport const gameSteps = {\n /** Waiting for players to be added */\n addPlayers: \"addPlayers\",\n /** Optional rules selection phase */\n options: \"options\",\n /** Ready to start the game */\n start: \"start\",\n /** Game has ended, results available */\n result: \"result\",\n} as const;\n\n/** Union type of all possible game steps */\nexport type GameSteps = ObjectValues<typeof gameSteps>;\n\n/**\n * Represents a player action that needs to be performed.\n * Used during active gameplay.\n */\nexport type NextAction = {\n /** Discriminator for action type */\n type: \"action\";\n /** ID of the lord who must perform the action */\n nextLord: string;\n /** The action the lord must perform */\n nextAction: PlayerActions;\n};\n\n/**\n * Represents a game phase transition.\n * Used during setup and game end.\n */\nexport type NextStep = {\n /** Discriminator for step type */\n type: \"step\";\n /** The current game step/phase */\n step: GameSteps;\n};\n\n/** Game state where a player action is required */\nexport type GameWithNextAction = Game & { nextAction: NextAction };\n\n/** Game state where a phase transition is occurring */\nexport type GameWithNextStep = Game & { nextAction: NextStep };\n\n/** Union of all possible game states */\nexport type GameState = GameWithNextAction | GameWithNextStep;\n\n/** Result wrapper for game state operations */\nexport type GameStateResult = Result<GameState>;\n\n/**\n * Type guard to check if the game requires a player action.\n * @param game - The game state to check\n * @returns True if the game is waiting for a player action\n */\nexport const isGameWithNextAction = (\n game: GameWithNextAction | GameWithNextStep\n): game is GameWithNextAction => {\n return game.nextAction.type === \"action\";\n};\n\n/**\n * Type guard to check if the game is in a phase transition.\n * @param game - The game state to check\n * @returns True if the game is transitioning between phases\n */\nexport const isGameWithNextStep = (\n game: GameWithNextAction | GameWithNextStep\n): game is GameWithNextStep => {\n return game.nextAction.type === \"step\";\n};\n\n/**\n * Represents the score calculation for a kingdom.\n */\nexport type Score = {\n /** Total points earned */\n points: number;\n /** Size of the largest contiguous property */\n maxPropertiesSize: number;\n /** Total number of crowns in the kingdom */\n totalCrowns: number;\n};\n\n/**\n * Score result for a specific player.\n */\nexport type ScoreResult = {\n /** Player's unique identifier */\n playerId: string;\n /** Player's display name */\n playerName: string;\n /** Detailed score breakdown */\n details: Score;\n};\n\n/**\n * Final result including ranking position.\n */\nexport type FinalResult = ScoreResult & {\n /** Player's final position (1 = winner) */\n position: number;\n};\n\n/** Game state with final results calculated */\nexport type GameWithResults = Game & { result: FinalResult[] };\n","import { isGameWithNextAction } from \"@core/domain/types/game.js\";\nimport type { GameState } from \"@core/domain/types/index.js\";\nimport type { GameEngine } from \"@core/portUserside/engine.js\";\n\n// ─── Types ──────────────────────────────────────────────────────────\n\n/**\n * Debug log verbosity level.\n * - `minimal`: method name + phase only\n * - `standard`: + game state summary + key params\n * - `verbose`: + full game state JSON dump\n */\nexport type DebugLogLevel = \"minimal\" | \"standard\" | \"verbose\";\n\n/**\n * Summary of the current game state, extracted for quick inspection.\n */\nexport type GameStateSummary = {\n gameId: string;\n turn: number;\n nextAction: string;\n playersCount: number;\n dominoesRemaining: number;\n currentDominoesCount: number;\n lordsCount: number;\n};\n\n/**\n * A single debug log entry emitted by the debug wrapper.\n */\nexport type DebugLogEntry = {\n timestamp: string;\n method: string;\n phase: \"before\" | \"after\" | \"error\";\n summary: GameStateSummary | null;\n params?: Record<string, unknown>;\n error?: string;\n durationMs?: number;\n fullState?: GameState;\n};\n\n/**\n * Custom debug logger interface.\n * Consumers can provide their own to redirect debug output.\n */\nexport type DebugLogger = {\n log: (entry: DebugLogEntry) => void;\n};\n\n/**\n * Configuration for the debug wrapper.\n */\nexport type DebugOptions = {\n /** Custom debug logger. Defaults to console-based logger. */\n logger?: DebugLogger;\n /** Verbosity level. Defaults to \"standard\". */\n level?: DebugLogLevel;\n};\n\n// ─── Helpers ────────────────────────────────────────────────────────\n\n/**\n * Extracts a concise summary from a game state object.\n */\nexport const summarizeGameState = (game: GameState): GameStateSummary => {\n const nextAction = isGameWithNextAction(game)\n ? `action:${game.nextAction.nextAction}`\n : `step:${game.nextAction.step}`;\n\n return {\n gameId: game.id,\n turn: game.turn,\n nextAction,\n playersCount: game.players.length,\n dominoesRemaining: game.dominoes.length,\n currentDominoesCount: game.currentDominoes.length,\n lordsCount: game.lords.length,\n };\n};\n\nconst defaultDebugLogger: DebugLogger = {\n log: (entry: DebugLogEntry) => {\n const phase = entry.phase.toUpperCase().padEnd(5);\n const base = `[KDomino:Debug] ${entry.timestamp} ${phase} ${entry.method}`;\n\n if (entry.phase === \"error\") {\n console.error(`${base} | error: ${entry.error}`);\n return;\n }\n\n if (entry.summary) {\n const s = entry.summary;\n console.log(\n `${base} | turn=${s.turn} next=${s.nextAction} players=${s.playersCount} dominoes=${s.dominoesRemaining}`,\n );\n } else {\n console.log(base);\n }\n },\n};\n\nconst isGameState = (value: unknown): value is GameState => {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"id\" in value &&\n \"nextAction\" in value &&\n \"players\" in value &&\n \"dominoes\" in value\n );\n};\n\ntype CommandWithGame = { game: GameState; [key: string]: unknown };\n\nconst hasGameInCommand = (cmd: unknown): cmd is CommandWithGame => {\n return (\n typeof cmd === \"object\" &&\n cmd !== null &&\n \"game\" in cmd &&\n isGameState((cmd as CommandWithGame).game)\n );\n};\n\nconst extractParams = (cmd: unknown): Record<string, unknown> | undefined => {\n if (typeof cmd !== \"object\" || cmd === null) return undefined;\n\n const record = cmd as Record<string, unknown>;\n const params: Record<string, unknown> = {};\n\n if (\"mode\" in record) params.mode = record.mode;\n if (\"lordId\" in record) params.lordId = record.lordId;\n if (\"dominoPick\" in record) params.dominoPick = record.dominoPick;\n if (\"position\" in record) params.position = record.position;\n if (\"rotation\" in record) params.rotation = record.rotation;\n if (\"players\" in record) params.players = record.players;\n if (\"extraRules\" in record) params.extraRules = record.extraRules;\n\n return Object.keys(params).length > 0 ? params : undefined;\n};\n\n// ─── Wrapper ────────────────────────────────────────────────────────\n\nconst wrapMethod = <TArgs, TResult>(\n method: string,\n fn: (cmd: TArgs) => TResult,\n logger: DebugLogger,\n level: DebugLogLevel,\n): ((cmd: TArgs) => TResult) => {\n return (cmd: TArgs) => {\n const timestamp = new Date().toISOString();\n\n // Before\n const beforeSummary =\n level !== \"minimal\" && hasGameInCommand(cmd)\n ? summarizeGameState(cmd.game)\n : null;\n\n const beforeEntry: DebugLogEntry = {\n timestamp,\n method,\n phase: \"before\",\n summary: beforeSummary,\n params: level !== \"minimal\" ? extractParams(cmd) : undefined,\n };\n\n logger.log(beforeEntry);\n\n // Execute\n const start = performance.now();\n let result: TResult;\n try {\n result = fn(cmd);\n } catch (err) {\n const durationMs = Math.round((performance.now() - start) * 100) / 100;\n const errorEntry: DebugLogEntry = {\n timestamp: new Date().toISOString(),\n method,\n phase: \"error\",\n summary: beforeSummary,\n error: err instanceof Error ? err.message : String(err),\n durationMs,\n };\n logger.log(errorEntry);\n throw err;\n }\n\n const durationMs = Math.round((performance.now() - start) * 100) / 100;\n\n // After\n const afterSummary =\n level !== \"minimal\" && isGameState(result)\n ? summarizeGameState(result as GameState)\n : null;\n\n const afterEntry: DebugLogEntry = {\n timestamp: new Date().toISOString(),\n method,\n phase: \"after\",\n summary: afterSummary,\n durationMs,\n fullState:\n level === \"verbose\" && isGameState(result)\n ? (result as GameState)\n : undefined,\n };\n\n logger.log(afterEntry);\n\n return result;\n };\n};\n\n/**\n * Wraps a GameEngine to emit detailed debug log entries before and after each method call.\n * Useful for UI developers to inspect engine behavior at every step.\n *\n * @param engine - The base game engine to wrap\n * @param options - Debug configuration (logger, verbosity level)\n * @returns A new GameEngine that emits debug logs\n *\n * @example\n * ```typescript\n * const debugEngine = wrapWithDebug(engine, { level: \"verbose\" });\n * let game = debugEngine.createGame({ mode: \"Classic\" });\n * // Console: [KDomino:Debug] ... BEFORE createGame\n * // Console: [KDomino:Debug] ... AFTER createGame | turn=0 ...\n * ```\n */\nexport const wrapWithDebug = (\n engine: GameEngine,\n options?: DebugOptions,\n): GameEngine => {\n const logger = options?.logger ?? defaultDebugLogger;\n const level = options?.level ?? \"standard\";\n\n return {\n getModes: wrapMethod(\"getModes\", engine.getModes, logger, level),\n getExtraRules: wrapMethod(\n \"getExtraRules\",\n engine.getExtraRules,\n logger,\n level,\n ),\n createGame: wrapMethod(\"createGame\", engine.createGame, logger, level),\n addPlayers: wrapMethod(\"addPlayers\", engine.addPlayers, logger, level),\n addExtraRules: wrapMethod(\n \"addExtraRules\",\n engine.addExtraRules,\n logger,\n level,\n ),\n startGame: wrapMethod(\"startGame\", engine.startGame, logger, level),\n chooseDomino: wrapMethod(\n \"chooseDomino\",\n engine.chooseDomino,\n logger,\n level,\n ),\n placeDomino: wrapMethod(\"placeDomino\", engine.placeDomino, logger, level),\n discardDomino: wrapMethod(\n \"discardDomino\",\n engine.discardDomino,\n logger,\n level,\n ),\n getResults: wrapMethod(\"getResults\", engine.getResults, logger, level),\n calculateScore: wrapMethod(\n \"calculateScore\",\n engine.calculateScore,\n logger,\n level,\n ),\n getValidPlacements: wrapMethod(\n \"getValidPlacements\",\n engine.getValidPlacements,\n logger,\n level,\n ),\n canPlaceDomino: wrapMethod(\n \"canPlaceDomino\",\n engine.canPlaceDomino,\n logger,\n level,\n ),\n serialize: wrapMethod(\"serialize\", engine.serialize, logger, level),\n deserialize: wrapMethod(\"deserialize\", engine.deserialize, logger, level),\n getDynastyResults: wrapMethod(\n \"getDynastyResults\",\n engine.getDynastyResults,\n logger,\n level,\n ),\n };\n};\n","import type {\n GameState,\n GameWithNextAction,\n GameWithNextStep,\n} from \"@core/domain/types/index.js\";\nimport { isGameWithNextStep } from \"@core/domain/types/game.js\";\nimport type { GameEngine } from \"@core/portUserside/engine.js\";\n\n// ─── Event Types ─────────────────────────────────────────────────────\n\n/**\n * Optional callbacks for game events.\n * Consumers provide these to react to state changes (UI updates, animations, logging).\n * All callbacks are optional — only the ones you provide will be called.\n *\n * @example\n * ```typescript\n * const engine = createGameEngine({\n * events: {\n * onDominoPlaced: ({ game, lordId }) => {\n * console.log(`Lord ${lordId} placed a domino`);\n * animatePlacement(game);\n * },\n * onTurnEnd: ({ turn }) => console.log(`Turn ${turn} ended`),\n * onGameEnd: () => showResultsScreen(),\n * },\n * });\n * ```\n */\nexport type GameEventCallbacks = {\n /** Called after a new game is created */\n onGameCreated?: (event: { game: GameWithNextStep }) => void;\n /** Called after players are added to the game */\n onPlayersAdded?: (event: { game: GameWithNextStep }) => void;\n /** Called after the game starts (first dominoes revealed) */\n onGameStarted?: (event: { game: GameWithNextAction }) => void;\n /** Called after a lord picks a domino */\n onDominoPicked?: (event: {\n game: GameState;\n lordId: string;\n dominoNumber: number;\n }) => void;\n /** Called after a lord places a domino on their kingdom */\n onDominoPlaced?: (event: { game: GameState; lordId: string }) => void;\n /** Called after a lord discards a domino (no valid placement) */\n onDominoDiscarded?: (event: { game: GameState; lordId: string }) => void;\n /** Called when a new turn begins */\n onTurnStart?: (event: { game: GameState; turn: number }) => void;\n /** Called when a turn ends (all lords have played) */\n onTurnEnd?: (event: { game: GameState; turn: number }) => void;\n /** Called when the game reaches the result phase */\n onGameEnd?: (event: { game: GameState }) => void;\n};\n\n// ─── Wrapper ─────────────────────────────────────────────────────────\n\nconst isGameEnded = (game: GameState): boolean =>\n isGameWithNextStep(game) && game.nextAction.step === \"result\";\n\n/**\n * Wraps a GameEngine to emit event callbacks after each state-changing method.\n * Read-only methods (getModes, calculateScore, etc.) are passed through unchanged.\n *\n * Derived events:\n * - `onTurnEnd` + `onTurnStart`: emitted when `chooseDomino` causes a turn increment\n * - `onGameEnd`: emitted when `placeDomino` or `discardDomino` transitions to the \"result\" step\n *\n * @param engine - The base game engine to wrap\n * @param callbacks - Optional event callbacks\n * @returns A new GameEngine that emits events\n */\nexport const wrapWithEvents = (\n engine: GameEngine,\n callbacks: GameEventCallbacks\n): GameEngine => ({\n // Read-only methods — pass through\n getModes: (cmd) => engine.getModes(cmd),\n getExtraRules: (cmd) => engine.getExtraRules(cmd),\n calculateScore: (cmd) => engine.calculateScore(cmd),\n getValidPlacements: (cmd) => engine.getValidPlacements(cmd),\n canPlaceDomino: (cmd) => engine.canPlaceDomino(cmd),\n serialize: (cmd) => engine.serialize(cmd),\n deserialize: (cmd) => engine.deserialize(cmd),\n getResults: (cmd) => engine.getResults(cmd),\n getDynastyResults: (cmd) => engine.getDynastyResults(cmd),\n\n // State-changing methods — emit events after execution\n createGame: (cmd) => {\n const game = engine.createGame(cmd);\n callbacks.onGameCreated?.({ game });\n return game;\n },\n\n addPlayers: (cmd) => {\n const game = engine.addPlayers(cmd);\n callbacks.onPlayersAdded?.({ game });\n return game;\n },\n\n addExtraRules: (cmd) => engine.addExtraRules(cmd),\n\n startGame: (cmd) => {\n const game = engine.startGame(cmd);\n callbacks.onGameStarted?.({ game });\n callbacks.onTurnStart?.({ game, turn: game.turn });\n return game;\n },\n\n chooseDomino: (cmd) => {\n const turnBefore = cmd.game.turn;\n const game = engine.chooseDomino(cmd);\n callbacks.onDominoPicked?.({\n game,\n lordId: cmd.lordId,\n dominoNumber: cmd.dominoPick,\n });\n\n // Detect turn transition\n if (game.turn !== turnBefore) {\n callbacks.onTurnEnd?.({ game, turn: turnBefore });\n callbacks.onTurnStart?.({ game, turn: game.turn });\n }\n\n return game;\n },\n\n placeDomino: (cmd) => {\n const game = engine.placeDomino(cmd);\n callbacks.onDominoPlaced?.({ game, lordId: cmd.lordId });\n\n if (isGameEnded(game)) {\n callbacks.onGameEnd?.({ game });\n }\n\n return game;\n },\n\n discardDomino: (cmd) => {\n const game = engine.discardDomino(cmd);\n callbacks.onDominoDiscarded?.({ game, lordId: cmd.lordId });\n\n if (isGameEnded(game)) {\n callbacks.onGameEnd?.({ game });\n }\n\n return game;\n },\n});\n","import type { Logger } from \"@core/portServerside/logger.js\";\n\n/**\n * Creates a lightweight console-based logger.\n * This is the default logger used when no custom logger is provided.\n * @param isLoggingEnabled - Whether logging is enabled\n * @returns A Logger instance that outputs to console\n */\nexport const consoleLogger = (isLoggingEnabled: boolean): Logger => {\n const formatMessage = (level: string, message: string): string => {\n const timestamp = new Date().toISOString();\n return `${timestamp} [KDomino_Engine] ${level}: ${message}`;\n };\n\n return {\n info: (message: string) => {\n if (isLoggingEnabled) {\n console.log(formatMessage(\"info\", message));\n }\n },\n error: (message: string) => {\n if (isLoggingEnabled) {\n console.error(formatMessage(\"error\", message));\n }\n },\n };\n};\n\n/**\n * A silent logger that does nothing.\n * Useful for testing or when logging should be completely disabled.\n */\nexport const silentLogger: Logger = {\n info: () => {},\n error: () => {},\n};\n","{\n \"Classic\": [\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 1\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 2\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 3\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 4\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 5\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 6\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 7\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 8\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 9\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 10\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 11\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"number\": 12\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 13\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 14\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 15\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"number\": 16\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 17\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 18\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 19\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 20\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 21\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"number\": 22\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 0\n },\n \"number\": 23\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 24\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 25\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 26\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 27\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 28\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 29\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 30\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 31\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 32\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 33\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 34\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 35\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 1\n },\n \"number\": 36\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 1\n },\n \"number\": 37\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 1\n },\n \"number\": 38\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"number\": 39\n },\n {\n \"left\": {\n \"type\": \"mine\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 40\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 2\n },\n \"number\": 41\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 2\n },\n \"number\": 42\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 2\n },\n \"number\": 43\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 2\n },\n \"number\": 44\n },\n {\n \"left\": {\n \"type\": \"mine\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 45\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 2\n },\n \"number\": 46\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 2\n },\n \"number\": 47\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 3\n },\n \"number\": 48\n }\n ]\n}\n","import type { Domino, Ground } from \"@core/domain/types/domino.js\";\nimport type { GameMode } from \"@core/domain/types/mode.js\";\nimport type { DominoesRepository } from \"@core/portServerside/dominoesRepository.js\";\nimport dominoesJson from \"../datasources/dominoes.json\" with { type: \"json\" };\n\nconst jsonDominoes = (): DominoesRepository => {\n const dominoes: Record<string, Domino[]> = {};\n\n for (const [key, value] of Object.entries(dominoesJson)) {\n const currentDominoes: Domino[] = [];\n value.forEach((domino) => {\n currentDominoes.push({\n left: {\n type: <Ground>domino.left.type,\n crowns: domino.left.crowns,\n },\n right: {\n type: <Ground>domino.right.type,\n crowns: domino.right.crowns,\n },\n number: domino.number,\n });\n });\n\n dominoes[key] = currentDominoes;\n }\n\n return {\n getForMode: (mode: GameMode) => {\n return dominoes[mode.name] || [];\n },\n };\n};\n\nexport default jsonDominoes;\n","[\n {\n \"name\": \"Classic\",\n \"description\": \"Original KingDomino rules\"\n }\n]","import type { GameMode } from \"@core/domain/types/mode.js\";\nimport type { ModeRepository } from \"@core/portServerside/modeRepository.js\";\nimport modesJson from \"../datasources/modes.json\" with { type: \"json\" };\n\nconst jsonModes = (): ModeRepository => {\n const modes: GameMode[] = [];\n\n modesJson.forEach((mode) => {\n modes.push({\n name: mode.name,\n description: mode.description,\n });\n });\n\n return {\n getAvailables: () => {\n return modes;\n },\n };\n};\n\nexport default jsonModes;\n","{\n \"commun\": [\n {\n \"playersLimit\": 1,\n \"lordsPerPlayer\": 1,\n \"maxDominoes\": 48,\n \"dominoesPerTurn\": 4,\n \"maxTurns\": 12,\n \"maxKingdomSize\": 5\n },\n {\n \"playersLimit\": 2,\n \"lordsPerPlayer\": 2,\n \"maxDominoes\": 24,\n \"dominoesPerTurn\": 4,\n \"maxTurns\": 6,\n \"maxKingdomSize\": 5\n },\n {\n \"playersLimit\": 3,\n \"lordsPerPlayer\": 1,\n \"maxDominoes\": 48,\n \"dominoesPerTurn\": 4,\n \"maxTurns\": 12,\n \"maxKingdomSize\": 5\n },\n {\n \"playersLimit\": 4,\n \"lordsPerPlayer\": 1,\n \"maxDominoes\": 48,\n \"dominoesPerTurn\": 4,\n \"maxTurns\": 12,\n \"maxKingdomSize\": 5\n }\n ],\n \"extra\": [\n {\n \"name\": \"The middle Kingdom\",\n \"description\": \"Gain 10 additional points if your castle is in the middle of the kingdom.\",\n \"mode\": [{ \"name\": \"Classic\", \"description\": \"King Domino classic mode\" }]\n },\n {\n \"name\": \"Harmony\",\n \"description\": \"Gain 5 additional points if your kingdom is complete (no discarded dominoes).\",\n \"mode\": [{ \"name\": \"Classic\", \"description\": \"King Domino classic mode\" }]\n },\n {\n \"name\": \"The Mighty Duel\",\n \"description\": \"Use all 48 dominoes and build a 7x7 kingdom. For 2 players only.\",\n \"mode\": [{ \"name\": \"Classic\", \"description\": \"King Domino classic mode\" }],\n \"playersLimit\": 2\n },\n {\n \"name\": \"Dynasty\",\n \"description\": \"Play 3 games in a row. The player with the highest total points wins.\",\n \"mode\": [{ \"name\": \"Classic\", \"description\": \"King Domino classic mode\" }]\n }\n ]\n}\n","import type { Rules } from \"@core/domain/types/rule.js\";\nimport type { RuleRepository } from \"@core/portServerside/ruleRepository.js\";\nimport rulesJson from \"../datasources/rules.json\" with { type: \"json\" };\n\nconst jsonRules = (): RuleRepository => {\n const rules: Rules = {\n basic: {},\n extraRules: [],\n };\n\n const commonRules = rulesJson.commun;\n const extraRules = rulesJson.extra;\n\n commonRules.forEach((rule) => {\n rules.basic[rule.playersLimit] = {\n lords: rule.lordsPerPlayer,\n maxDominoes: rule.maxDominoes,\n dominoesPerTurn: rule.dominoesPerTurn,\n maxTurns: rule.maxTurns,\n maxKingdomSize: rule.maxKingdomSize,\n };\n });\n\n extraRules.forEach((rule) => {\n rules.extraRules.push({\n name: rule.name,\n description: rule.description,\n mode: rule.mode,\n ...(\"playersLimit\" in rule && { playersLimit: rule.playersLimit }),\n });\n });\n\n return {\n getAll: () => {\n return rules;\n },\n getAllExtra: () => {\n return rules.extraRules;\n },\n };\n};\n\nexport default jsonRules;\n","import type { ShuffleMethod } from \"@core/portServerside/shuffleMethod.js\";\n\nexport const shuffleMethod: ShuffleMethod = <T>(array: T[]) => {\n for (let i = array.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [array[i], array[j]] = [array[j] as T, array[i] as T];\n }\n return array;\n};\n","import type { UuidMethod } from \"@core/portServerside/uuidMethod.js\";\nimport { randomUUID } from \"crypto\";\n\nexport const uuidMethod: UuidMethod = () => {\n return randomUUID();\n};\n","/**\n * Error codes for domain-level errors.\n * These codes can be used for i18n and programmatic error handling.\n */\nexport const ErrorCode = {\n // Game flow errors\n INVALID_STEP: \"INVALID_STEP\",\n STEP_EXECUTION_FAILED: \"STEP_EXECUTION_FAILED\",\n ACTION_EXECUTION_FAILED: \"ACTION_EXECUTION_FAILED\",\n\n // Entity not found errors\n LORD_NOT_FOUND: \"LORD_NOT_FOUND\",\n PLAYER_NOT_FOUND: \"PLAYER_NOT_FOUND\",\n DOMINO_NOT_FOUND: \"DOMINO_NOT_FOUND\",\n MODE_NOT_FOUND: \"MODE_NOT_FOUND\",\n\n // Validation errors\n INVALID_PLAYER_COUNT: \"INVALID_PLAYER_COUNT\",\n INVALID_PLAYER_NAME: \"INVALID_PLAYER_NAME\",\n INVALID_PLACEMENT: \"INVALID_PLACEMENT\",\n PLACEMENT_NOT_EMPTY: \"PLACEMENT_NOT_EMPTY\",\n PLACEMENT_NOT_ADJACENT: \"PLACEMENT_NOT_ADJACENT\",\n PLACEMENT_INVALID_TERRAIN: \"PLACEMENT_INVALID_TERRAIN\",\n PLACEMENT_OUT_OF_BOUNDS: \"PLACEMENT_OUT_OF_BOUNDS\",\n PLACEMENT_EXCEEDS_KINGDOM_SIZE: \"PLACEMENT_EXCEEDS_KINGDOM_SIZE\",\n\n // Action errors\n NOT_YOUR_TURN: \"NOT_YOUR_TURN\",\n CANNOT_PICK: \"CANNOT_PICK\",\n CANNOT_PLACE: \"CANNOT_PLACE\",\n DOMINO_ALREADY_PICKED: \"DOMINO_ALREADY_PICKED\",\n\n // History errors\n UNDO_UNAVAILABLE: \"UNDO_UNAVAILABLE\",\n REDO_UNAVAILABLE: \"REDO_UNAVAILABLE\",\n} as const;\n\nexport type ErrorCodeType = (typeof ErrorCode)[keyof typeof ErrorCode];\n\n/**\n * Structured domain error with code and context.\n */\nexport interface DomainError {\n /** Error code for programmatic handling */\n code: ErrorCodeType;\n /** Human-readable error message */\n message: string;\n /** Optional context data for debugging */\n context?: Record<string, unknown>;\n}\n\n/**\n * Creates a domain error object.\n */\nexport const createDomainError = (\n code: ErrorCodeType,\n message: string,\n context?: Record<string, unknown>,\n): DomainError => ({\n code,\n message,\n context,\n});\n\n/**\n * Base class for domain errors thrown by handlers.\n */\nexport class DomainException extends Error {\n public readonly code: ErrorCodeType;\n public readonly context?: Record<string, unknown>;\n\n constructor(error: DomainError) {\n super(error.message);\n this.name = \"DomainException\";\n this.code = error.code;\n this.context = error.context;\n }\n}\n\n/**\n * Error thrown when the game is in an invalid step for the requested action.\n */\nexport class InvalidStepError extends DomainException {\n constructor(message: string, context?: Record<string, unknown>) {\n super({\n code: ErrorCode.INVALID_STEP,\n message,\n context,\n });\n this.name = \"InvalidStepError\";\n }\n}\n\n/**\n * Error thrown when a step execution fails.\n */\nexport class StepExecutionError extends DomainException {\n constructor(\n message: string,\n code: ErrorCodeType = ErrorCode.STEP_EXECUTION_FAILED,\n context?: Record<string, unknown>,\n ) {\n super({\n code,\n message,\n context,\n });\n this.name = \"StepExecutionError\";\n }\n}\n\n/**\n * Error thrown when an action execution fails.\n */\nexport class ActionExecutionError extends DomainException {\n constructor(\n message: string,\n code: ErrorCodeType = ErrorCode.ACTION_EXECUTION_FAILED,\n context?: Record<string, unknown>,\n ) {\n super({\n code,\n message,\n context,\n });\n this.name = \"ActionExecutionError\";\n }\n}\n\n/**\n * Error thrown when a required entity is not found.\n */\nexport class NotFoundError extends DomainException {\n constructor(\n message: string,\n code: ErrorCodeType = ErrorCode.LORD_NOT_FOUND,\n context?: Record<string, unknown>,\n ) {\n super({\n code,\n message,\n context,\n });\n this.name = \"NotFoundError\";\n }\n}\n\n/**\n * Error thrown when validation fails.\n */\nexport class ValidationError extends DomainException {\n constructor(\n message: string,\n code: ErrorCodeType,\n context?: Record<string, unknown>,\n ) {\n super({\n code,\n message,\n context,\n });\n this.name = \"ValidationError\";\n }\n}\n\n/**\n * Error thrown when undo is requested but no previous state exists.\n */\nexport class UndoError extends DomainException {\n constructor(message = \"No state to undo\", context?: Record<string, unknown>) {\n super({\n code: ErrorCode.UNDO_UNAVAILABLE,\n message,\n context,\n });\n this.name = \"UndoError\";\n }\n}\n\n/**\n * Error thrown when redo is requested but no future state exists.\n */\nexport class RedoError extends DomainException {\n constructor(message = \"No state to redo\", context?: Record<string, unknown>) {\n super({\n code: ErrorCode.REDO_UNAVAILABLE,\n message,\n context,\n });\n this.name = \"RedoError\";\n }\n}\n","import {\n ErrorCode,\n type ErrorCodeType,\n} from \"@core/domain/errors/domainErrors.js\";\n\n/**\n * Translation keys for internationalization support.\n * Use these keys instead of hardcoded strings for translatable content.\n */\nexport const TranslationKey = {\n // Error messages\n ERROR_INVALID_STEP: \"error.invalidStep\",\n ERROR_STEP_EXECUTION_FAILED: \"error.stepExecutionFailed\",\n ERROR_ACTION_EXECUTION_FAILED: \"error.actionExecutionFailed\",\n ERROR_LORD_NOT_FOUND: \"error.lordNotFound\",\n ERROR_PLAYER_NOT_FOUND: \"error.playerNotFound\",\n ERROR_DOMINO_NOT_FOUND: \"error.dominoNotFound\",\n ERROR_MODE_NOT_FOUND: \"error.modeNotFound\",\n ERROR_INVALID_PLACEMENT: \"error.invalidPlacement\",\n ERROR_PLACEMENT_NOT_EMPTY: \"error.placementNotEmpty\",\n ERROR_PLACEMENT_NOT_ADJACENT: \"error.placementNotAdjacent\",\n ERROR_PLACEMENT_INVALID_TERRAIN: \"error.placementInvalidTerrain\",\n ERROR_PLACEMENT_OUT_OF_BOUNDS: \"error.placementOutOfBounds\",\n ERROR_PLACEMENT_EXCEEDS_KINGDOM_SIZE: \"error.placementExceedsKingdomSize\",\n ERROR_NOT_YOUR_TURN: \"error.notYourTurn\",\n ERROR_CANNOT_PICK: \"error.cannotPick\",\n ERROR_CANNOT_PLACE: \"error.cannotPlace\",\n ERROR_DOMINO_ALREADY_PICKED: \"error.dominoAlreadyPicked\",\n ERROR_INVALID_PLAYER_COUNT: \"error.invalidPlayerCount\",\n ERROR_INVALID_PLAYER_NAME: \"error.invalidPlayerName\",\n ERROR_UNDO_UNAVAILABLE: \"error.undoUnavailable\",\n ERROR_REDO_UNAVAILABLE: \"error.redoUnavailable\",\n\n // Game mode names\n MODE_CLASSIC: \"mode.classic\",\n\n // Extra rule names\n RULE_MIDDLE_KINGDOM: \"rule.middleKingdom\",\n RULE_HARMONY: \"rule.harmony\",\n\n // Ground types\n GROUND_CASTLE: \"ground.castle\",\n GROUND_WHEAT: \"ground.wheat\",\n GROUND_FOREST: \"ground.forest\",\n GROUND_SEA: \"ground.sea\",\n GROUND_PLAIN: \"ground.plain\",\n GROUND_SWAMP: \"ground.swamp\",\n GROUND_MINE: \"ground.mine\",\n\n // Game phases\n PHASE_ADD_PLAYERS: \"phase.addPlayers\",\n PHASE_OPTIONS: \"phase.options\",\n PHASE_START: \"phase.start\",\n PHASE_RESULT: \"phase.result\",\n\n // Actions\n ACTION_PICK_DOMINO: \"action.pickDomino\",\n ACTION_PLACE_DOMINO: \"action.placeDomino\",\n ACTION_PASS: \"action.pass\",\n} as const;\n\nexport type TranslationKeyType =\n (typeof TranslationKey)[keyof typeof TranslationKey];\n\n/**\n * Default English translations.\n */\nexport const defaultTranslations: Record<TranslationKeyType, string> = {\n // Error messages\n [TranslationKey.ERROR_INVALID_STEP]: \"Invalid game step\",\n [TranslationKey.ERROR_STEP_EXECUTION_FAILED]: \"Step execution failed\",\n [TranslationKey.ERROR_ACTION_EXECUTION_FAILED]: \"Action execution failed\",\n [TranslationKey.ERROR_LORD_NOT_FOUND]: \"Lord not found\",\n [TranslationKey.ERROR_PLAYER_NOT_FOUND]: \"Player not found\",\n [TranslationKey.ERROR_DOMINO_NOT_FOUND]: \"Domino not found\",\n [TranslationKey.ERROR_MODE_NOT_FOUND]: \"Game mode not found\",\n [TranslationKey.ERROR_INVALID_PLACEMENT]: \"Invalid placement\",\n [TranslationKey.ERROR_PLACEMENT_NOT_EMPTY]: \"Position is not empty\",\n [TranslationKey.ERROR_PLACEMENT_NOT_ADJACENT]:\n \"Not adjacent to existing tiles\",\n [TranslationKey.ERROR_PLACEMENT_INVALID_TERRAIN]:\n \"Terrain type does not match\",\n [TranslationKey.ERROR_PLACEMENT_OUT_OF_BOUNDS]: \"Placement is out of bounds\",\n [TranslationKey.ERROR_PLACEMENT_EXCEEDS_KINGDOM_SIZE]:\n \"Placement exceeds kingdom size\",\n [TranslationKey.ERROR_NOT_YOUR_TURN]: \"It is not your turn\",\n [TranslationKey.ERROR_CANNOT_PICK]: \"Cannot pick a domino now\",\n [TranslationKey.ERROR_CANNOT_PLACE]: \"Cannot place a domino now\",\n [TranslationKey.ERROR_DOMINO_ALREADY_PICKED]:\n \"Domino has already been picked\",\n [TranslationKey.ERROR_INVALID_PLAYER_COUNT]:\n \"Invalid number of players (1-4 required)\",\n [TranslationKey.ERROR_INVALID_PLAYER_NAME]:\n \"Player name must be at least 3 characters\",\n [TranslationKey.ERROR_UNDO_UNAVAILABLE]: \"No state to undo\",\n [TranslationKey.ERROR_REDO_UNAVAILABLE]: \"No state to redo\",\n\n // Game mode names\n [TranslationKey.MODE_CLASSIC]: \"Classic\",\n\n // Extra rule names\n [TranslationKey.RULE_MIDDLE_KINGDOM]: \"The Middle Kingdom\",\n [TranslationKey.RULE_HARMONY]: \"Harmony\",\n\n // Ground types\n [TranslationKey.GROUND_CASTLE]: \"Castle\",\n [TranslationKey.GROUND_WHEAT]: \"Wheat Field\",\n [TranslationKey.GROUND_FOREST]: \"Forest\",\n [TranslationKey.GROUND_SEA]: \"Sea\",\n [TranslationKey.GROUND_PLAIN]: \"Plain\",\n [TranslationKey.GROUND_SWAMP]: \"Swamp\",\n [TranslationKey.GROUND_MINE]: \"Mine\",\n\n // Game phases\n [TranslationKey.PHASE_ADD_PLAYERS]: \"Add Players\",\n [TranslationKey.PHASE_OPTIONS]: \"Game Options\",\n [TranslationKey.PHASE_START]: \"Start Game\",\n [TranslationKey.PHASE_RESULT]: \"Game Results\",\n\n // Actions\n [TranslationKey.ACTION_PICK_DOMINO]: \"Pick Domino\",\n [TranslationKey.ACTION_PLACE_DOMINO]: \"Place Domino\",\n [TranslationKey.ACTION_PASS]: \"Pass\",\n};\n\n/**\n * Maps ErrorCode values to their corresponding TranslationKey values.\n * Used by handlers to translate error codes into localized messages.\n */\nexport const errorCodeToTranslationKey: Record<\n ErrorCodeType,\n TranslationKeyType\n> = {\n [ErrorCode.INVALID_STEP]: TranslationKey.ERROR_INVALID_STEP,\n [ErrorCode.STEP_EXECUTION_FAILED]: TranslationKey.ERROR_STEP_EXECUTION_FAILED,\n [ErrorCode.ACTION_EXECUTION_FAILED]:\n TranslationKey.ERROR_ACTION_EXECUTION_FAILED,\n [ErrorCode.LORD_NOT_FOUND]: TranslationKey.ERROR_LORD_NOT_FOUND,\n [ErrorCode.PLAYER_NOT_FOUND]: TranslationKey.ERROR_PLAYER_NOT_FOUND,\n [ErrorCode.DOMINO_NOT_FOUND]: TranslationKey.ERROR_DOMINO_NOT_FOUND,\n [ErrorCode.MODE_NOT_FOUND]: TranslationKey.ERROR_MODE_NOT_FOUND,\n [ErrorCode.INVALID_PLAYER_COUNT]: TranslationKey.ERROR_INVALID_PLAYER_COUNT,\n [ErrorCode.INVALID_PLAYER_NAME]: TranslationKey.ERROR_INVALID_PLAYER_NAME,\n [ErrorCode.INVALID_PLACEMENT]: TranslationKey.ERROR_INVALID_PLACEMENT,\n [ErrorCode.PLACEMENT_NOT_EMPTY]: TranslationKey.ERROR_PLACEMENT_NOT_EMPTY,\n [ErrorCode.PLACEMENT_NOT_ADJACENT]:\n TranslationKey.ERROR_PLACEMENT_NOT_ADJACENT,\n [ErrorCode.PLACEMENT_INVALID_TERRAIN]:\n TranslationKey.ERROR_PLACEMENT_INVALID_TERRAIN,\n [ErrorCode.PLACEMENT_OUT_OF_BOUNDS]:\n TranslationKey.ERROR_PLACEMENT_OUT_OF_BOUNDS,\n [ErrorCode.PLACEMENT_EXCEEDS_KINGDOM_SIZE]:\n TranslationKey.ERROR_PLACEMENT_EXCEEDS_KINGDOM_SIZE,\n [ErrorCode.NOT_YOUR_TURN]: TranslationKey.ERROR_NOT_YOUR_TURN,\n [ErrorCode.CANNOT_PICK]: TranslationKey.ERROR_CANNOT_PICK,\n [ErrorCode.CANNOT_PLACE]: TranslationKey.ERROR_CANNOT_PLACE,\n [ErrorCode.DOMINO_ALREADY_PICKED]: TranslationKey.ERROR_DOMINO_ALREADY_PICKED,\n [ErrorCode.UNDO_UNAVAILABLE]: TranslationKey.ERROR_UNDO_UNAVAILABLE,\n [ErrorCode.REDO_UNAVAILABLE]: TranslationKey.ERROR_REDO_UNAVAILABLE,\n};\n\n/**\n * Translates an error code to a localized message.\n * Convenience function combining errorCodeToTranslationKey lookup and translation.\n */\nexport const translateErrorCode = (\n translator: Translator,\n code: ErrorCodeType,\n params?: Record<string, string | number>,\n): string => {\n const key = errorCodeToTranslationKey[code];\n return translator.t(key, params);\n};\n\n/**\n * Translator interface for custom translations.\n */\nexport interface Translator {\n /**\n * Translate a key to the current language.\n * @param key - The translation key\n * @param params - Optional parameters for interpolation\n * @returns The translated string\n */\n t(key: TranslationKeyType, params?: Record<string, string | number>): string;\n}\n\n/**\n * Creates a translator with the provided translations.\n * Falls back to default English translations for missing keys.\n *\n * @param translations - Custom translations to use\n * @returns A translator instance\n */\nexport const createTranslator = (\n translations: Partial<Record<TranslationKeyType, string>> = {},\n): Translator => {\n const mergedTranslations = { ...defaultTranslations, ...translations };\n\n return {\n t(\n key: TranslationKeyType,\n params?: Record<string, string | number>,\n ): string {\n let text = mergedTranslations[key] || key;\n\n // Simple parameter interpolation: {{param}}\n if (params) {\n for (const [paramKey, value] of Object.entries(params)) {\n text = text.replace(\n new RegExp(`\\\\{\\\\{${paramKey}\\\\}\\\\}`, \"g\"),\n String(value),\n );\n }\n }\n\n return text;\n },\n };\n};\n\n/**\n * Default translator using English translations.\n */\nexport const defaultTranslator: Translator = createTranslator();\n","export type Result<T> = Ok<T> | Err;\n\nexport interface Ok<T> {\n readonly tag: \"Ok\";\n readonly value: T;\n}\n\nexport interface Err {\n readonly tag: \"Err\";\n readonly error: string;\n}\n\nexport const ok = <T>(value: T): Ok<T> => ({ tag: \"Ok\", value });\nexport const err = (error: string): Err => ({ tag: \"Err\", error });\n\nexport const isOk = <T>(result: Result<T>): result is Ok<T> =>\n result.tag === \"Ok\";\nexport const isErr = <T>(result: Result<T>): result is Err =>\n result.tag === \"Err\";\n\nexport const unwrap = <T>(result: Ok<T> | Err): T => {\n if (result.tag === \"Err\") {\n throw new Error(result.error);\n }\n return result.value;\n};\n","import type { AddExtraRulesCommand } from \"@application/commands/addExtraRulesCommand.js\";\nimport {\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n StepExecutionError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameWithNextStep,\n isGameWithNextStep,\n} from \"@core/domain/types/game.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport { translateErrorCode } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { AddExtraRulesUseCase } from \"@core/useCases/addExtraRules.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype AddExtraRulesHandler = (command: AddExtraRulesCommand) => GameWithNextStep;\n\nexport const addExtraRulesHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: AddExtraRulesUseCase,\n ): AddExtraRulesHandler =>\n (command: AddExtraRulesCommand) => {\n const { game, extraRules } = command;\n logger.info(`Adding extra rules to game: ${game.id}`);\n logger.info(`Extra rules: ${extraRules}`);\n\n if (!isGameWithNextStep(game)) {\n logger.error(\n `Invalid game, required nextAction type: 'step' but got: ${game.nextAction.type}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n { expected: \"step\", actual: game.nextAction.type, gameId: game.id },\n );\n }\n\n if (game.nextAction.step !== \"options\") {\n logger.error(\n `Required game with options step but got: ${game.nextAction.step}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n { expected: \"options\", actual: game.nextAction.step, gameId: game.id },\n );\n }\n\n const result = useCase(game, extraRules);\n\n if (isErr(result)) {\n logger.error(`Error adding extra rules: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new StepExecutionError(translateErrorCode(translator, code), code, {\n gameId: game.id,\n extraRules: command.extraRules,\n });\n }\n\n logger.info(`Extra rules added to game: ${game.id}`);\n return result.value;\n };\n","import type { AddPlayersCommand } from \"@application/commands/addPlayersCommand.js\";\nimport {\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n StepExecutionError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameWithNextStep,\n isGameWithNextStep,\n} from \"@core/domain/types/game.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport { translateErrorCode } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { AddPlayersUseCase } from \"@core/useCases/addPlayers.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype AddPlayersHandler = (command: AddPlayersCommand) => GameWithNextStep;\n\nexport const addPlayersHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: AddPlayersUseCase,\n ): AddPlayersHandler =>\n (command: AddPlayersCommand) => {\n const { game, players } = command;\n\n logger.info(`Adding players to game: ${game.id}`);\n\n if (!isGameWithNextStep(game)) {\n logger.error(\n `Invalid game, required nextAction type: 'step' but got: ${game.nextAction.type}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n { expected: \"step\", actual: game.nextAction.type, gameId: game.id },\n );\n }\n\n if (game.nextAction.step !== \"addPlayers\") {\n logger.error(\n `Required game with addPlayers step but got: ${game.nextAction.step}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"addPlayers\",\n actual: game.nextAction.step,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(game, players);\n\n if (isErr(result)) {\n logger.error(`Error adding players: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new StepExecutionError(translateErrorCode(translator, code), code, {\n gameId: game.id,\n players: command.players,\n });\n }\n\n logger.info(`Players added to game: ${game.id}`);\n return result.value;\n };\n","import type { CalculateScoreCommand } from \"@application/commands/calculateScoreCommand.js\";\nimport type { Score } from \"@core/domain/types/game.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { CalculateScoreUseCase } from \"@core/useCases/calculateScore.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype CalculateScoreHandler = (command: CalculateScoreCommand) => Score;\n\nexport const calculateScoreHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: CalculateScoreUseCase,\n ): CalculateScoreHandler =>\n (command) => {\n const { kingdom } = command;\n logger.info(`Calculating score for kingdom`);\n const result = useCase(kingdom);\n\n if (isErr(result)) {\n logger.error(`Error calculating score: ${result.error}`);\n throw new Error(result.error);\n }\n\n logger.info(`Score calculated: ${result.value}`);\n return result.value;\n };\n","import type { CanPlaceDominoCommand } from \"@application/commands/canPlaceDominoCommand.js\";\nimport type { Domino, Kingdom } from \"@core/domain/types/index.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\n\ntype CanPlaceDominoUseCase = (\n kingdom: Kingdom,\n domino: Domino,\n maxKingdomSize?: number,\n) => boolean;\n\ntype CanPlaceDominoHandler = (command: CanPlaceDominoCommand) => boolean;\n\n/**\n * Creates a handler for checking if a domino can be placed.\n */\nexport const canPlaceDominoHandler = (\n logger: Logger,\n translator: Translator,\n useCase: CanPlaceDominoUseCase,\n): CanPlaceDominoHandler => {\n return (command) => {\n logger.info(`Checking if domino ${command.domino.number} can be placed`);\n const canPlace = useCase(\n command.kingdom,\n command.domino,\n command.maxKingdomSize,\n );\n logger.info(`Can place domino: ${canPlace}`);\n return canPlace;\n };\n};\n","import type { ChooseDominoCommand } from \"@application/commands/chooseDominoCommand.js\";\nimport {\n ActionExecutionError,\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameWithNextAction,\n isGameWithNextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport { translateErrorCode } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { ChooseDominoUseCase } from \"@core/useCases/chooseDomino.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype ChooseDominoHandler = (command: ChooseDominoCommand) => GameWithNextAction;\n\nexport const chooseDominoHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: ChooseDominoUseCase,\n ): ChooseDominoHandler =>\n (command: ChooseDominoCommand) => {\n const { game, lordId, dominoPick } = command;\n logger.info(\n `Choosing domino: ${dominoPick} for lord: ${lordId} in game: ${game.id}`,\n );\n\n if (!isGameWithNextAction(game)) {\n logger.error(\n `Invalid game, required nextAction type: 'action' but got: ${game.nextAction.type}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n { expected: \"action\", actual: game.nextAction.type, gameId: game.id },\n );\n }\n\n if (game.nextAction.nextAction !== \"pickDomino\") {\n logger.error(\n `Required game with pickDomino action but got: ${game.nextAction.nextAction}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"pickDomino\",\n actual: game.nextAction.nextAction,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(game, lordId, dominoPick);\n\n if (isErr(result)) {\n logger.error(`Error choosing domino: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new ActionExecutionError(\n translateErrorCode(translator, code),\n code,\n {\n gameId: game.id,\n lordId: command.lordId,\n dominoPick: command.dominoPick,\n },\n );\n }\n\n logger.info(\n `Domino chosen: ${dominoPick} for lord: ${lordId} in game: ${game.id}`,\n );\n return result.value;\n };\n","import type { CreateGameCommand } from \"@application/commands/createGameCommand.js\";\nimport {\n type ErrorCodeType,\n StepExecutionError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { GameWithNextStep } from \"@core/domain/types/game.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport { translateErrorCode } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { CreateGameUseCase } from \"@core/useCases/createGame.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype CreateGameHandler = (command: CreateGameCommand) => GameWithNextStep;\n\nexport const createGameHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: CreateGameUseCase,\n ): CreateGameHandler =>\n (command: CreateGameCommand) => {\n logger.info(`Creating game with mode: ${command.mode}`);\n const result = useCase(command.mode, command.seed);\n\n if (isErr(result)) {\n logger.error(`Error creating game: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new StepExecutionError(translateErrorCode(translator, code), code, {\n mode: command.mode,\n });\n }\n\n logger.info(`Game created: ${result.value.id}`);\n return result.value;\n };\n","import type { DiscardDominoCommand } from \"@application/commands/discardDominoCommand.js\";\nimport {\n ActionExecutionError,\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameState,\n isGameWithNextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport { translateErrorCode } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { DiscardDominoUseCase } from \"@core/useCases/discardDomino.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype DiscardDominoHandler = (command: DiscardDominoCommand) => GameState;\n\nexport const discardDominoHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: DiscardDominoUseCase,\n ): DiscardDominoHandler =>\n (command: DiscardDominoCommand) => {\n const { game, lordId } = command;\n logger.info(`Discarding domino for lord: ${lordId} in game: ${game.id}`);\n\n if (!isGameWithNextAction(game)) {\n logger.error(\n `Invalid game, required nextAction type: 'action' but got: ${game.nextAction.type}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n { expected: \"action\", actual: game.nextAction.type, gameId: game.id },\n );\n }\n\n if (game.nextAction.nextAction !== \"placeDomino\") {\n logger.error(\n `Required game with placeDomino action but got: ${game.nextAction.nextAction}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"placeDomino\",\n actual: game.nextAction.nextAction,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(game, lordId);\n\n if (isErr(result)) {\n logger.error(`Error discarding domino: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new ActionExecutionError(\n translateErrorCode(translator, code),\n code,\n { gameId: game.id, lordId: command.lordId },\n );\n }\n\n if (isGameWithNextAction(result.value)) {\n logger.info(`Domino discarded: ${lordId} in game: ${game.id}`);\n return result.value;\n }\n\n logger.info(`Domino discarded: ${lordId} in game: ${game.id}`);\n return result.value;\n };\n","import type { GetDynastyResultCommand } from \"@application/commands/getDynastyResultCommand.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type {\n DynastyResult,\n GetDynastyResultUseCase,\n} from \"@core/useCases/getDynastyResult.js\";\n\ntype GetDynastyResultHandler = (\n command: GetDynastyResultCommand,\n) => DynastyResult[];\n\nexport const getDynastyResultHandler = (\n logger: Logger,\n translator: Translator,\n useCase: GetDynastyResultUseCase,\n): GetDynastyResultHandler => {\n return (command) => {\n logger.info(\n `Calculating dynasty results for ${command.games.length} games`,\n );\n const results = useCase(command.games);\n logger.info(`Dynasty results calculated`);\n return results;\n };\n};\n","import type { GetExtraRulesCommand } from \"@application/commands/getExtraRulesCommand.js\";\nimport {\n ErrorCode,\n type ErrorCodeType,\n NotFoundError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { ExtraRule } from \"@core/domain/types/rule.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport { translateErrorCode } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { GetExtraRulesUseCase } from \"@core/useCases/getExtraRules.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype GetExtraRulesHandler = (command: GetExtraRulesCommand) => ExtraRule[];\n\nexport const getExtraRulesHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: GetExtraRulesUseCase,\n ): GetExtraRulesHandler =>\n (command: GetExtraRulesCommand) => {\n const { mode, players } = command;\n logger.info(\n `Getting extra rules for mode: ${mode} and players: ${players}`,\n );\n const result = useCase(mode, players);\n\n if (isErr(result)) {\n logger.error(`Error getting extra rules: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new NotFoundError(translateErrorCode(translator, code), code, {\n mode: command.mode,\n });\n }\n\n logger.info(`Extra rules retrieved: ${result.value}`);\n return result.value;\n };\n","import type { GetModesCommand } from \"@application/commands/getModesCommand.js\";\nimport {\n ErrorCode,\n type ErrorCodeType,\n NotFoundError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { GameMode } from \"@core/domain/types/mode.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport { translateErrorCode } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { GetModesUseCase } from \"@core/useCases/getModes.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype GetModesHandler = (command: GetModesCommand) => GameMode[];\n\nexport const getModesHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: GetModesUseCase,\n ): GetModesHandler =>\n (_command: GetModesCommand) => {\n logger.info(\"Getting modes\");\n const result = useCase();\n\n if (isErr(result)) {\n logger.error(`Error getting modes: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new NotFoundError(translateErrorCode(translator, code), code);\n }\n\n logger.info(`Modes retrieved: ${result.value}`);\n return result.value;\n };\n","import type { GetResultCommand } from \"@application/commands/getResultCommand.js\";\nimport {\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n NotFoundError,\n StepExecutionError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameWithResults,\n isGameWithNextStep,\n type ScoreResult,\n} from \"@core/domain/types/game.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport { translateErrorCode } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { CalculateScoreUseCase } from \"@core/useCases/calculateScore.js\";\nimport type { GetResultUseCase } from \"@core/useCases/getResult.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype GetResultHandler = (command: GetResultCommand) => GameWithResults;\n\nexport const getResultHandler =\n (\n logger: Logger,\n translator: Translator,\n useCases: {\n getResultUseCase: GetResultUseCase;\n calculateScoreUseCase: CalculateScoreUseCase;\n },\n ): GetResultHandler =>\n (command: GetResultCommand) => {\n const { getResultUseCase, calculateScoreUseCase } = useCases;\n const { game } = command;\n logger.info(`Getting result for game: ${game.id}`);\n\n if (!isGameWithNextStep(game)) {\n logger.error(\n `Invalid game, required nextAction type: 'step' but got: ${game.nextAction.type}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n { expected: \"step\", actual: game.nextAction.type, gameId: game.id },\n );\n }\n\n if (game.nextAction.step !== \"result\") {\n logger.error(\n `Required game with result step but got: ${game.nextAction.step}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n { expected: \"result\", actual: game.nextAction.step, gameId: game.id },\n );\n }\n\n const { players } = game;\n\n const scoreResult: ScoreResult[] = players.map((player) => {\n const { kingdom } = player;\n const result = calculateScoreUseCase(kingdom);\n\n if (isErr(result)) {\n logger.error(`Error when calculating score: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new StepExecutionError(\n translateErrorCode(translator, code),\n code,\n {\n gameId: game.id,\n },\n );\n }\n\n return {\n playerId: player.id,\n playerName: player.name,\n details: {\n ...result.value,\n },\n };\n });\n\n const result = getResultUseCase(game, scoreResult);\n\n if (isErr(result)) {\n logger.error(`Error getting result: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new NotFoundError(translateErrorCode(translator, code), code, {\n gameId: game.id,\n });\n }\n\n logger.info(`Result retrieved for game: ${game.id}`);\n return result.value;\n };\n","import type { GetValidPlacementsCommand } from \"@application/commands/getValidPlacementsCommand.js\";\nimport type { Domino, Kingdom } from \"@core/domain/types/index.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { ValidPlacement } from \"@core/useCases/getValidPlacements.js\";\n\ntype GetValidPlacementsUseCase = (\n kingdom: Kingdom,\n domino: Domino,\n maxKingdomSize?: number,\n) => ValidPlacement[];\n\ntype GetValidPlacementsHandler = (\n command: GetValidPlacementsCommand,\n) => ValidPlacement[];\n\n/**\n * Creates a handler for getting valid placements.\n */\nexport const getValidPlacementsHandler = (\n logger: Logger,\n translator: Translator,\n useCase: GetValidPlacementsUseCase,\n): GetValidPlacementsHandler => {\n return (command) => {\n logger.info(\n `Getting valid placements for domino: ${command.domino.number}`,\n );\n const placements = useCase(\n command.kingdom,\n command.domino,\n command.maxKingdomSize,\n );\n logger.info(`Found ${placements.length} valid placements`);\n return placements;\n };\n};\n","import type { PlaceDominoCommand } from \"@application/commands/placeDominoCommand.js\";\nimport {\n ActionExecutionError,\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameState,\n isGameWithNextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport { translateErrorCode } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { PlaceDominoUseCase } from \"@core/useCases/placeDomino.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype PlaceDominoHandler = (command: PlaceDominoCommand) => GameState;\n\nexport const placeDominoHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: PlaceDominoUseCase,\n ): PlaceDominoHandler =>\n (command: PlaceDominoCommand) => {\n const { game, lordId, position, rotation } = command;\n logger.info(\n `Placing domino: ${lordId} in position: ${JSON.stringify(\n position,\n )} with rotation: ${rotation} in game: ${game.id}`,\n );\n\n if (!isGameWithNextAction(game)) {\n logger.error(\n `Invalid game, required nextAction type: 'action' but got: ${game.nextAction.type}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n { expected: \"action\", actual: game.nextAction.type, gameId: game.id },\n );\n }\n\n if (game.nextAction.nextAction !== \"placeDomino\") {\n logger.error(\n `Required game with placeDomino action but got: ${game.nextAction.nextAction}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"placeDomino\",\n actual: game.nextAction.nextAction,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(game, lordId, position, rotation);\n\n if (isErr(result)) {\n logger.error(`Error placing domino: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new ActionExecutionError(\n translateErrorCode(translator, code),\n code,\n {\n gameId: game.id,\n lordId: command.lordId,\n position: command.position,\n rotation: command.rotation,\n },\n );\n }\n\n if (isGameWithNextAction(result.value)) {\n logger.info(\n `Domino placed: ${lordId} in position: ${JSON.stringify(\n position,\n )} with rotation: ${rotation} in game: ${game.id}`,\n );\n return result.value;\n }\n\n logger.info(\n `Domino placed: ${lordId} in position: ${JSON.stringify(\n position,\n )} with rotation: ${rotation} in game: ${game.id}`,\n );\n return result.value;\n };\n","import type { GameState } from \"@core/domain/types/index.js\";\nimport { ok, err, type Result } from \"@utils/result.js\";\n\n/**\n * Serialization format version for backwards compatibility.\n */\nconst SERIALIZATION_VERSION = 1;\n\n/**\n * Serialized game data structure.\n */\ninterface SerializedGame {\n version: number;\n data: GameState;\n timestamp: string;\n}\n\n/**\n * Serializes a game state to a JSON string.\n * The serialized string includes version information for future compatibility.\n *\n * @param game - The game state to serialize\n * @returns JSON string representation of the game\n */\nexport const serializeGame = (game: GameState): string => {\n const serialized: SerializedGame = {\n version: SERIALIZATION_VERSION,\n data: game,\n timestamp: new Date().toISOString(),\n };\n return JSON.stringify(serialized);\n};\n\n/**\n * Deserializes a JSON string back to a game state.\n * Validates the structure and version before returning.\n *\n * @param json - The JSON string to deserialize\n * @returns Result containing the game state or an error\n */\nexport const deserializeGame = (json: string): Result<GameState> => {\n try {\n const parsed = JSON.parse(json) as SerializedGame;\n\n // Validate structure\n if (!parsed.version || !parsed.data) {\n return err(\"Invalid serialized game format\");\n }\n\n // Check version compatibility\n if (parsed.version > SERIALIZATION_VERSION) {\n return err(\n `Unsupported serialization version: ${parsed.version}. Current version: ${SERIALIZATION_VERSION}`\n );\n }\n\n // Validate essential game properties\n const game = parsed.data;\n if (!game.id || !game.players || !game.lords || !game.nextAction) {\n return err(\"Invalid game state structure\");\n }\n\n return ok(game);\n } catch (error) {\n return err(`Failed to parse game JSON: ${(error as Error).message}`);\n }\n};\n\n/**\n * Creates a save point for the current game state.\n * Includes metadata for debugging and restore purposes.\n */\nexport interface GameSavePoint {\n /** Serialized game data */\n serialized: string;\n /** When the save was created */\n createdAt: string;\n /** Game ID for reference */\n gameId: string;\n /** Current turn number */\n turn: number;\n}\n\n/**\n * Creates a save point from a game state.\n *\n * @param game - The game state to save\n * @returns A save point object with metadata\n */\nexport const createSavePoint = (game: GameState): GameSavePoint => {\n return {\n serialized: serializeGame(game),\n createdAt: new Date().toISOString(),\n gameId: game.id,\n turn: game.turn,\n };\n};\n\n/**\n * Restores a game state from a save point.\n *\n * @param savePoint - The save point to restore from\n * @returns Result containing the restored game state or an error\n */\nexport const restoreFromSavePoint = (\n savePoint: GameSavePoint\n): Result<GameState> => {\n return deserializeGame(savePoint.serialized);\n};\n","import type {\n DeserializeGameCommand,\n SerializeGameCommand,\n} from \"@application/commands/serializeGameCommand.js\";\nimport {\n type ErrorCodeType,\n StepExecutionError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { GameState } from \"@core/domain/types/index.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport { translateErrorCode } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport {\n deserializeGame,\n serializeGame,\n} from \"@core/useCases/serialization.js\";\nimport { isErr, unwrap } from \"@utils/result.js\";\n\ntype SerializeGameHandler = (command: SerializeGameCommand) => string;\ntype DeserializeGameHandler = (command: DeserializeGameCommand) => GameState;\n\n/**\n * Creates a handler for serializing game state.\n */\nexport const serializeGameHandler = (\n logger: Logger,\n _translator: Translator,\n): SerializeGameHandler => {\n return (command) => {\n logger.info(`Serializing game: ${command.game.id}`);\n const serialized = serializeGame(command.game);\n logger.info(`Game serialized successfully`);\n return serialized;\n };\n};\n\n/**\n * Creates a handler for deserializing game state.\n */\nexport const deserializeGameHandler = (\n logger: Logger,\n translator: Translator,\n): DeserializeGameHandler => {\n return (command) => {\n logger.info(`Deserializing game from JSON`);\n const result = deserializeGame(command.json);\n\n if (isErr(result)) {\n logger.error(`Failed to deserialize game: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new StepExecutionError(translateErrorCode(translator, code), code);\n }\n\n const game = unwrap(result);\n logger.info(`Game deserialized successfully: ${game.id}`);\n return game;\n };\n};\n","import type { StartGameCommand } from \"@application/commands/startGameCommand.js\";\nimport {\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n StepExecutionError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameWithNextAction,\n isGameWithNextStep,\n} from \"@core/domain/types/game.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport { translateErrorCode } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { StartGameUseCase } from \"@core/useCases/startGame.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype StartGameHandler = (command: StartGameCommand) => GameWithNextAction;\n\nexport const startGameHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: StartGameUseCase,\n ): StartGameHandler =>\n (command: StartGameCommand) => {\n const { game } = command;\n logger.info(`Starting game: ${game.id}`);\n\n if (!isGameWithNextStep(game)) {\n logger.error(\n `Invalid game, required nextAction type: 'step' but got: ${game.nextAction.type}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n { expected: \"step\", actual: game.nextAction.type, gameId: game.id },\n );\n }\n\n if (\n game.nextAction.step !== \"start\" &&\n game.nextAction.step !== \"options\"\n ) {\n logger.error(\n `Required game with start step or options step but got: ${game.nextAction.step}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"start|options\",\n actual: game.nextAction.step,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(game);\n\n if (isErr(result)) {\n logger.error(`Error starting game: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new StepExecutionError(translateErrorCode(translator, code), code, {\n gameId: game.id,\n });\n }\n\n logger.info(`Game started: ${game.id}`);\n return result.value;\n };\n","import type { EmptyTile, Tile } from \"./domino.js\";\n\n/**\n * Represents a position on the kingdom grid.\n * Origin (0,0) is at the top-left corner.\n */\nexport type Position = {\n /** Column index (0-8, left to right) */\n x: number;\n /** Row index (0-8, top to bottom) */\n y: number;\n};\n\n/**\n * Rotation angle for domino placement.\n * - 0: Horizontal, left tile at position, right tile to the east\n * - 90: Vertical, left tile at position, right tile to the south\n * - 180: Horizontal, right tile at position, left tile to the east\n * - 270: Vertical, right tile at position, left tile to the south\n */\nexport type Rotation = 0 | 90 | 180 | 270;\n\n/**\n * Represents a player's kingdom as a 2D grid of tiles.\n * The grid is 9x9 to allow for the 5x5 maximum kingdom size\n * with the castle at any position.\n */\nexport type Kingdom = (Tile | EmptyTile)[][];\n\n/**\n * The size of the kingdom grid (9x9).\n * This allows for a 5x5 kingdom with the castle placed anywhere.\n */\nexport const GRIDSIZE = 9;\n\n/**\n * Maximum kingdom size (5x5 in standard rules, 7x7 for Mighty Duel).\n */\nexport const MAX_KINGDOM_SIZE = 5;\n","/**\n * All possible ground/terrain types in Kingdomino.\n * Each type can form contiguous properties for scoring.\n */\nexport const GROUND = [\n \"castle\",\n \"wheat\",\n \"forest\",\n \"sea\",\n \"plain\",\n \"swamp\",\n \"mine\",\n] as const;\n\n/** Union type of all terrain types */\nexport type Ground = (typeof GROUND)[number];\n\n/** Special ground type for empty/unplaced tiles */\nexport type EmptyGround = \"empty\";\n\n/** Number of crowns on a tile (0-3) */\nexport type Crown = number;\n\n/**\n * Represents a single tile with terrain and crowns.\n * Two tiles form a domino.\n */\nexport type Tile = {\n /** The terrain type of this tile */\n type: Ground;\n /** Number of crowns (0-3), multiplier for scoring */\n crowns: Crown;\n};\n\n/**\n * Represents an empty/unplaced tile on the kingdom grid.\n */\nexport type EmptyTile = {\n /** Always \"empty\" for unplaced tiles */\n type: EmptyGround;\n /** Empty tiles have no crowns */\n crowns: 0;\n};\n\n/**\n * Represents a domino piece consisting of two connected tiles.\n * Dominoes are the main game pieces that players place on their kingdoms.\n */\nexport type Domino = {\n /** The left tile of the domino */\n left: Tile;\n /** The right tile of the domino */\n right: Tile;\n /** Unique number identifying this domino (1-48 in Classic mode) */\n number: number;\n};\n\n/**\n * Represents a domino that has been revealed for player selection.\n * Contains selection state for the current turn.\n */\nexport type RevealsDomino = {\n /** The actual domino piece */\n domino: Domino;\n /** Whether this domino has been picked by a lord */\n picked: boolean;\n /** ID of the lord who picked this domino, or null if unpicked */\n lordId: string | null;\n /** Display position in the revealed set (for UI ordering) */\n position: number;\n};\n","import type { Kingdom } from \"./kingdom.js\";\nimport type { ObjectValues } from \"./utils.js\";\n\n/**\n * Represents a player in the game.\n */\nexport type Player = {\n /** Unique identifier for the player */\n id: string;\n /** Display name of the player */\n name: string;\n /** The player's kingdom grid where dominoes are placed */\n kingdom: Kingdom;\n /** If set, this player is controlled by a bot with the named strategy */\n bot?: { strategyName: string };\n};\n\n/**\n * Payload for creating a new player.\n */\nexport type PlayerPayload = {\n /** Display name for the player (minimum 3 characters) */\n name: string;\n};\n\n/** Array of player creation payloads */\nexport type PlayersPayload = PlayerPayload[];\n\n/** Array of players */\nexport type Players = Player[];\n\n/**\n * Available actions a player can perform during their turn.\n */\nexport const playerActions = {\n /** Place a previously picked domino on the kingdom */\n placeDomino: \"placeDomino\",\n /** Pick a domino from the revealed set */\n pickDomino: \"pickDomino\",\n /** Pass/discard when no valid placement exists */\n pass: \"pass\",\n} as const;\n\n/** Union type of all player actions */\nexport type PlayerActions = ObjectValues<typeof playerActions>;\n","import { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type { ExtraRule } from \"@core/domain/types/rule.js\";\nimport { ok, err, type Result } from \"@utils/result.js\";\n\nexport const getAvailablesExtraRules = (\n extraRules: ExtraRule[],\n mode: string,\n numberOfPlayers: number\n): Result<ExtraRule[]> => {\n const availableExtraRules = extraRules.filter((rule) => {\n return (\n rule.mode.filter((m) => m.name === mode).length > 0 &&\n (!rule.playersLimit || rule.playersLimit === numberOfPlayers)\n );\n });\n\n if (availableExtraRules.length === 0) {\n return err(ErrorCode.STEP_EXECUTION_FAILED);\n }\n\n return ok(availableExtraRules);\n};\n\nexport const toExtraRule = (\n rule: string,\n extraRules: ExtraRule[]\n): Result<ExtraRule> => {\n const foundRule = extraRules.find((r) => r.name === rule);\n\n if (!foundRule) {\n return err(ErrorCode.STEP_EXECUTION_FAILED);\n }\n\n return ok(foundRule);\n};\n","import type { ShuffleMethod } from \"@core/portServerside/shuffleMethod.js\";\n\nconst hashSeed = (str: string): number => {\n let hash = 2166136261;\n for (let i = 0; i < str.length; i++) {\n hash ^= str.charCodeAt(i);\n hash = Math.imul(hash, 16777619);\n }\n return hash >>> 0;\n};\n\nconst mulberry32 = (seed: number): (() => number) => {\n let state = seed;\n return () => {\n state |= 0;\n state = (state + 0x6d2b79f5) | 0;\n let t = Math.imul(state ^ (state >>> 15), 1 | state);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n};\n\nexport const createSeededShuffle = (\n seed: string,\n salt: string\n): ShuffleMethod => {\n const numericSeed = hashSeed(`${seed}|${salt}`);\n const random = mulberry32(numericSeed);\n\n return <T>(array: T[]): T[] => {\n const result = [...array];\n for (let i = result.length - 1; i > 0; i--) {\n const j = Math.floor(random() * (i + 1));\n [result[i], result[j]] = [result[j] as T, result[i] as T];\n }\n return result;\n };\n};\n","import {\n gameSteps,\n type ExtraRule,\n type GameWithNextStep,\n type NextStep,\n} from \"@core/domain/types/index.js\";\nimport { isErr, ok, type Result } from \"@utils/result.js\";\nimport type { RuleRepository } from \"@core/portServerside/ruleRepository.js\";\nimport type { DominoesRepository } from \"@core/portServerside/dominoesRepository.js\";\nimport type { ShuffleMethod } from \"@core/portServerside/shuffleMethod.js\";\nimport { toExtraRule } from \"@core/domain/entities/rule.js\";\nimport { createSeededShuffle } from \"@utils/seededShuffle.js\";\n\nexport type AddExtraRulesUseCase = (\n game: GameWithNextStep,\n rules: string[]\n) => Result<GameWithNextStep>;\n\nexport const addExtraRulesUseCase =\n (deps: {\n ruleRepository: RuleRepository;\n dominoesRepository: DominoesRepository;\n shuffleMethod: ShuffleMethod;\n }): AddExtraRulesUseCase =>\n (game, rules) => {\n const { ruleRepository, dominoesRepository, shuffleMethod } = deps;\n const availableExtraRules = ruleRepository.getAllExtra();\n\n const newExtraRules: ExtraRule[] = [];\n\n for (const rule of rules) {\n const result = toExtraRule(rule, availableExtraRules);\n\n if (isErr(result)) {\n return result;\n }\n\n newExtraRules.push(result.value);\n }\n\n // The Mighty Duel overrides basic rules for 2-player games\n let updatedBasic = game.rules.basic;\n let updatedDominoes = game.dominoes;\n const hasMightyDuel = newExtraRules.some((r) => r.name === \"The Mighty Duel\");\n if (hasMightyDuel) {\n updatedBasic = {\n ...updatedBasic,\n maxDominoes: 48,\n maxTurns: 12,\n maxKingdomSize: 7,\n };\n // Reload and shuffle all 48 dominoes\n const allDominoes = dominoesRepository.getForMode(game.mode);\n if (allDominoes) {\n const shuffle = game.seed\n ? createSeededShuffle(game.seed, \"mighty-duel\")\n : shuffleMethod;\n updatedDominoes = shuffle(allDominoes);\n }\n }\n\n const updatedRules = {\n basic: updatedBasic,\n extra: newExtraRules,\n };\n\n const next: NextStep = {\n type: \"step\",\n step: gameSteps.start,\n };\n\n const updatedGame: GameWithNextStep = {\n ...game,\n dominoes: updatedDominoes,\n rules: updatedRules,\n nextAction: next,\n };\n\n return ok(updatedGame);\n };\n","import {\n GROUND,\n type Crown,\n type EmptyGround,\n type EmptyTile,\n type Ground,\n type Tile,\n} from \"@core/domain/types/domino.js\";\n\nconst isGround = (ground: any): ground is Ground => {\n return GROUND.includes(ground);\n};\n\nexport const createTile = (\n ground: Ground | EmptyGround,\n crowns: Crown = 0\n): Tile | EmptyTile => {\n if (isGround(ground)) {\n return { type: ground, crowns } as Tile;\n }\n return { type: ground, crowns: 0 } as EmptyTile;\n};\n","import {\n type Domino,\n type EmptyTile,\n GRIDSIZE,\n MAX_KINGDOM_SIZE,\n type Kingdom,\n type Position,\n type Rotation,\n type Tile,\n} from \"@core/domain/types/index.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport {err, isErr, isOk, ok, type Result} from \"@utils/result.js\";\nimport {createTile} from \"./domino.js\";\n\nexport const createEmptyKingdom = (): Kingdom => {\n const emptyTile = createTile(\"empty\");\n return Array.from({length: GRIDSIZE}, () =>\n Array.from({length: GRIDSIZE}, () => emptyTile)\n );\n};\n\nexport const placeCastle = (kingdom: Kingdom): Kingdom => {\n const castle = createTile(\"castle\");\n const newKingdom = deepCopyKingdom(kingdom);\n newKingdom[4]![4] = castle;\n return newKingdom;\n};\n\nexport const placeTile = (\n kingdom: Kingdom,\n position: Position,\n tile: Tile\n): Kingdom => {\n const newKingdom = deepCopyKingdom(kingdom);\n newKingdom[position.y]![position.x] = tile;\n return newKingdom;\n};\n\nexport const getTile = (\n kingdom: Kingdom,\n position: Position\n): Result<Tile | EmptyTile> => {\n const tile = kingdom[position.y]?.[position.x];\n if (!tile) {\n return err(ErrorCode.PLACEMENT_OUT_OF_BOUNDS);\n }\n return ok(tile);\n};\n\nexport const calculateDominoPosition = (\n position: Position,\n rotation: Rotation,\n domino: Domino\n): [{ tile: Tile; position: Position }, { tile: Tile; position: Position }] => {\n let firstTile: {\n tile: Tile;\n position: Position;\n };\n let secondTile: {\n tile: Tile;\n position: Position;\n };\n\n switch (rotation) {\n case 0: // horizontal, left to right\n firstTile = {\n tile: domino.left,\n position: {\n x: position.x,\n y: position.y,\n },\n };\n secondTile = {\n tile: domino.right,\n position: {\n x: position.x + 1,\n y: position.y,\n },\n };\n break;\n case 90: // vertical, top to bottom\n firstTile = {\n tile: domino.left,\n position: {\n x: position.x,\n y: position.y,\n },\n };\n secondTile = {\n tile: domino.right,\n position: {\n x: position.x,\n y: position.y + 1,\n },\n };\n break;\n case 180: // horizontal, right to left\n firstTile = {\n tile: domino.right,\n position: {\n x: position.x,\n y: position.y,\n },\n };\n secondTile = {\n tile: domino.left,\n position: {\n x: position.x + 1,\n y: position.y,\n },\n };\n break;\n case 270: // vertical, bottom to top\n firstTile = {\n tile: domino.right,\n position: {\n x: position.x,\n y: position.y,\n },\n };\n secondTile = {\n tile: domino.left,\n position: {\n x: position.x,\n y: position.y + 1,\n },\n };\n break;\n }\n\n return [firstTile, secondTile];\n};\n\nexport const placeDomino = (\n kingdom: Kingdom,\n position: Position,\n rotation: Rotation,\n domino: Domino,\n maxKingdomSize: number = MAX_KINGDOM_SIZE\n): Result<Kingdom> => {\n const [firstTile, secondTile] = calculateDominoPosition(\n position,\n rotation,\n domino\n );\n\n const isFreePlaceResult = isFreePlace(\n kingdom,\n firstTile.position,\n secondTile.position\n );\n if (isErr(isFreePlaceResult)) {\n return isFreePlaceResult;\n }\n\n if (exceedsMaxSize(kingdom, firstTile.position, secondTile.position, maxKingdomSize)) {\n return err(ErrorCode.PLACEMENT_EXCEEDS_KINGDOM_SIZE);\n }\n\n const adjacentTiles = isAdjacent(\n kingdom,\n firstTile.position,\n secondTile.position\n );\n\n if (adjacentTiles.length === 0) {\n return err(ErrorCode.PLACEMENT_NOT_ADJACENT);\n }\n\n const hasValidAdjacentTiles = hasValidAdjacent(adjacentTiles, [\n firstTile.tile,\n secondTile.tile,\n ]);\n\n if (!hasValidAdjacentTiles) {\n return err(ErrorCode.PLACEMENT_INVALID_TERRAIN);\n }\n\n return ok(placeTiles(kingdom, [firstTile, secondTile]));\n};\n\nconst placeTiles = (\n kingdom: Kingdom,\n tiles: { tile: Tile; position: Position }[]\n) => {\n let newKingdom = deepCopyKingdom(kingdom);\n for (const { tile, position } of tiles) {\n newKingdom = placeTile(newKingdom, position, tile);\n }\n return newKingdom;\n};\n\nconst isFreePlace = (\n kingdom: Kingdom,\n firstPosition: Position,\n secondPosition: Position\n): Result<boolean> => {\n const firstTile = getTile(kingdom, firstPosition);\n const secondTile = getTile(kingdom, secondPosition);\n\n if (isErr(firstTile)) {\n return firstTile;\n }\n\n if (isErr(secondTile)) {\n return secondTile;\n }\n\n if (firstTile.value.type !== \"empty\" || secondTile.value.type !== \"empty\") {\n return err(ErrorCode.PLACEMENT_NOT_EMPTY);\n }\n\n return ok(true);\n};\n\nconst isAdjacent = (\n kingdom: Kingdom,\n firstPosition: Position,\n secondPosition: Position\n): Tile[] => {\n const offsets = [\n { x: -1, y: 0 },\n { x: 1, y: 0 },\n { x: 0, y: -1 },\n { x: 0, y: 1 },\n ];\n\n const isOwnPosition = (x: number, y: number) =>\n (x === firstPosition.x && y === firstPosition.y) ||\n (x === secondPosition.x && y === secondPosition.y);\n\n const adjacentTiles: Tile[] = [];\n\n for (const pos of [firstPosition, secondPosition]) {\n for (const offset of offsets) {\n const nx = pos.x + offset.x;\n const ny = pos.y + offset.y;\n if (isOwnPosition(nx, ny)) continue;\n const tile = getTile(kingdom, { x: nx, y: ny });\n if (isOk(tile) && tile.value.type !== \"empty\") {\n adjacentTiles.push(tile.value);\n }\n }\n }\n\n return adjacentTiles;\n};\n\nconst hasValidAdjacent = (\n adjacentTiles: (Tile | EmptyTile)[],\n tiles: Tile[]\n): boolean => {\n return adjacentTiles.some((adjacentTile) => {\n return tiles.some((tile) => {\n return tile.type === adjacentTile.type || adjacentTile.type === \"castle\";\n });\n });\n};\n\nexport const checkCastleIsInMiddle = (kingdom: Kingdom): boolean => {\n // Find castle coordinates\n let castleX: number | undefined;\n let castleY: number | undefined;\n\n for (let y = 0; y < kingdom.length; y++) {\n const x = kingdom[y]!.findIndex((tile) => tile.type === \"castle\");\n if (x !== -1) {\n castleX = x;\n castleY = y;\n break;\n }\n }\n\n if (castleX === undefined || castleY === undefined) {\n return false;\n }\n\n const bbox = getBoundingBox(kingdom);\n if (!bbox) return false;\n\n // Castle must be at the exact center of the bounding box\n const centerX = (bbox.minX + bbox.maxX) / 2;\n const centerY = (bbox.minY + bbox.maxY) / 2;\n\n return castleX === centerX && castleY === centerY;\n};\n\nexport const getBoundingBox = (\n kingdom: Kingdom\n): { minX: number; maxX: number; minY: number; maxY: number } | null => {\n let minX = Infinity;\n let maxX = -Infinity;\n let minY = Infinity;\n let maxY = -Infinity;\n\n for (let y = 0; y < kingdom.length; y++) {\n for (let x = 0; x < kingdom[y]!.length; x++) {\n if (kingdom[y]![x]!.type !== \"empty\") {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n }\n }\n\n if (minX === Infinity) return null;\n return { minX, maxX, minY, maxY };\n};\n\nconst exceedsMaxSize = (\n kingdom: Kingdom,\n firstPosition: Position,\n secondPosition: Position,\n maxSize: number = MAX_KINGDOM_SIZE\n): boolean => {\n const bbox = getBoundingBox(kingdom);\n\n let minX = bbox?.minX ?? Infinity;\n let maxX = bbox?.maxX ?? -Infinity;\n let minY = bbox?.minY ?? Infinity;\n let maxY = bbox?.maxY ?? -Infinity;\n\n for (const pos of [firstPosition, secondPosition]) {\n if (pos.x < minX) minX = pos.x;\n if (pos.x > maxX) maxX = pos.x;\n if (pos.y < minY) minY = pos.y;\n if (pos.y > maxY) maxY = pos.y;\n }\n\n return (maxX - minX + 1) > maxSize || (maxY - minY + 1) > maxSize;\n};\n\nexport const countDominoes = (kingdom: Kingdom): number => {\n const notEmpties = kingdom.flat().filter((tile) => tile.type !== \"empty\");\n // -1 because the castle is not a domino\n return (notEmpties.length - 1) / 2;\n};\n\nconst deepCopyKingdom = (kingdom: Kingdom): Kingdom => {\n return kingdom.map((line) => line.map((tile) => ({ ...tile })));\n};\n","import { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport { type Result, err, ok, isErr } from \"@utils/result.js\";\nimport type { Player } from \"@core/domain/types/player.js\";\nimport type { Kingdom } from \"@core/domain/types/kingdom.js\";\n\nconst MINPLAYERSNAMELENGTH = 3;\n\nexport const validatePlayer = (name: string): Result<string> => {\n if (!name || name.trim().length < MINPLAYERSNAMELENGTH) {\n return err(ErrorCode.INVALID_PLAYER_NAME);\n }\n\n return ok(name);\n};\n\nexport const createPlayer = (\n playerName: string,\n id: string,\n kingdom: Kingdom,\n bot?: { strategyName: string }\n): Result<Player> => {\n const name = validatePlayer(playerName);\n\n if (isErr(name)) {\n return name;\n }\n\n return ok({\n name: name.value,\n id,\n kingdom,\n ...(bot && { bot }),\n });\n};\n","import {\n createEmptyKingdom,\n placeCastle,\n} from \"@core/domain/entities/kingdom.js\";\nimport { createPlayer } from \"@core/domain/entities/player.js\";\nimport type {\n GameWithNextStep,\n NextStep,\n Players,\n} from \"@core/domain/types/index.js\";\nimport type { RuleRepository } from \"@core/portServerside/ruleRepository.js\";\nimport type { ShuffleMethod } from \"@core/portServerside/shuffleMethod.js\";\nimport type { UuidMethod } from \"@core/portServerside/uuidMethod.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport { err, isErr, ok, type Result } from \"@utils/result.js\";\nimport { createSeededShuffle } from \"@utils/seededShuffle.js\";\nimport type { PlayerInput } from \"@application/commands/addPlayersCommand.js\";\n\nexport type AddPlayersUseCase = (\n game: GameWithNextStep,\n players: PlayerInput[]\n) => Result<GameWithNextStep>;\n\nconst normalizePlayerInput = (\n input: PlayerInput\n): { name: string; bot?: { strategyName: string } } => {\n if (typeof input === \"string\") {\n return { name: input };\n }\n return { name: input.name, bot: input.bot };\n};\n\nexport const addPlayersUseCase =\n (deps: {\n uuidMethod: UuidMethod;\n shuffleMethod: ShuffleMethod;\n ruleRepository: RuleRepository;\n }): AddPlayersUseCase =>\n (game, players) => {\n const { uuidMethod, shuffleMethod, ruleRepository } = deps;\n\n if (!players || players.length < 1 || players.length > 4) {\n return err(ErrorCode.INVALID_PLAYER_COUNT);\n }\n\n const newPlayers: Players = [];\n\n for (const player of players) {\n const { name, bot } = normalizePlayerInput(player);\n let kingdom = createEmptyKingdom();\n kingdom = placeCastle(kingdom);\n let id = uuidMethod();\n const newPlayer = createPlayer(name, id, kingdom, bot);\n\n if (isErr(newPlayer)) {\n return newPlayer;\n }\n\n newPlayers.push(newPlayer.value);\n }\n\n // set rules\n const rules = ruleRepository.getAll();\n const basicRules = rules.basic[newPlayers.length];\n\n if (!basicRules) {\n return err(ErrorCode.STEP_EXECUTION_FAILED);\n }\n\n // updateDominoes\n const dominoes = game.dominoes;\n const { maxDominoes } = basicRules;\n const shuffle = game.seed\n ? createSeededShuffle(game.seed, \"dominoes\")\n : shuffleMethod;\n const shuffledDominoes = shuffle(dominoes);\n const splicedDominoes = shuffledDominoes.slice(0, maxDominoes);\n const next: NextStep = {\n type: \"step\",\n step: \"options\",\n };\n\n const updatedGame: GameWithNextStep = {\n ...game,\n players: newPlayers,\n dominoes: splicedDominoes,\n rules: {\n ...game.rules,\n basic: basicRules,\n },\n nextAction: next,\n };\n\n return ok(updatedGame);\n };\n","import type { Kingdom, Score } from \"@core/domain/types/index.js\";\nimport { ok, type Result } from \"@utils/result.js\";\n\nexport type CalculateScoreUseCase = (kingdom: Kingdom) => Result<Score>;\n\ntype Property = {\n size: number;\n crowns: number;\n};\n\nexport const calculateScoreUseCase: CalculateScoreUseCase = (kingdom) => {\n const rows = kingdom.length;\n const cols = kingdom[0]!.length;\n const visited: boolean[][] = kingdom.map((row) => row.map(() => false));\n const properties: Property[] = [];\n\n const directions = [\n [-1, 0],\n [1, 0],\n [0, -1],\n [0, 1],\n ];\n\n for (let y = 0; y < rows; y++) {\n for (let x = 0; x < cols; x++) {\n const tile = kingdom[y]![x]!;\n if (visited[y]![x] || tile.type === \"empty\" || tile.type === \"castle\") {\n continue;\n }\n\n // BFS flood-fill for this property\n const type = tile.type;\n let size = 0;\n let crowns = 0;\n const queue: [number, number][] = [[x, y]];\n visited[y]![x] = true;\n\n while (queue.length > 0) {\n const [cx, cy] = queue.pop()!;\n const current = kingdom[cy]![cx]!;\n size++;\n crowns += current.crowns;\n\n for (const [dx, dy] of directions) {\n const nx = cx + (dx as number);\n const ny = cy + (dy as number);\n if (\n nx >= 0 &&\n ny >= 0 &&\n nx < cols &&\n ny < rows &&\n !visited[ny]![nx] &&\n kingdom[ny]![nx]!.type === type\n ) {\n visited[ny]![nx] = true;\n queue.push([nx, ny]);\n }\n }\n }\n\n properties.push({ size, crowns });\n }\n }\n\n if (properties.length === 0) {\n return ok({\n points: 0,\n maxPropertiesSize: 0,\n totalCrowns: 0,\n });\n }\n\n let points = 0;\n let maxPropertiesSize = 0;\n let totalCrowns = 0;\n\n for (const property of properties) {\n points += property.size * property.crowns;\n if (property.size > maxPropertiesSize) {\n maxPropertiesSize = property.size;\n }\n totalCrowns += property.crowns;\n }\n\n return ok({\n points,\n maxPropertiesSize,\n totalCrowns,\n });\n};\n","import type { NextAction } from \"@core/domain/types/game.js\";\nimport type { Lord } from \"@core/domain/types/lord.js\";\nimport { playerActions } from \"@core/domain/types/player.js\";\n\nexport const createLord = (id: string, playerId: string): Lord => {\n return {\n id,\n playerId,\n turnEnded: false,\n hasPick: false,\n hasPlace: true,\n };\n};\n\nconst hasPick = (lord: Lord): boolean => lord.hasPick;\nconst hasPlace = (lord: Lord): boolean => lord.hasPlace;\nconst hasTurnEnded = (lord: Lord): boolean => lord.turnEnded;\n\nexport const canPass = (lord: Lord): boolean => {\n return !hasPick(lord) && !hasPlace(lord) && !hasTurnEnded(lord);\n};\n\nexport const canPick = (lord: Lord): boolean => {\n return !hasPick(lord) && hasPlace(lord) && !hasTurnEnded(lord);\n};\n\nexport const canPlaceAndDominoPickedIsDefined = (\n lord: Lord\n): lord is Required<Lord & Pick<Lord, \"dominoPicked\">> => {\n return (\n !hasPick(lord) &&\n !hasPlace(lord) &&\n !hasTurnEnded(lord) &&\n lord.dominoPicked !== undefined\n );\n};\n\nexport const updateLordOrder = (lords: Lord[]): Lord[] => {\n return [...lords].sort((a, b) => {\n return (a.dominoPicked?.number ?? 0) - (b.dominoPicked?.number ?? 0);\n });\n};\n\nexport const resetLordsActions = (lords: Lord[]): Lord[] => {\n return lords.map((lord) => ({\n ...lord,\n turnEnded: false,\n hasPick: false,\n hasPlace: false,\n }));\n};\n\nexport const nextLordWithAction = (lords: Lord[]): NextAction => {\n const nextLord = findNextLord(lords);\n\n return {\n type: \"action\",\n nextLord: nextLord.id,\n nextAction: hasPlace(nextLord)\n ? playerActions.pickDomino\n : playerActions.placeDomino,\n };\n};\n\nconst findNextLord = (lords: Lord[]): Lord => {\n const lord = lords.find((lord) => !hasTurnEnded(lord));\n if (!lord) {\n return lords[0]!;\n }\n return lord;\n};\n\nexport const allLordsHavePlayed = (lords: Lord[]): boolean => {\n return lords.every((lord) => lord.turnEnded);\n};\n","import {\n allLordsHavePlayed,\n canPick,\n nextLordWithAction,\n resetLordsActions,\n updateLordOrder,\n} from \"@core/domain/entities/lord.js\";\nimport type { GameWithNextAction } from \"@core/domain/types/game.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport { err, ok, type Result } from \"@utils/result.js\";\n\nexport type ChooseDominoUseCase = (\n game: GameWithNextAction,\n lordId: string,\n dominoPick: number\n) => Result<GameWithNextAction>;\n\nexport const chooseDominoUseCase: ChooseDominoUseCase = (\n game,\n lordId,\n dominoPick\n) => {\n const currentLord = game.lords.find(\n (lord) => lord.id === game.nextAction.nextLord\n );\n\n if (!currentLord) {\n return err(ErrorCode.LORD_NOT_FOUND);\n }\n\n if (currentLord.id !== lordId) {\n return err(ErrorCode.NOT_YOUR_TURN);\n }\n\n if (!canPick(currentLord)) {\n return err(ErrorCode.CANNOT_PICK);\n }\n\n // Check if dominoPick is valid choice\n const selectedDomino = game.currentDominoes.find(\n (domino) => domino.domino.number === dominoPick\n );\n\n if (!selectedDomino) {\n return err(ErrorCode.DOMINO_NOT_FOUND);\n }\n\n if (selectedDomino.picked) {\n return err(ErrorCode.DOMINO_ALREADY_PICKED);\n }\n\n // update currentDominoes\n const updatedCurrentDominoes = game.currentDominoes.map((domino) =>\n domino.domino.number === dominoPick\n ? { ...domino, picked: true, lordId: currentLord.id }\n : domino\n );\n\n // update lords\n const updatedLords = game.lords.map((lord) =>\n lord.id === currentLord.id\n ? { ...lord, hasPick: true, turnEnded: true, dominoPicked: selectedDomino.domino }\n : lord\n );\n\n const turnEnded = allLordsHavePlayed(updatedLords);\n\n if (turnEnded) {\n const lords = resetLordsActions(updateLordOrder(updatedLords));\n const updatedTurn = game.turn + 1;\n const next = nextLordWithAction(lords);\n const dominoesCopy = [...game.dominoes];\n const dominoesDrawn = dominoesCopy.splice(\n 0,\n game.rules.basic.dominoesPerTurn\n );\n dominoesDrawn.sort((a, b) => a.number - b.number);\n const updatedCurrentDominoes = dominoesDrawn.map((domino, index) => {\n return {\n domino,\n picked: false,\n lordId: null,\n position: index + 1,\n };\n });\n\n return ok({\n ...game,\n currentDominoes: updatedCurrentDominoes,\n dominoes: dominoesCopy,\n lords,\n turn: updatedTurn,\n nextAction: next,\n });\n }\n\n const next = nextLordWithAction(updatedLords);\n\n // update state\n const updatedState = {\n ...game,\n currentDominoes: updatedCurrentDominoes,\n lords: updatedLords,\n nextAction: next,\n };\n\n return ok(updatedState);\n};\n","import {\n gameSteps,\n type Domino,\n type GameMode,\n type GameWithNextStep,\n} from \"@core/domain/types/index.js\";\n\nexport const create = (payload: {\n id: string;\n mode: GameMode;\n dominoes: Domino[];\n seed?: string;\n}): GameWithNextStep => {\n const { id, mode, dominoes, seed } = payload;\n return {\n id,\n dominoes,\n currentDominoes: [],\n players: [],\n lords: [],\n turn: 0,\n nextAction: {\n type: \"step\",\n step: gameSteps.addPlayers,\n },\n rules: {\n basic: {\n lords: 0,\n maxDominoes: 0,\n dominoesPerTurn: 0,\n maxTurns: 0,\n maxKingdomSize: 5,\n },\n extra: [],\n },\n mode,\n ...(seed !== undefined && { seed }),\n };\n};\n","import { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport { err, ok, type Result } from \"@utils/result.js\";\nimport type { GameMode } from \"@core/domain/types/mode.js\";\n\nconst findMode = (\n mode: string,\n availableMode: GameMode[]\n): GameMode | undefined => {\n return availableMode.find((m) => m.name === mode);\n};\n\nexport const createMode = (\n mode: string,\n availableMode: GameMode[]\n): Result<GameMode> => {\n const foundMode = findMode(mode, availableMode);\n if (foundMode) {\n return ok(foundMode);\n }\n\n return err(ErrorCode.MODE_NOT_FOUND);\n};\n","import { create } from \"@core/domain/entities/game.js\";\nimport { createMode } from \"@core/domain/entities/mode.js\";\nimport type { GameWithNextStep } from \"@core/domain/types/game.js\";\nimport type { DominoesRepository } from \"@core/portServerside/dominoesRepository.js\";\nimport type { ModeRepository } from \"@core/portServerside/modeRepository.js\";\nimport type { UuidMethod } from \"@core/portServerside/uuidMethod.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport { err, isErr, ok, type Result } from \"@utils/result.js\";\n\nexport type CreateGameUseCase = (\n mode: string,\n seed?: string\n) => Result<GameWithNextStep>;\n\nexport const createGameUseCase =\n (deps: {\n modeRepository: ModeRepository;\n dominoesRepository: DominoesRepository;\n uuidMethod: UuidMethod;\n }): CreateGameUseCase =>\n (mode, seed) => {\n const { modeRepository, dominoesRepository, uuidMethod } = deps;\n const id = uuidMethod();\n const gameSeed = seed ?? uuidMethod();\n const availableMode = modeRepository.getAvailables();\n const newMode = createMode(mode, availableMode);\n\n if (isErr(newMode)) {\n return newMode;\n }\n\n const dominoes = dominoesRepository.getForMode(newMode.value);\n\n if (!dominoes || dominoes.length === 0) {\n return err(ErrorCode.DOMINO_NOT_FOUND);\n }\n\n const payload = {\n id,\n mode: newMode.value,\n dominoes,\n seed: gameSeed,\n };\n\n const newGame = create(payload);\n\n return ok(newGame);\n };\n","import type { Kingdom, Position, Rotation, Domino } from \"@core/domain/types/index.js\";\nimport { GRIDSIZE, MAX_KINGDOM_SIZE } from \"@core/domain/types/kingdom.js\";\nimport { placeDomino } from \"@core/domain/entities/kingdom.js\";\nimport { isOk } from \"@utils/result.js\";\n\n/**\n * Represents a valid placement position with rotation.\n */\nexport type ValidPlacement = {\n position: Position;\n rotation: Rotation;\n};\n\nexport type GetValidPlacementsUseCase = (\n kingdom: Kingdom,\n domino: Domino,\n maxKingdomSize?: number\n) => ValidPlacement[];\n\n/**\n * Finds all valid placements for a domino on a kingdom grid.\n * Tests all positions and rotations to determine where the domino can be placed.\n *\n * @param kingdom - The current state of the kingdom grid\n * @param domino - The domino to place\n * @param maxKingdomSize - Maximum kingdom size (default: 5)\n * @returns Array of valid placements (position + rotation combinations)\n */\nexport const getValidPlacementsUseCase: GetValidPlacementsUseCase = (\n kingdom,\n domino,\n maxKingdomSize = MAX_KINGDOM_SIZE\n) => {\n const validPlacements: ValidPlacement[] = [];\n const rotations: Rotation[] = [0, 90, 180, 270];\n\n // Try each position on the grid\n for (let y = 0; y < GRIDSIZE; y++) {\n for (let x = 0; x < GRIDSIZE; x++) {\n const position: Position = { x, y };\n\n // Try each rotation\n for (const rotation of rotations) {\n const result = placeDomino(kingdom, position, rotation, domino, maxKingdomSize);\n if (isOk(result)) {\n validPlacements.push({ position, rotation });\n }\n }\n }\n }\n\n return validPlacements;\n};\n\n/**\n * Checks if a domino can be placed anywhere on the kingdom.\n *\n * @param kingdom - The current state of the kingdom grid\n * @param domino - The domino to check\n * @param maxKingdomSize - Maximum kingdom size (default: 5)\n * @returns True if at least one valid placement exists\n */\nexport const canPlaceDominoUseCase = (\n kingdom: Kingdom,\n domino: Domino,\n maxKingdomSize: number = MAX_KINGDOM_SIZE\n): boolean => {\n const rotations: Rotation[] = [0, 90, 180, 270];\n\n // Check each position on the grid\n for (let y = 0; y < GRIDSIZE; y++) {\n for (let x = 0; x < GRIDSIZE; x++) {\n const position: Position = { x, y };\n\n // Check each rotation - return early if any placement is valid\n for (const rotation of rotations) {\n const result = placeDomino(kingdom, position, rotation, domino, maxKingdomSize);\n if (isOk(result)) {\n return true;\n }\n }\n }\n }\n\n return false;\n};\n","import {\n allLordsHavePlayed,\n canPass,\n nextLordWithAction,\n} from \"@core/domain/entities/lord.js\";\nimport {\n gameSteps,\n type GameState,\n type GameStateResult,\n type GameWithNextAction,\n type NextAction,\n type NextStep,\n} from \"@core/domain/types/game.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport { canPlaceDominoUseCase } from \"./getValidPlacements.js\";\nimport { err, ok } from \"@utils/result.js\";\n\nexport type DiscardDominoUseCase = (\n game: GameWithNextAction,\n lordId: string\n) => GameStateResult;\n\nexport const discardDominoUseCase: DiscardDominoUseCase = (game, lordId) => {\n const nextAction = game.nextAction;\n\n const currentLord = game.lords.find(\n (lord) => lord.id === nextAction.nextLord\n );\n\n if (!currentLord) {\n return err(ErrorCode.LORD_NOT_FOUND);\n }\n\n if (currentLord.id !== lordId) {\n return err(ErrorCode.NOT_YOUR_TURN);\n }\n\n if (!canPass(currentLord)) {\n return err(ErrorCode.CANNOT_PLACE);\n }\n\n if (currentLord.dominoPicked) {\n const currentPlayer = game.players.find(\n (player) => player.id === currentLord.playerId\n );\n\n if (currentPlayer && canPlaceDominoUseCase(currentPlayer.kingdom, currentLord.dominoPicked, game.rules.basic.maxKingdomSize)) {\n return err(ErrorCode.CANNOT_PLACE);\n }\n }\n\n const maxTurns = game.rules.basic.maxTurns;\n const currentTurn = game.turn;\n const isLastTurn = currentTurn === maxTurns;\n\n const updatedLord = game.lords.map((lord) => {\n if (lord.id === currentLord.id) {\n if (isLastTurn) {\n return {\n ...lord,\n turnEnded: true,\n hasPlace: true,\n };\n }\n\n return {\n ...lord,\n hasPlace: true,\n };\n }\n return lord;\n });\n\n let updatedGame: GameState;\n\n const resultStep: NextStep = {\n type: \"step\",\n step: gameSteps.result,\n };\n\n if (isLastTurn && allLordsHavePlayed(updatedLord)) {\n updatedGame = {\n ...game,\n lords: updatedLord,\n nextAction: resultStep,\n };\n } else {\n updatedGame = {\n ...game,\n lords: updatedLord,\n nextAction: <NextAction>nextLordWithAction(updatedLord),\n };\n }\n\n return ok(updatedGame);\n};\n","import type { FinalResult, GameWithResults } from \"@core/domain/types/index.js\";\n\nexport type DynastyResult = {\n playerId: string;\n playerName: string;\n totalPoints: number;\n gamesPoints: number[];\n position: number;\n};\n\nexport type GetDynastyResultUseCase = (\n games: GameWithResults[]\n) => DynastyResult[];\n\nexport const getDynastyResultUseCase: GetDynastyResultUseCase = (games) => {\n // Collect all unique players\n const playerMap = new Map<string, { name: string; points: number[] }>();\n\n for (const game of games) {\n for (const result of game.result) {\n const existing = playerMap.get(result.playerId);\n if (existing) {\n existing.points.push(result.details.points);\n } else {\n playerMap.set(result.playerId, {\n name: result.playerName,\n points: [result.details.points],\n });\n }\n }\n }\n\n // Calculate totals and sort\n const results: Omit<DynastyResult, \"position\">[] = [];\n for (const [playerId, data] of playerMap) {\n results.push({\n playerId,\n playerName: data.name,\n totalPoints: data.points.reduce((sum, p) => sum + p, 0),\n gamesPoints: data.points,\n });\n }\n\n results.sort((a, b) => b.totalPoints - a.totalPoints);\n\n // Assign positions with tie detection\n const finalResults: DynastyResult[] = [];\n for (let i = 0; i < results.length; i++) {\n const current = results[i]!;\n const previous = i > 0 ? finalResults[i - 1]! : null;\n const position =\n previous && current.totalPoints === previous.totalPoints\n ? previous.position\n : i + 1;\n finalResults.push({ ...current, position });\n }\n\n return finalResults;\n};\n","import { getAvailablesExtraRules } from \"@core/domain/entities/rule.js\";\nimport type { GameMode } from \"@core/domain/types/mode.js\";\nimport type { ExtraRule } from \"@core/domain/types/rule.js\";\nimport type { RuleRepository } from \"@core/portServerside/ruleRepository.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport { err, type Result } from \"@utils/result.js\";\n\nexport type GetExtraRulesUseCase = (\n mode: GameMode[\"name\"],\n players: number\n) => Result<ExtraRule[]>;\n\nexport const getExtraRulesUseCase =\n (deps: { ruleRepository: RuleRepository }): GetExtraRulesUseCase =>\n (mode: GameMode[\"name\"], players: number): Result<ExtraRule[]> => {\n const { ruleRepository } = deps;\n\n const allExtraRules = ruleRepository.getAllExtra();\n\n if (!allExtraRules) {\n return err(ErrorCode.STEP_EXECUTION_FAILED);\n }\n\n return getAvailablesExtraRules(allExtraRules, mode, players);\n };\n","import type { GameMode } from \"@core/domain/types/mode.js\";\nimport type { ModeRepository } from \"@core/portServerside/modeRepository.js\";\nimport { ok, type Result } from \"@utils/result.js\";\n\nexport type GetModesUseCase = () => Result<GameMode[]>;\n\nexport const getModesUseCase =\n (deps: { modeRepository: ModeRepository }): GetModesUseCase =>\n (): Result<GameMode[]> => {\n const { modeRepository } = deps;\n return ok(modeRepository.getAvailables());\n };\n","import {\n checkCastleIsInMiddle,\n countDominoes,\n} from \"@core/domain/entities/kingdom.js\";\nimport type {\n FinalResult,\n GameWithNextStep,\n GameWithResults,\n ScoreResult,\n} from \"@core/domain/types/index.js\";\nimport { err, ok, type Result } from \"@utils/result.js\";\n\nexport type GetResultUseCase = (\n game: GameWithNextStep,\n scoreResult: ScoreResult[]\n) => Result<GameWithResults>;\n\nexport const getResultUseCase: GetResultUseCase = (game, scoreResult) => {\n const { rules } = game;\n const { basic, extra } = rules;\n\n const finalScoreResult = scoreResult.map((score): ScoreResult => {\n let finalScore = score.details.points;\n\n const player = game.players.find((p) => p.id === score.playerId);\n if (!player) {\n return score;\n }\n\n const { kingdom } = player;\n\n if (extra.length > 0) {\n extra.forEach((extraRule) => {\n if (extraRule.name === \"The middle Kingdom\") {\n const castleIsInMiddle = checkCastleIsInMiddle(kingdom);\n if (castleIsInMiddle) {\n finalScore += 10;\n }\n }\n\n if (extraRule.name === \"Harmony\") {\n const totalDominoes = countDominoes(kingdom);\n const dominoLimit = basic.maxDominoes;\n const totalPlayers = game.players.length;\n const dominoesPerPlayer = dominoLimit / totalPlayers;\n if (totalDominoes === dominoesPerPlayer) {\n finalScore += 5;\n }\n }\n });\n }\n\n return {\n ...score,\n details: {\n ...score.details,\n points: finalScore,\n },\n };\n });\n\n // Order players by score, then by maxPropertiesSize (per official rules, no further tiebreaker)\n finalScoreResult.sort((a, b) => {\n if (a.details.points !== b.details.points) {\n return b.details.points - a.details.points;\n }\n return b.details.maxPropertiesSize - a.details.maxPropertiesSize;\n });\n\n const result: FinalResult[] = [];\n\n let isTie = false;\n result.push({\n playerId: finalScoreResult[0]!.playerId,\n playerName: finalScoreResult[0]!.playerName,\n details: finalScoreResult[0]!.details,\n position: 1,\n });\n\n for (let i = 1; i < finalScoreResult.length; i++) {\n const currentScore = finalScoreResult[i];\n const previousScore = finalScoreResult[i - 1];\n if (\n previousScore &&\n currentScore &&\n currentScore.details.points === previousScore.details.points &&\n currentScore.details.maxPropertiesSize ===\n previousScore.details.maxPropertiesSize\n ) {\n isTie = true;\n }\n\n if (isTie) {\n result.push({\n ...currentScore!,\n position: result[i - 1]!.position,\n });\n } else {\n result.push({\n ...currentScore!,\n position: i + 1,\n });\n }\n\n isTie = false;\n }\n\n return ok({\n ...game,\n result: result,\n });\n};\n","import { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport { err, isErr, ok } from \"@utils/result.js\";\nimport {\n gameSteps,\n type GameState,\n type GameStateResult,\n type GameWithNextAction,\n type NextAction,\n type NextStep,\n} from \"@core/domain/types/game.js\";\nimport {\n allLordsHavePlayed,\n canPlaceAndDominoPickedIsDefined,\n nextLordWithAction,\n} from \"@core/domain/entities/lord.js\";\nimport { placeDomino } from \"@core/domain/entities/kingdom.js\";\nimport type {\n Position,\n Rotation,\n} from \"@core/domain/types/kingdom.js\";\n\nexport type PlaceDominoUseCase = (\n game: GameWithNextAction,\n lordId: string,\n position: Position,\n rotation: Rotation\n) => GameStateResult;\n\nexport const placeDominoUseCase: PlaceDominoUseCase = (\n game,\n lordId,\n position,\n rotation\n) => {\n const nextAction = game.nextAction;\n\n const currentLord = game.lords.find(\n (lord) => lord.id === nextAction.nextLord\n );\n\n if (!currentLord) {\n return err(ErrorCode.LORD_NOT_FOUND);\n }\n\n if (currentLord.id !== lordId) {\n return err(ErrorCode.NOT_YOUR_TURN);\n }\n\n if (!canPlaceAndDominoPickedIsDefined(currentLord)) {\n return err(ErrorCode.CANNOT_PLACE);\n }\n\n const domino = currentLord.dominoPicked;\n\n const currentPlayer = game.players.find(\n (player) => player.id === currentLord.playerId\n );\n\n if (!currentPlayer) {\n return err(ErrorCode.PLAYER_NOT_FOUND);\n }\n\n const updatedKingdom = placeDomino(\n currentPlayer.kingdom,\n position,\n rotation,\n domino,\n game.rules.basic.maxKingdomSize\n );\n\n if (isErr(updatedKingdom)) {\n return updatedKingdom;\n }\n\n const updatedPlayers = game.players.map((player) => {\n if (player.id === currentPlayer.id) {\n player.kingdom = updatedKingdom.value;\n }\n return player;\n });\n\n const maxTurns = game.rules.basic.maxTurns;\n const currentTurn = game.turn;\n const isLastTurn = currentTurn === maxTurns;\n\n const updatedLords = game.lords.map((lord) => {\n if (lord.id === currentLord.id) {\n if (isLastTurn) {\n return {\n ...lord,\n turnEnded: true,\n hasPlace: true,\n };\n }\n return {\n ...lord,\n hasPlace: true,\n };\n }\n return lord;\n });\n\n let updatedGame: GameState;\n\n const resultStep: NextStep = {\n type: \"step\",\n step: gameSteps.result,\n };\n\n if (isLastTurn && allLordsHavePlayed(updatedLords)) {\n updatedGame = {\n ...game,\n lords: updatedLords,\n nextAction: resultStep,\n players: updatedPlayers,\n };\n } else {\n updatedGame = {\n ...game,\n lords: updatedLords,\n nextAction: <NextAction>nextLordWithAction(updatedLords),\n players: updatedPlayers,\n };\n }\n\n return ok(updatedGame);\n};\n","import { createLord } from \"@core/domain/entities/lord\";\nimport type {\n GameWithNextAction,\n GameWithNextStep,\n NextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Lord } from \"@core/domain/types/lord.js\";\nimport { playerActions } from \"@core/domain/types/player.js\";\nimport type { ShuffleMethod } from \"@core/portServerside/shuffleMethod.js\";\nimport type { UuidMethod } from \"@core/portServerside/uuidMethod.js\";\nimport { ok, type Result } from \"@utils/result.js\";\nimport { createSeededShuffle } from \"@utils/seededShuffle.js\";\n\nexport type StartGameUseCase = (\n game: GameWithNextStep\n) => Result<GameWithNextAction>;\n\nexport const startGameUseCase =\n (deps: {\n uuidMethod: UuidMethod;\n shuffleMethod: ShuffleMethod;\n }): StartGameUseCase =>\n (game) => {\n const { uuidMethod, shuffleMethod } = deps;\n const {\n rules: {\n basic: { lords: maxLords, dominoesPerTurn },\n },\n players,\n dominoes,\n } = game;\n\n const numberOfPlayers = players.length;\n\n const newLords: Lord[] = [];\n\n for (let i = 0; i < numberOfPlayers; i++) {\n for (let j = 0; j < maxLords; j++) {\n const lord = createLord(uuidMethod(), players[i]!.id);\n newLords.push(lord);\n }\n }\n\n const shuffle = game.seed\n ? createSeededShuffle(game.seed, \"lords\")\n : shuffleMethod;\n const shuffledLords = shuffle(newLords);\n const dominoesCopy = [...dominoes];\n const dominoesDrawn = dominoesCopy.splice(0, dominoesPerTurn);\n dominoesDrawn.sort((a, b) => a.number - b.number);\n const nextAction: NextAction = {\n type: \"action\",\n nextLord: shuffledLords[0]!.id,\n nextAction: playerActions.pickDomino,\n };\n\n const newState: GameWithNextAction = {\n ...game,\n lords: shuffledLords,\n nextAction,\n dominoes: dominoesCopy,\n currentDominoes: dominoesDrawn.map((domino, index) => {\n return {\n domino,\n picked: false,\n lordId: null,\n position: index + 1,\n };\n }),\n };\n\n return ok(newState);\n };\n","import { consoleLogger, silentLogger } from \"@adapter/consoleLogger.js\";\nimport jsonDominoes from \"@adapter/jsonDominoes.js\";\nimport jsonModes from \"@adapter/jsonModes.js\";\nimport jsonRules from \"@adapter/jsonRules.js\";\nimport { shuffleMethod } from \"@adapter/shuffle.js\";\nimport { uuidMethod } from \"@adapter/uuid.js\";\nimport { addExtraRulesHandler } from \"@application/handlers/addExtraRulesHandler.js\";\nimport { addPlayersHandler } from \"@application/handlers/addPlayersHandler.js\";\nimport { calculateScoreHandler } from \"@application/handlers/calculateScoreHandler.js\";\nimport { canPlaceDominoHandler } from \"@application/handlers/canPlaceDominoHandler.js\";\nimport { chooseDominoHandler } from \"@application/handlers/chooseDominoHandler.js\";\nimport { createGameHandler } from \"@application/handlers/createGameHandler.js\";\nimport { discardDominoHandler } from \"@application/handlers/discardDominoHandler.js\";\nimport { getDynastyResultHandler } from \"@application/handlers/getDynastyResultHandler.js\";\nimport { getExtraRulesHandler } from \"@application/handlers/getExtraRulesHandler.js\";\nimport { getModesHandler } from \"@application/handlers/getModesHandler.js\";\nimport { getResultHandler } from \"@application/handlers/getResultHandler.js\";\nimport { getValidPlacementsHandler } from \"@application/handlers/getValidPlacementsHandler.js\";\nimport { placeDominoHandler } from \"@application/handlers/placeDominoHandler.js\";\nimport {\n deserializeGameHandler,\n serializeGameHandler,\n} from \"@application/handlers/serializeGameHandler.js\";\nimport { startGameHandler } from \"@application/handlers/startGameHandler.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport type { GameEngine } from \"@core/portUserside/engine.js\";\nimport { defaultTranslator } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { ShuffleMethod } from \"@core/portServerside/shuffleMethod.js\";\nimport type { UuidMethod } from \"@core/portServerside/uuidMethod.js\";\nimport { addExtraRulesUseCase } from \"@core/useCases/addExtraRules.js\";\nimport { addPlayersUseCase } from \"@core/useCases/addPlayers.js\";\nimport { calculateScoreUseCase } from \"@core/useCases/calculateScore.js\";\nimport { chooseDominoUseCase } from \"@core/useCases/chooseDomino.js\";\nimport { createGameUseCase } from \"@core/useCases/createGame.js\";\nimport { discardDominoUseCase } from \"@core/useCases/discardDomino.js\";\nimport type { DebugOptions } from \"@core/useCases/gameDebug.js\";\nimport type { GameEventCallbacks } from \"@core/useCases/gameEvents.js\";\nimport { getDynastyResultUseCase } from \"@core/useCases/getDynastyResult.js\";\nimport { getExtraRulesUseCase } from \"@core/useCases/getExtraRules.js\";\nimport { getModesUseCase } from \"@core/useCases/getModes.js\";\nimport { getResultUseCase } from \"@core/useCases/getResult.js\";\nimport {\n canPlaceDominoUseCase,\n getValidPlacementsUseCase,\n} from \"@core/useCases/getValidPlacements.js\";\nimport { placeDominoUseCase } from \"@core/useCases/placeDomino.js\";\nimport { startGameUseCase } from \"@core/useCases/startGame.js\";\n\n/**\n * Configuration options for the game engine.\n */\nexport type EngineConfig = {\n /** Custom UUID generation method. Defaults to crypto.randomUUID() */\n uuidMethod?: UuidMethod;\n /** Custom shuffle method. Defaults to Fisher-Yates algorithm */\n shuffleMethod?: ShuffleMethod;\n /** Enable console logging. Defaults to false */\n logging?: boolean;\n /** Custom logger instance. When provided, takes precedence over 'logging' option */\n logger?: Logger;\n /** Optional event callbacks for UI/animation integration */\n events?: GameEventCallbacks;\n /** Custom translator for i18n error messages. Defaults to English */\n translator?: Translator;\n /** Enable debug mode with detailed logging. Pass `true` for defaults or a `DebugOptions` object. */\n debug?: boolean | DebugOptions;\n};\n\nexport type ConfiguredHandlers = {\n createGameHandler: GameEngine[\"createGame\"];\n getModesHandler: GameEngine[\"getModes\"];\n getExtraRulesHandler: GameEngine[\"getExtraRules\"];\n addPlayersHandler: GameEngine[\"addPlayers\"];\n addExtraRulesHandler: GameEngine[\"addExtraRules\"];\n startGameHandler: GameEngine[\"startGame\"];\n chooseDominoHandler: GameEngine[\"chooseDomino\"];\n placeDominoHandler: GameEngine[\"placeDomino\"];\n discardDominoHandler: GameEngine[\"discardDomino\"];\n getResultHandler: GameEngine[\"getResults\"];\n calculateScoreHandler: GameEngine[\"calculateScore\"];\n getValidPlacementsHandler: GameEngine[\"getValidPlacements\"];\n canPlaceDominoHandler: GameEngine[\"canPlaceDomino\"];\n serializeGameHandler: GameEngine[\"serialize\"];\n deserializeGameHandler: GameEngine[\"deserialize\"];\n getDynastyResultHandler: GameEngine[\"getDynastyResults\"];\n};\n\nexport const configureEngine = (config: Partial<EngineConfig>): ConfiguredHandlers => {\n const modeRepository = jsonModes();\n const dominoesRepository = jsonDominoes();\n const ruleRepository = jsonRules();\n const uuid = config.uuidMethod || uuidMethod;\n const shuffle = config.shuffleMethod || shuffleMethod;\n const translator = config.translator || defaultTranslator;\n\n // Logger priority: custom logger > logging flag > silent\n const logger = config.logger\n ? config.logger\n : config.logging\n ? consoleLogger(true)\n : silentLogger;\n\n return {\n createGameHandler: createGameHandler(\n logger,\n translator,\n createGameUseCase({\n modeRepository,\n dominoesRepository,\n uuidMethod: uuid,\n }),\n ),\n getModesHandler: getModesHandler(\n logger,\n translator,\n getModesUseCase({ modeRepository }),\n ),\n getExtraRulesHandler: getExtraRulesHandler(\n logger,\n translator,\n getExtraRulesUseCase({ ruleRepository }),\n ),\n addPlayersHandler: addPlayersHandler(\n logger,\n translator,\n addPlayersUseCase({\n uuidMethod: uuid,\n shuffleMethod: shuffle,\n ruleRepository,\n }),\n ),\n addExtraRulesHandler: addExtraRulesHandler(\n logger,\n translator,\n addExtraRulesUseCase({\n ruleRepository,\n dominoesRepository,\n shuffleMethod: shuffle,\n }),\n ),\n startGameHandler: startGameHandler(\n logger,\n translator,\n startGameUseCase({ uuidMethod: uuid, shuffleMethod: shuffle }),\n ),\n chooseDominoHandler: chooseDominoHandler(\n logger,\n translator,\n chooseDominoUseCase,\n ),\n placeDominoHandler: placeDominoHandler(\n logger,\n translator,\n placeDominoUseCase,\n ),\n discardDominoHandler: discardDominoHandler(\n logger,\n translator,\n discardDominoUseCase,\n ),\n getResultHandler: getResultHandler(logger, translator, {\n getResultUseCase,\n calculateScoreUseCase,\n }),\n calculateScoreHandler: calculateScoreHandler(\n logger,\n translator,\n calculateScoreUseCase,\n ),\n getValidPlacementsHandler: getValidPlacementsHandler(\n logger,\n translator,\n getValidPlacementsUseCase,\n ),\n canPlaceDominoHandler: canPlaceDominoHandler(\n logger,\n translator,\n canPlaceDominoUseCase,\n ),\n serializeGameHandler: serializeGameHandler(logger, translator),\n deserializeGameHandler: deserializeGameHandler(logger, translator),\n getDynastyResultHandler: getDynastyResultHandler(\n logger,\n translator,\n getDynastyResultUseCase,\n ),\n };\n};\n","import { GROUND } from \"@core/domain/types/domino.js\";\nimport type { Game } from \"@core/domain/types/game.js\";\nimport { gameSteps } from \"@core/domain/types/game.js\";\nimport { GRIDSIZE } from \"@core/domain/types/kingdom.js\";\nimport { playerActions } from \"@core/domain/types/player.js\";\nimport type { ValidationIssue, ValidationSeverity } from \"@core/domain/types/validation.js\";\n\nconst issue = (\n path: string,\n code: string,\n message: string,\n severity: ValidationSeverity = \"error\",\n): ValidationIssue => ({ path, code, message, severity });\n\nconst isNonEmptyString = (value: unknown): value is string =>\n typeof value === \"string\" && value.length > 0;\n\nconst isNonNegativeInteger = (value: unknown): value is number =>\n typeof value === \"number\" && Number.isInteger(value) && value >= 0;\n\nconst isPositiveInteger = (value: unknown): value is number =>\n typeof value === \"number\" && Number.isInteger(value) && value > 0;\n\nconst validGrounds = new Set<string>([...GROUND, \"empty\"]);\nconst validPlayerActions = new Set<string>(Object.values(playerActions));\nconst validGameSteps = new Set<string>(Object.values(gameSteps));\n\n// --- Validation sub-functions ---\n\nconst validateGameStructure = (game: Game): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n\n if (!isNonEmptyString(game.id)) {\n issues.push(issue(\"id\", \"INVALID_ID\", \"Game id must be a non-empty string\"));\n }\n if (!isNonNegativeInteger(game.turn)) {\n issues.push(issue(\"turn\", \"INVALID_TURN\", \"Turn must be a non-negative integer\"));\n }\n if (!Array.isArray(game.dominoes)) {\n issues.push(issue(\"dominoes\", \"INVALID_DOMINOES\", \"Dominoes must be an array\"));\n }\n if (!Array.isArray(game.currentDominoes)) {\n issues.push(issue(\"currentDominoes\", \"INVALID_CURRENT_DOMINOES\", \"CurrentDominoes must be an array\"));\n }\n if (!Array.isArray(game.players)) {\n issues.push(issue(\"players\", \"INVALID_PLAYERS\", \"Players must be an array\"));\n }\n if (!Array.isArray(game.lords)) {\n issues.push(issue(\"lords\", \"INVALID_LORDS\", \"Lords must be an array\"));\n }\n if (!game.rules || typeof game.rules !== \"object\") {\n issues.push(issue(\"rules\", \"INVALID_RULES\", \"Rules must be an object\"));\n } else {\n if (!game.rules.basic || typeof game.rules.basic !== \"object\") {\n issues.push(issue(\"rules.basic\", \"INVALID_BASIC_RULES\", \"Rules.basic must be an object\"));\n }\n if (!Array.isArray(game.rules.extra)) {\n issues.push(issue(\"rules.extra\", \"INVALID_EXTRA_RULES\", \"Rules.extra must be an array\"));\n }\n }\n if (!game.mode || typeof game.mode !== \"object\") {\n issues.push(issue(\"mode\", \"INVALID_MODE\", \"Mode must be an object\"));\n } else {\n if (!isNonEmptyString(game.mode.name)) {\n issues.push(issue(\"mode.name\", \"INVALID_MODE_NAME\", \"Mode name must be a non-empty string\"));\n }\n }\n if (!game.nextAction || typeof game.nextAction !== \"object\") {\n issues.push(issue(\"nextAction\", \"INVALID_NEXT_ACTION\", \"NextAction must be an object\"));\n } else if (game.nextAction.type !== \"action\" && game.nextAction.type !== \"step\") {\n issues.push(issue(\"nextAction.type\", \"INVALID_NEXT_ACTION_TYPE\", \"NextAction.type must be 'action' or 'step'\"));\n }\n\n return issues;\n};\n\nconst validateTile = (tile: unknown, path: string): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n if (!tile || typeof tile !== \"object\") {\n issues.push(issue(path, \"INVALID_TILE\", `Tile at ${path} must be an object`));\n return issues;\n }\n const t = tile as Record<string, unknown>;\n if (typeof t.type !== \"string\" || !validGrounds.has(t.type)) {\n issues.push(issue(`${path}.type`, \"INVALID_TILE_TYPE\", `Invalid terrain type at ${path}`));\n }\n if (typeof t.crowns !== \"number\" || t.crowns < 0) {\n issues.push(issue(`${path}.crowns`, \"INVALID_TILE_CROWNS\", `Invalid crowns at ${path}`));\n }\n return issues;\n};\n\nconst validatePlayers = (game: Game): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n if (!Array.isArray(game.players)) return issues;\n\n const playerIds = new Set<string>();\n for (let i = 0; i < game.players.length; i++) {\n const player = game.players[i]!;\n const path = `players[${i}]`;\n\n if (!isNonEmptyString(player.id)) {\n issues.push(issue(`${path}.id`, \"INVALID_PLAYER_ID\", `Player id must be a non-empty string`));\n } else if (playerIds.has(player.id)) {\n issues.push(issue(`${path}.id`, \"DUPLICATE_PLAYER_ID\", `Duplicate player id: ${player.id}`));\n } else {\n playerIds.add(player.id);\n }\n\n if (typeof player.name !== \"string\" || player.name.length < 3) {\n issues.push(issue(`${path}.name`, \"INVALID_PLAYER_NAME\", `Player name must be at least 3 characters`));\n }\n\n // Kingdom validation\n if (!Array.isArray(player.kingdom)) {\n issues.push(issue(`${path}.kingdom`, \"INVALID_KINGDOM\", `Kingdom must be a 2D array`));\n continue;\n }\n if (player.kingdom.length !== GRIDSIZE) {\n issues.push(issue(`${path}.kingdom`, \"INVALID_KINGDOM_GRID\", `Kingdom must have ${GRIDSIZE} rows, got ${player.kingdom.length}`));\n continue;\n }\n\n let castleCount = 0;\n for (let y = 0; y < player.kingdom.length; y++) {\n const row = player.kingdom[y]!;\n if (!Array.isArray(row) || row.length !== GRIDSIZE) {\n issues.push(issue(`${path}.kingdom[${y}]`, \"INVALID_KINGDOM_ROW\", `Kingdom row ${y} must have ${GRIDSIZE} columns`));\n continue;\n }\n for (let x = 0; x < row.length; x++) {\n const cell = row[x]!;\n issues.push(...validateTile(cell, `${path}.kingdom[${y}][${x}]`));\n if (cell && typeof cell === \"object\" && (cell as Record<string, unknown>).type === \"castle\") {\n castleCount++;\n }\n }\n }\n if (castleCount === 0) {\n issues.push(issue(`${path}.kingdom`, \"MISSING_CASTLE\", `Kingdom must have exactly one castle tile`, \"warning\"));\n } else if (castleCount > 1) {\n issues.push(issue(`${path}.kingdom`, \"MULTIPLE_CASTLES\", `Kingdom has ${castleCount} castle tiles, expected 1`));\n }\n }\n\n return issues;\n};\n\nconst validateDominoes = (game: Game): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n const allNumbers = new Set<number>();\n\n // Validate draw pile dominoes\n if (Array.isArray(game.dominoes)) {\n for (let i = 0; i < game.dominoes.length; i++) {\n const domino = game.dominoes[i]!;\n const path = `dominoes[${i}]`;\n\n if (!isPositiveInteger(domino.number)) {\n issues.push(issue(`${path}.number`, \"INVALID_DOMINO_NUMBER\", `Domino number must be a positive integer`));\n } else if (allNumbers.has(domino.number)) {\n issues.push(issue(`${path}.number`, \"DUPLICATE_DOMINO_NUMBER\", `Duplicate domino number: ${domino.number}`));\n } else {\n allNumbers.add(domino.number);\n }\n issues.push(...validateTile(domino.left, `${path}.left`));\n issues.push(...validateTile(domino.right, `${path}.right`));\n }\n }\n\n // Validate current (revealed) dominoes\n if (Array.isArray(game.currentDominoes)) {\n for (let i = 0; i < game.currentDominoes.length; i++) {\n const revealed = game.currentDominoes[i]!;\n const path = `currentDominoes[${i}]`;\n\n if (!revealed.domino || typeof revealed.domino !== \"object\") {\n issues.push(issue(`${path}.domino`, \"INVALID_REVEALED_DOMINO\", `Revealed domino must be an object`));\n continue;\n }\n\n const domino = revealed.domino;\n if (!isPositiveInteger(domino.number)) {\n issues.push(issue(`${path}.domino.number`, \"INVALID_DOMINO_NUMBER\", `Domino number must be a positive integer`));\n } else if (allNumbers.has(domino.number)) {\n issues.push(issue(`${path}.domino.number`, \"DUPLICATE_DOMINO_NUMBER\", `Duplicate domino number: ${domino.number}`));\n } else {\n allNumbers.add(domino.number);\n }\n issues.push(...validateTile(domino.left, `${path}.domino.left`));\n issues.push(...validateTile(domino.right, `${path}.domino.right`));\n\n // picked/lordId consistency\n if (revealed.picked && revealed.lordId === null) {\n issues.push(issue(`${path}`, \"PICKED_WITHOUT_LORD\", `Domino is marked as picked but has no lordId`));\n }\n if (!revealed.picked && revealed.lordId !== null) {\n issues.push(issue(`${path}`, \"UNPICKED_WITH_LORD\", `Domino is not picked but has a lordId`));\n }\n }\n }\n\n // Validate dominos picked by lords\n // Note: lord.dominoPicked is a copy of the domino from currentDominoes,\n // so the same number legitimately appears in both places.\n if (Array.isArray(game.lords)) {\n const lordPickedNumbers = new Set<number>();\n for (let i = 0; i < game.lords.length; i++) {\n const lord = game.lords[i]!;\n if (lord.dominoPicked) {\n const path = `lords[${i}].dominoPicked`;\n const domino = lord.dominoPicked;\n if (!isPositiveInteger(domino.number)) {\n issues.push(issue(`${path}.number`, \"INVALID_DOMINO_NUMBER\", `Domino number must be a positive integer`));\n } else if (lordPickedNumbers.has(domino.number)) {\n issues.push(issue(`${path}.number`, \"DUPLICATE_DOMINO_NUMBER\", `Duplicate domino number among lords: ${domino.number}`));\n } else {\n lordPickedNumbers.add(domino.number);\n }\n issues.push(...validateTile(domino.left, `${path}.left`));\n issues.push(...validateTile(domino.right, `${path}.right`));\n }\n }\n }\n\n return issues;\n};\n\nconst validateLords = (game: Game): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n if (!Array.isArray(game.lords)) return issues;\n\n const playerIds = new Set<string>(\n Array.isArray(game.players) ? game.players.map((p) => p.id) : [],\n );\n const lordIds = new Set<string>();\n\n for (let i = 0; i < game.lords.length; i++) {\n const lord = game.lords[i]!;\n const path = `lords[${i}]`;\n\n if (!isNonEmptyString(lord.id)) {\n issues.push(issue(`${path}.id`, \"INVALID_LORD_ID\", `Lord id must be a non-empty string`));\n } else if (lordIds.has(lord.id)) {\n issues.push(issue(`${path}.id`, \"DUPLICATE_LORD_ID\", `Duplicate lord id: ${lord.id}`));\n } else {\n lordIds.add(lord.id);\n }\n\n if (!isNonEmptyString(lord.playerId)) {\n issues.push(issue(`${path}.playerId`, \"INVALID_LORD_PLAYER_ID\", `Lord playerId must be a non-empty string`));\n } else if (playerIds.size > 0 && !playerIds.has(lord.playerId)) {\n issues.push(issue(`${path}.playerId`, \"LORD_PLAYER_NOT_FOUND\", `Lord references non-existent player: ${lord.playerId}`));\n }\n\n if (lord.turnEnded && (!lord.hasPick || !lord.hasPlace)) {\n issues.push(issue(path, \"INCONSISTENT_LORD_FLAGS\", `Lord has turnEnded=true but hasPick=${lord.hasPick}, hasPlace=${lord.hasPlace}`, \"warning\"));\n }\n }\n\n return issues;\n};\n\nconst validateGameFlow = (game: Game): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n if (!game.nextAction || typeof game.nextAction !== \"object\") return issues;\n\n const nextAction = game.nextAction;\n\n if (nextAction.type === \"action\") {\n const action = nextAction as { type: \"action\"; nextLord?: unknown; nextAction?: unknown };\n\n if (!isNonEmptyString(action.nextLord)) {\n issues.push(issue(\"nextAction.nextLord\", \"INVALID_NEXT_LORD\", \"nextLord must be a non-empty string\"));\n } else if (Array.isArray(game.lords) && !game.lords.some((l) => l.id === action.nextLord)) {\n issues.push(issue(\"nextAction.nextLord\", \"NEXT_LORD_NOT_FOUND\", `nextLord references non-existent lord: ${action.nextLord as string}`));\n }\n\n if (typeof action.nextAction !== \"string\" || !validPlayerActions.has(action.nextAction as string)) {\n issues.push(issue(\"nextAction.nextAction\", \"INVALID_PLAYER_ACTION\", `nextAction must be one of: ${[...validPlayerActions].join(\", \")}`));\n }\n } else if (nextAction.type === \"step\") {\n const step = nextAction as { type: \"step\"; step?: unknown };\n\n if (typeof step.step !== \"string\" || !validGameSteps.has(step.step as string)) {\n issues.push(issue(\"nextAction.step\", \"INVALID_GAME_STEP\", `step must be one of: ${[...validGameSteps].join(\", \")}`));\n }\n }\n\n return issues;\n};\n\nconst isSetupPhase = (game: Game): boolean => {\n if (game.nextAction?.type !== \"step\") return false;\n const step = (game.nextAction as { step: string }).step;\n return step === \"addPlayers\" || step === \"options\" || step === \"start\";\n};\n\nconst validateRules = (game: Game): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n if (!game.rules || typeof game.rules !== \"object\") return issues;\n\n // During setup phases (before players are added), basic rules may have zero values\n const allowZero = isSetupPhase(game);\n\n const basic = game.rules.basic;\n if (basic && typeof basic === \"object\") {\n const fields = [\"lords\", \"maxDominoes\", \"dominoesPerTurn\", \"maxTurns\", \"maxKingdomSize\"] as const;\n for (const field of fields) {\n const check = allowZero ? isNonNegativeInteger : isPositiveInteger;\n if (!check(basic[field])) {\n issues.push(issue(`rules.basic.${field}`, \"INVALID_BASIC_RULE_VALUE\", `rules.basic.${field} must be a positive integer`));\n }\n }\n }\n\n if (Array.isArray(game.rules.extra)) {\n for (let i = 0; i < game.rules.extra.length; i++) {\n const rule = game.rules.extra[i]!;\n if (!isNonEmptyString(rule.name)) {\n issues.push(issue(`rules.extra[${i}].name`, \"INVALID_EXTRA_RULE_NAME\", `Extra rule name must be a non-empty string`));\n }\n }\n }\n\n return issues;\n};\n\n/**\n * Validates the integrity of a game state.\n *\n * Use this function after deserializing or restoring a persisted game state\n * to detect corruptions before resuming gameplay.\n *\n * @param game - The game state to validate\n * @returns An array of validation issues. Empty array means the state is valid.\n *\n * @example\n * ```typescript\n * const issues = validateGameState(game);\n * if (issues.length > 0) {\n * console.error(\"Game state is corrupted:\", issues);\n * }\n * ```\n */\nexport const validateGameState = (game: Game): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n\n issues.push(...validateGameStructure(game));\n issues.push(...validatePlayers(game));\n issues.push(...validateDominoes(game));\n issues.push(...validateLords(game));\n issues.push(...validateGameFlow(game));\n issues.push(...validateRules(game));\n\n return issues;\n};\n","import type { BotStrategy } from \"./bot.js\";\nimport {\n randomStrategy,\n greedyStrategy,\n advancedStrategy,\n expertStrategy,\n} from \"./bot.js\";\n\n/**\n * Built-in strategy names.\n */\nexport type StrategyName = \"random\" | \"greedy\" | \"advanced\" | \"expert\";\n\nconst defaultStrategies: Record<string, BotStrategy> = {\n random: randomStrategy,\n greedy: greedyStrategy,\n advanced: advancedStrategy,\n expert: expertStrategy,\n};\n\n/**\n * Resolves a strategy by name. Checks custom strategies first, then defaults.\n * Returns undefined if the name is not found.\n */\nexport const getStrategy = (\n name: string,\n custom?: Record<string, BotStrategy>\n): BotStrategy | undefined => {\n return custom?.[name] ?? defaultStrategies[name];\n};\n\n/**\n * Returns the list of built-in strategy names.\n */\nexport const getStrategyNames = (): string[] => Object.keys(defaultStrategies);\n","import type {\n Domino,\n RevealsDomino,\n Kingdom,\n GameWithNextAction,\n GameState,\n Score,\n} from \"@core/domain/types/index.js\";\nimport { isGameWithNextAction } from \"@core/domain/types/game.js\";\nimport type { ValidPlacement } from \"./getValidPlacements.js\";\nimport type { GameEngine } from \"@core/portUserside/engine.js\";\nimport { placeDomino } from \"@core/domain/entities/kingdom.js\";\nimport { calculateScoreUseCase } from \"./calculateScore.js\";\nimport { getValidPlacementsUseCase } from \"./getValidPlacements.js\";\nimport { isOk } from \"@utils/result.js\";\nimport { getStrategy } from \"./botRegistry.js\";\n\n// ─── Types ───────────────────────────────────────────────────────────\n\n/**\n * Context provided to a bot strategy when choosing a domino to pick.\n */\nexport type PickContext = {\n game: GameWithNextAction;\n lordId: string;\n availableDominoes: RevealsDomino[];\n};\n\n/**\n * Context provided to a bot strategy when choosing where to place a domino.\n */\nexport type PlaceContext = {\n game: GameWithNextAction;\n lordId: string;\n domino: Domino;\n kingdom: Kingdom;\n validPlacements: ValidPlacement[];\n};\n\n/**\n * A bot strategy that decides which domino to pick and where to place it.\n * Strategies are stateless — all information comes from the context.\n */\nexport type BotStrategy = {\n chooseDomino: (context: PickContext) => number;\n choosePlacement: (context: PlaceContext) => ValidPlacement | null;\n};\n\n// ─── Helpers ─────────────────────────────────────────────────────────\n\nconst scoreKingdom = (kingdom: Kingdom): number => {\n const result = calculateScoreUseCase(kingdom);\n return isOk(result) ? result.value.points : 0;\n};\n\nconst simulatePlacement = (\n kingdom: Kingdom,\n domino: Domino,\n placement: ValidPlacement,\n maxKingdomSize: number\n): Kingdom | null => {\n const result = placeDomino(\n kingdom,\n placement.position,\n placement.rotation,\n domino,\n maxKingdomSize\n );\n return isOk(result) ? result.value : null;\n};\n\nconst bestPlacementScore = (\n kingdom: Kingdom,\n domino: Domino,\n placements: ValidPlacement[],\n maxKingdomSize: number\n): { placement: ValidPlacement; score: number; kingdom: Kingdom } | null => {\n let best: { placement: ValidPlacement; score: number; kingdom: Kingdom } | null = null;\n\n for (const placement of placements) {\n const newKingdom = simulatePlacement(kingdom, domino, placement, maxKingdomSize);\n if (!newKingdom) continue;\n const score = scoreKingdom(newKingdom);\n if (!best || score > best.score) {\n best = { placement, score, kingdom: newKingdom };\n }\n }\n\n return best;\n};\n\nconst getMaxKingdomSize = (game: GameWithNextAction): number =>\n game.rules.basic.maxKingdomSize;\n\nconst getLordAndPlayer = (game: GameWithNextAction, lordId: string) => {\n const lord = game.lords.find((l) => l.id === lordId);\n const player = lord\n ? game.players.find((p) => p.id === lord.playerId)\n : undefined;\n return { lord, player };\n};\n\nconst getNextBatchDominoes = (game: GameWithNextAction): Domino[] => {\n const perTurn = game.rules.basic.dominoesPerTurn;\n return [...game.dominoes]\n .slice(0, perTurn)\n .sort((a, b) => a.number - b.number);\n};\n\n// ─── Random Strategy ─────────────────────────────────────────────────\n\n/**\n * Bot strategy that makes random choices.\n * Picks a random available domino and places it at a random valid position.\n */\nexport const randomStrategy: BotStrategy = {\n chooseDomino: (context) => {\n const { availableDominoes } = context;\n const idx = Math.floor(Math.random() * availableDominoes.length);\n return availableDominoes[idx]!.domino.number;\n },\n\n choosePlacement: (context) => {\n const { validPlacements } = context;\n if (validPlacements.length === 0) return null;\n const idx = Math.floor(Math.random() * validPlacements.length);\n return validPlacements[idx]!;\n },\n};\n\n// ─── Greedy Strategy ─────────────────────────────────────────────────\n\n/**\n * Bot strategy that maximizes the immediate score.\n * Evaluates every valid placement and picks the one yielding the highest score.\n * When picking a domino, simulates the best placement for each option.\n */\nexport const greedyStrategy: BotStrategy = {\n chooseDomino: (context) => {\n const { game, lordId, availableDominoes } = context;\n const { player } = getLordAndPlayer(game, lordId);\n if (!player) return availableDominoes[0]!.domino.number;\n\n const maxSize = getMaxKingdomSize(game);\n let bestScore = -1;\n let bestPick = availableDominoes[0]!.domino.number;\n\n for (const rd of availableDominoes) {\n const placements = getValidPlacementsUseCase(\n player.kingdom,\n rd.domino,\n maxSize\n );\n const result = bestPlacementScore(\n player.kingdom,\n rd.domino,\n placements,\n maxSize\n );\n const score = result ? result.score : 0;\n if (score > bestScore) {\n bestScore = score;\n bestPick = rd.domino.number;\n }\n }\n\n return bestPick;\n },\n\n choosePlacement: (context) => {\n const { game, domino, kingdom, validPlacements } = context;\n if (validPlacements.length === 0) return null;\n\n const maxSize = getMaxKingdomSize(game);\n const result = bestPlacementScore(kingdom, domino, validPlacements, maxSize);\n return result ? result.placement : validPlacements[0]!;\n },\n};\n\n// ─── Advanced Strategy ───────────────────────────────────────────────\n\nconst evaluateWithLookahead = (\n kingdom: Kingdom,\n maxSize: number,\n nextDominoes: Domino[]\n): number => {\n if (nextDominoes.length === 0) return 0;\n\n let bestNextScore = 0;\n for (const nextDomino of nextDominoes) {\n const nextPlacements = getValidPlacementsUseCase(kingdom, nextDomino, maxSize);\n const result = bestPlacementScore(kingdom, nextDomino, nextPlacements, maxSize);\n if (result && result.score > bestNextScore) {\n bestNextScore = result.score;\n }\n }\n\n return bestNextScore;\n};\n\n/**\n * Bot strategy with 1-turn lookahead.\n * When making decisions, considers not just the immediate score but also\n * the best possible score achievable in the next turn by peeking at\n * the upcoming domino batch from the draw pile.\n */\nexport const advancedStrategy: BotStrategy = {\n chooseDomino: (context) => {\n const { game, lordId, availableDominoes } = context;\n const { player } = getLordAndPlayer(game, lordId);\n if (!player) return availableDominoes[0]!.domino.number;\n\n const maxSize = getMaxKingdomSize(game);\n const nextBatch = getNextBatchDominoes(game);\n\n let bestCombinedScore = -1;\n let bestPick = availableDominoes[0]!.domino.number;\n\n for (const rd of availableDominoes) {\n const placements = getValidPlacementsUseCase(\n player.kingdom,\n rd.domino,\n maxSize\n );\n const result = bestPlacementScore(\n player.kingdom,\n rd.domino,\n placements,\n maxSize\n );\n\n const immediateScore = result ? result.score : scoreKingdom(player.kingdom);\n const kingdomAfter = result ? result.kingdom : player.kingdom;\n const futureScore = evaluateWithLookahead(kingdomAfter, maxSize, nextBatch);\n const combined = immediateScore + futureScore * 0.8;\n\n if (combined > bestCombinedScore) {\n bestCombinedScore = combined;\n bestPick = rd.domino.number;\n }\n }\n\n return bestPick;\n },\n\n choosePlacement: (context) => {\n const { game, domino, kingdom, validPlacements } = context;\n if (validPlacements.length === 0) return null;\n\n const maxSize = getMaxKingdomSize(game);\n const nextBatch = getNextBatchDominoes(game);\n\n let bestCombinedScore = -1;\n let bestPlacement: ValidPlacement = validPlacements[0]!;\n\n for (const placement of validPlacements) {\n const newKingdom = simulatePlacement(kingdom, domino, placement, maxSize);\n if (!newKingdom) continue;\n\n const immediateScore = scoreKingdom(newKingdom);\n const futureScore = evaluateWithLookahead(newKingdom, maxSize, nextBatch);\n const combined = immediateScore + futureScore * 0.8;\n\n if (combined > bestCombinedScore) {\n bestCombinedScore = combined;\n bestPlacement = placement;\n }\n }\n\n return bestPlacement;\n },\n};\n\n// ─── Expert Strategy ─────────────────────────────────────────────────\n\n/** Maximum placements to evaluate per domino at each depth level (beam width) */\nconst EXPERT_BEAM_WIDTH = 2;\n\n/** Maximum search depth for the expert strategy */\nconst EXPERT_MAX_DEPTH = 2;\n\n/**\n * Ranks placements by immediate score gain (greedy heuristic)\n * and returns only the top N candidates for deeper evaluation.\n */\nconst topPlacements = (\n kingdom: Kingdom,\n domino: Domino,\n placements: ValidPlacement[],\n maxSize: number,\n limit: number\n): ValidPlacement[] => {\n if (placements.length <= limit) return placements;\n\n const scored = placements\n .map((p) => {\n const k = simulatePlacement(kingdom, domino, p, maxSize);\n return { placement: p, score: k ? scoreKingdom(k) : 0 };\n })\n .sort((a, b) => b.score - a.score);\n\n return scored.slice(0, limit).map((s) => s.placement);\n};\n\nconst expertEvaluate = (\n kingdom: Kingdom,\n remainingDominoes: Domino[],\n dominoesPerTurn: number,\n maxSize: number,\n depth: number\n): number => {\n if (depth <= 0 || remainingDominoes.length === 0) {\n return scoreKingdom(kingdom);\n }\n\n // Get next batch (sorted by number, as the engine does)\n const batch = [...remainingDominoes]\n .slice(0, dominoesPerTurn)\n .sort((a, b) => a.number - b.number);\n const afterBatch = remainingDominoes.slice(dominoesPerTurn);\n\n let bestScore = scoreKingdom(kingdom);\n\n for (const domino of batch) {\n const allPlacements = getValidPlacementsUseCase(kingdom, domino, maxSize);\n\n if (allPlacements.length === 0) {\n const score = expertEvaluate(\n kingdom,\n afterBatch,\n dominoesPerTurn,\n maxSize,\n depth - 1\n );\n if (score > bestScore) bestScore = score;\n continue;\n }\n\n // Prune: only evaluate top candidates by greedy score\n const candidates = topPlacements(\n kingdom,\n domino,\n allPlacements,\n maxSize,\n EXPERT_BEAM_WIDTH\n );\n\n for (const placement of candidates) {\n const newKingdom = simulatePlacement(kingdom, domino, placement, maxSize);\n if (!newKingdom) continue;\n\n const score = expertEvaluate(\n newKingdom,\n afterBatch,\n dominoesPerTurn,\n maxSize,\n depth - 1\n );\n if (score > bestScore) bestScore = score;\n }\n }\n\n return bestScore;\n};\n\n/**\n * Bot strategy that searches the game tree with beam-search pruning.\n * Explores all remaining turns, but limits the number of placements\n * evaluated per domino to the top candidates (by greedy score).\n * Since kingdoms are independent, this is a solo optimization (no adversarial search needed).\n */\nexport const expertStrategy: BotStrategy = {\n chooseDomino: (context) => {\n const { game, lordId, availableDominoes } = context;\n const { player } = getLordAndPlayer(game, lordId);\n if (!player) return availableDominoes[0]!.domino.number;\n\n const maxSize = getMaxKingdomSize(game);\n const perTurn = game.rules.basic.dominoesPerTurn;\n const turnsLeft = Math.min(\n game.rules.basic.maxTurns - game.turn,\n EXPERT_MAX_DEPTH\n );\n\n let bestScore = -1;\n let bestPick = availableDominoes[0]!.domino.number;\n\n for (const rd of availableDominoes) {\n const allPlacements = getValidPlacementsUseCase(\n player.kingdom,\n rd.domino,\n maxSize\n );\n\n if (allPlacements.length === 0) {\n const score = expertEvaluate(\n player.kingdom,\n game.dominoes,\n perTurn,\n maxSize,\n turnsLeft\n );\n if (score > bestScore) {\n bestScore = score;\n bestPick = rd.domino.number;\n }\n continue;\n }\n\n const candidates = topPlacements(\n player.kingdom,\n rd.domino,\n allPlacements,\n maxSize,\n EXPERT_BEAM_WIDTH\n );\n\n for (const placement of candidates) {\n const newKingdom = simulatePlacement(\n player.kingdom,\n rd.domino,\n placement,\n maxSize\n );\n if (!newKingdom) continue;\n\n const score = expertEvaluate(\n newKingdom,\n game.dominoes,\n perTurn,\n maxSize,\n turnsLeft\n );\n if (score > bestScore) {\n bestScore = score;\n bestPick = rd.domino.number;\n }\n }\n }\n\n return bestPick;\n },\n\n choosePlacement: (context) => {\n const { game, domino, kingdom, validPlacements } = context;\n if (validPlacements.length === 0) return null;\n\n const maxSize = getMaxKingdomSize(game);\n const perTurn = game.rules.basic.dominoesPerTurn;\n const turnsLeft = Math.min(\n game.rules.basic.maxTurns - game.turn,\n EXPERT_MAX_DEPTH\n );\n\n let bestScore = -1;\n let bestPlacement: ValidPlacement = validPlacements[0]!;\n\n for (const placement of validPlacements) {\n const newKingdom = simulatePlacement(kingdom, domino, placement, maxSize);\n if (!newKingdom) continue;\n\n const score = expertEvaluate(\n newKingdom,\n game.dominoes,\n perTurn,\n maxSize,\n turnsLeft\n );\n if (score > bestScore) {\n bestScore = score;\n bestPlacement = placement;\n }\n }\n\n return bestPlacement;\n },\n};\n\n// ─── playBotTurn ─────────────────────────────────────────────────────\n\n/**\n * Executes a single bot turn using the given strategy and engine.\n * Reads the current game state to determine the required action,\n * asks the strategy for a decision, and executes it via the engine.\n *\n * @param engine - The game engine instance\n * @param game - Current game state (must require a player action)\n * @param strategy - The bot strategy to use for decisions\n * @returns Updated game state after the bot's action\n */\nexport const playBotTurn = (\n engine: GameEngine,\n game: GameWithNextAction,\n strategy: BotStrategy\n): GameState => {\n const lordId = game.nextAction.nextLord;\n const action = game.nextAction.nextAction;\n\n if (action === \"pickDomino\") {\n const availableDominoes = game.currentDominoes.filter((d) => !d.picked);\n const dominoPick = strategy.chooseDomino({\n game,\n lordId,\n availableDominoes,\n });\n return engine.chooseDomino({ game, lordId, dominoPick });\n }\n\n if (action === \"placeDomino\") {\n const { lord, player } = getLordAndPlayer(game, lordId);\n if (!lord?.dominoPicked || !player) {\n return engine.discardDomino({ game, lordId });\n }\n\n const domino = lord.dominoPicked;\n const kingdom = player.kingdom;\n const maxSize = getMaxKingdomSize(game);\n const validPlacements = getValidPlacementsUseCase(kingdom, domino, maxSize);\n\n const placement = strategy.choosePlacement({\n game,\n lordId,\n domino,\n kingdom,\n validPlacements,\n });\n\n if (!placement) {\n return engine.discardDomino({ game, lordId });\n }\n\n return engine.placeDomino({\n game,\n lordId,\n position: placement.position,\n rotation: placement.rotation,\n });\n }\n\n // action === \"pass\"\n return engine.discardDomino({ game, lordId });\n};\n\n// ─── Mixed human/bot helpers ────────────────────────────────────────\n\n/**\n * Checks if the current turn belongs to a bot player.\n */\nexport const isBotTurn = (game: GameWithNextAction): boolean => {\n const lordId = game.nextAction.nextLord;\n const lord = game.lords.find((l) => l.id === lordId);\n const player = lord\n ? game.players.find((p) => p.id === lord.playerId)\n : undefined;\n return !!player?.bot;\n};\n\n/**\n * Plays all consecutive bot turns until a human turn or game end is reached.\n * Resolves each bot's strategy by name from the registry (or custom map).\n * Falls back to randomStrategy if the strategy name is not found.\n *\n * @param engine - The game engine instance\n * @param game - Current game state\n * @param customStrategies - Optional custom strategy map (name → BotStrategy)\n * @returns Updated game state paused at the next human turn or game end\n */\nexport const playBotTurns = (\n engine: GameEngine,\n game: GameState,\n customStrategies?: Record<string, BotStrategy>\n): GameState => {\n let current = game;\n\n while (isGameWithNextAction(current) && isBotTurn(current)) {\n const lordId = current.nextAction.nextLord;\n const lord = current.lords.find((l) => l.id === lordId);\n const player = lord\n ? current.players.find((p) => p.id === lord.playerId)\n : undefined;\n const strategyName = player?.bot?.strategyName ?? \"random\";\n const strategy =\n getStrategy(strategyName, customStrategies) ?? randomStrategy;\n current = playBotTurn(engine, current, strategy);\n }\n\n return current;\n};\n","import type {\n GameState,\n Position,\n Rotation,\n} from \"@core/domain/types/index.js\";\nimport type { GameEngine } from \"@core/portUserside/engine.js\";\nimport type { PlayerInput } from \"@application/commands/addPlayersCommand.js\";\n\n// ─── Types ──────────────────────────────────────────────────────────\n\n/**\n * The types of state-changing actions that can be recorded.\n */\nexport type ActionType =\n | \"createGame\"\n | \"addPlayers\"\n | \"addExtraRules\"\n | \"startGame\"\n | \"chooseDomino\"\n | \"placeDomino\"\n | \"discardDomino\";\n\n/**\n * Payload types for each action, containing only the command parameters\n * (excluding the game state, which is too large to store).\n */\nexport type ActionPayloadMap = {\n createGame: { mode: string; seed?: string };\n addPlayers: { players: PlayerInput[] };\n addExtraRules: { extraRules: string[] };\n startGame: Record<string, never>;\n chooseDomino: { lordId: string; dominoPick: number };\n placeDomino: { lordId: string; position: Position; rotation: Rotation };\n discardDomino: { lordId: string };\n};\n\n/**\n * A single recorded action in the game log.\n */\nexport type ActionEntry<T extends ActionType = ActionType> = {\n /** Auto-incrementing index (0-based) */\n id: number;\n /** Timestamp when the action was recorded (Date.now()) */\n timestamp: number;\n /** The type of action performed */\n action: T;\n /** Command parameters (excludes game state) */\n payload: ActionPayloadMap[T];\n /** Turn number after the action was applied */\n turn: number;\n};\n\n/**\n * An immutable log of all actions performed during a game.\n * Can be used to replay a game or analyze player decisions.\n *\n * @example\n * ```typescript\n * const { engine, getLog } = wrapWithActionLog(baseEngine);\n * let game = engine.createGame({ mode: 'Classic' });\n * game = engine.addPlayers({ game, players: ['Alice', 'Bob'] });\n * // ... play the game ...\n * const log = getLog();\n * console.log(log.entries); // all actions recorded\n * ```\n */\nexport type GameActionLog = {\n /** The game ID this log belongs to */\n gameId: string;\n /** Immutable array of recorded actions */\n entries: readonly ActionEntry[];\n};\n\n// ─── Construction ───────────────────────────────────────────────────\n\n/**\n * Creates an empty action log for a game.\n */\nexport const createActionLog = (gameId: string): GameActionLog => ({\n gameId,\n entries: [],\n});\n\n/**\n * Appends an action to the log (immutable — returns a new log).\n */\nexport const appendAction = (\n log: GameActionLog,\n entry: Omit<ActionEntry, \"id\" | \"timestamp\">,\n): GameActionLog => ({\n ...log,\n entries: [\n ...log.entries,\n {\n ...entry,\n id: log.entries.length,\n timestamp: Date.now(),\n },\n ],\n});\n\n// ─── Queries ────────────────────────────────────────────────────────\n\n/**\n * Returns all entries in the log.\n */\nexport const getActions = (log: GameActionLog): readonly ActionEntry[] =>\n log.entries;\n\n/**\n * Returns entries filtered by action type.\n */\nexport const getActionsByType = (\n log: GameActionLog,\n type: ActionType,\n): readonly ActionEntry[] => log.entries.filter((e) => e.action === type);\n\n/**\n * Returns entries filtered by turn number.\n */\nexport const getActionsByTurn = (\n log: GameActionLog,\n turn: number,\n): readonly ActionEntry[] => log.entries.filter((e) => e.turn === turn);\n\n// ─── Engine Wrapper ─────────────────────────────────────────────────\n\n/**\n * Wraps a GameEngine to automatically record every state-changing action.\n * Read-only methods are passed through unchanged.\n *\n * @param engine - The base game engine to wrap\n * @returns An object with the wrapped engine and a getLog() accessor\n *\n * @example\n * ```typescript\n * const { engine: logged, getLog } = wrapWithActionLog(baseEngine);\n * let game = logged.createGame({ mode: 'Classic' });\n * // ... play ...\n * const log = getLog(); // retrieve the full action log\n * ```\n */\nexport const wrapWithActionLog = (\n engine: GameEngine,\n): { engine: GameEngine; getLog: () => GameActionLog } => {\n let log = createActionLog(\"\");\n\n const record = <T extends ActionType>(\n action: T,\n payload: ActionPayloadMap[T],\n turn: number,\n ): void => {\n log = appendAction(log, { action, payload, turn });\n };\n\n const wrappedEngine: GameEngine = {\n // Read-only methods — pass through\n getModes: (cmd) => engine.getModes(cmd),\n getExtraRules: (cmd) => engine.getExtraRules(cmd),\n calculateScore: (cmd) => engine.calculateScore(cmd),\n getValidPlacements: (cmd) => engine.getValidPlacements(cmd),\n canPlaceDomino: (cmd) => engine.canPlaceDomino(cmd),\n serialize: (cmd) => engine.serialize(cmd),\n deserialize: (cmd) => engine.deserialize(cmd),\n getResults: (cmd) => engine.getResults(cmd),\n getDynastyResults: (cmd) => engine.getDynastyResults(cmd),\n\n // State-changing methods — record after execution\n createGame: (cmd) => {\n const game = engine.createGame(cmd);\n log = createActionLog(game.id);\n record(\"createGame\", { mode: cmd.mode, seed: cmd.seed }, game.turn);\n return game;\n },\n\n addPlayers: (cmd) => {\n const game = engine.addPlayers(cmd);\n record(\"addPlayers\", { players: cmd.players }, game.turn);\n return game;\n },\n\n addExtraRules: (cmd) => {\n const game = engine.addExtraRules(cmd);\n record(\"addExtraRules\", { extraRules: cmd.extraRules }, game.turn);\n return game;\n },\n\n startGame: (cmd) => {\n const game = engine.startGame(cmd);\n record(\"startGame\", {}, game.turn);\n return game;\n },\n\n chooseDomino: (cmd) => {\n const game = engine.chooseDomino(cmd);\n record(\n \"chooseDomino\",\n { lordId: cmd.lordId, dominoPick: cmd.dominoPick },\n game.turn,\n );\n return game;\n },\n\n placeDomino: (cmd) => {\n const game = engine.placeDomino(cmd);\n record(\n \"placeDomino\",\n {\n lordId: cmd.lordId,\n position: cmd.position,\n rotation: cmd.rotation,\n },\n game.turn,\n );\n return game;\n },\n\n discardDomino: (cmd) => {\n const game = engine.discardDomino(cmd);\n record(\"discardDomino\", { lordId: cmd.lordId }, game.turn);\n return game;\n },\n };\n\n return {\n engine: wrappedEngine,\n getLog: () => log,\n };\n};\n\n// ─── Replay ─────────────────────────────────────────────────────────\n\n/**\n * Replays all actions from a log on a fresh engine to reconstruct the final game state.\n * The engine should use the same configuration (especially shuffleMethod) as the original game\n * to guarantee deterministic results when a seed is present.\n *\n * @param engine - A game engine instance (should match original config)\n * @param log - The action log to replay\n * @returns The final game state after replaying all actions\n */\nexport const replayActions = (\n engine: GameEngine,\n log: GameActionLog,\n): GameState => {\n if (log.entries.length === 0) {\n throw new Error(\"Cannot replay an empty action log\");\n }\n\n const firstEntry = log.entries[0];\n if (firstEntry?.action !== \"createGame\") {\n throw new Error(\"Action log must start with a createGame action\");\n }\n\n const firstPayload = firstEntry.payload as ActionPayloadMap[\"createGame\"];\n let game: GameState = engine.createGame({\n mode: firstPayload.mode,\n seed: firstPayload.seed,\n });\n\n for (let i = 1; i < log.entries.length; i++) {\n const entry = log.entries[i];\n if (!entry) continue;\n\n switch (entry.action) {\n case \"createGame\": {\n const payload = entry.payload as ActionPayloadMap[\"createGame\"];\n game = engine.createGame({ mode: payload.mode, seed: payload.seed });\n break;\n }\n case \"addPlayers\": {\n const payload = entry.payload as ActionPayloadMap[\"addPlayers\"];\n game = engine.addPlayers({ game, players: payload.players });\n break;\n }\n case \"addExtraRules\": {\n const payload = entry.payload as ActionPayloadMap[\"addExtraRules\"];\n game = engine.addExtraRules({\n game,\n extraRules: payload.extraRules,\n });\n break;\n }\n case \"startGame\": {\n game = engine.startGame({ game });\n break;\n }\n case \"chooseDomino\": {\n const payload = entry.payload as ActionPayloadMap[\"chooseDomino\"];\n game = engine.chooseDomino({\n game,\n lordId: payload.lordId,\n dominoPick: payload.dominoPick,\n });\n break;\n }\n case \"placeDomino\": {\n const payload = entry.payload as ActionPayloadMap[\"placeDomino\"];\n game = engine.placeDomino({\n game,\n lordId: payload.lordId,\n position: payload.position,\n rotation: payload.rotation,\n });\n break;\n }\n case \"discardDomino\": {\n const payload = entry.payload as ActionPayloadMap[\"discardDomino\"];\n game = engine.discardDomino({\n game,\n lordId: payload.lordId,\n });\n break;\n }\n }\n }\n\n return game;\n};\n","import type { GameState } from \"@core/domain/types/index.js\";\nimport { UndoError, RedoError } from \"@core/domain/errors/domainErrors.js\";\n\n/**\n * Manages a history of game states for undo/redo support.\n * Uses a snapshot-based approach: each state is stored as a full GameState.\n *\n * @example\n * ```typescript\n * let history = createGameHistory(initialGame);\n * const newGame = engine.chooseDomino({ game: history.current, ... });\n * history = pushState(history, newGame);\n * history = undo(history); // back to initialGame\n * history = redo(history); // forward to newGame\n * ```\n */\nexport type GameHistory = {\n /** The current game state */\n current: GameState;\n /** Stack of previous states (most recent last) */\n past: GameState[];\n /** Stack of undone states (most recent last) */\n future: GameState[];\n};\n\n/**\n * Creates a new game history initialized with a game state.\n *\n * @param initialState - The starting game state\n * @returns A new GameHistory with empty past and future\n */\nexport const createGameHistory = (initialState: GameState): GameHistory => ({\n current: initialState,\n past: [],\n future: [],\n});\n\n/**\n * Records a new game state in the history.\n * The current state is pushed to the past stack, and the future stack is cleared\n * (branching from a previous undo point discards the old future).\n *\n * @param history - The current history\n * @param newState - The new game state to record\n * @returns Updated history with the new state as current\n */\nexport const pushState = (\n history: GameHistory,\n newState: GameState\n): GameHistory => ({\n current: newState,\n past: [...history.past, history.current],\n future: [],\n});\n\n/**\n * Reverts to the previous game state.\n * The current state is moved to the future stack for potential redo.\n *\n * @param history - The current history\n * @returns Updated history with the previous state as current\n * @throws {UndoError} If there is no previous state to revert to\n */\nexport const undo = (history: GameHistory): GameHistory => {\n if (history.past.length === 0) {\n throw new UndoError();\n }\n\n const previous = history.past[history.past.length - 1]!;\n return {\n current: previous,\n past: history.past.slice(0, -1),\n future: [...history.future, history.current],\n };\n};\n\n/**\n * Re-applies a previously undone game state.\n * The current state is moved to the past stack.\n *\n * @param history - The current history\n * @returns Updated history with the next undone state as current\n * @throws {RedoError} If there is no undone state to re-apply\n */\nexport const redo = (history: GameHistory): GameHistory => {\n if (history.future.length === 0) {\n throw new RedoError();\n }\n\n const next = history.future[history.future.length - 1]!;\n return {\n current: next,\n past: [...history.past, history.current],\n future: history.future.slice(0, -1),\n };\n};\n\n/**\n * Checks whether an undo operation is available.\n */\nexport const canUndo = (history: GameHistory): boolean =>\n history.past.length > 0;\n\n/**\n * Checks whether a redo operation is available.\n */\nexport const canRedo = (history: GameHistory): boolean =>\n history.future.length > 0;\n\n/**\n * Clears the undo/redo history, keeping only the current state.\n *\n * @param history - The current history\n * @returns A new history with empty past and future\n */\nexport const clearHistory = (history: GameHistory): GameHistory => ({\n current: history.current,\n past: [],\n future: [],\n});\n\n/**\n * Returns the number of states in the past and future stacks.\n */\nexport const getHistorySize = (\n history: GameHistory\n): { past: number; future: number } => ({\n past: history.past.length,\n future: history.future.length,\n});\n","import type { GameEngine } from \"@core/portUserside/engine\";\nimport { type DebugOptions, wrapWithDebug } from \"@core/useCases/gameDebug.js\";\nimport { wrapWithEvents } from \"@core/useCases/gameEvents.js\";\nimport { configureEngine, type EngineConfig } from \"./config.js\";\n\n// Commands\nexport * from \"@application/commands/index.js\";\nexport { validateGameState } from \"@core/domain/entities/validateGameState.js\";\n// Domain errors\nexport * from \"@core/domain/errors/domainErrors.js\";\n// Domain types\nexport * from \"@core/domain/types/index.js\";\n// i18n\nexport * from \"@core/i18n/translations.js\";\n// Ports\nexport * from \"@core/portServerside/index.js\";\nexport * from \"@core/portUserside/engine.js\";\n// Bot / AI player\nexport {\n advancedStrategy,\n type BotStrategy,\n expertStrategy,\n greedyStrategy,\n isBotTurn,\n type PickContext,\n type PlaceContext,\n playBotTurn,\n playBotTurns,\n randomStrategy,\n} from \"@core/useCases/bot.js\";\n// Bot strategy registry\nexport {\n getStrategy,\n getStrategyNames,\n type StrategyName,\n} from \"@core/useCases/botRegistry.js\";\n// Action log (game history / replay)\nexport {\n type ActionEntry,\n type ActionPayloadMap,\n type ActionType,\n appendAction,\n createActionLog,\n type GameActionLog,\n getActions,\n getActionsByTurn,\n getActionsByType,\n replayActions,\n wrapWithActionLog,\n} from \"@core/useCases/gameActionLog.js\";\n// Debug mode\nexport {\n type DebugLogEntry,\n type DebugLogger,\n type DebugLogLevel,\n type DebugOptions,\n type GameStateSummary,\n summarizeGameState,\n wrapWithDebug,\n} from \"@core/useCases/gameDebug.js\";\n// Game events\nexport {\n type GameEventCallbacks,\n wrapWithEvents,\n} from \"@core/useCases/gameEvents.js\";\n// History (undo/redo)\nexport {\n canRedo,\n canUndo,\n clearHistory,\n createGameHistory,\n type GameHistory,\n getHistorySize,\n pushState,\n redo,\n undo,\n} from \"@core/useCases/gameHistory.js\";\nexport type { DynastyResult } from \"@core/useCases/getDynastyResult.js\";\n// Use cases (for advanced usage)\nexport type { ValidPlacement } from \"@core/useCases/getValidPlacements.js\";\nexport {\n createSavePoint,\n deserializeGame,\n type GameSavePoint,\n restoreFromSavePoint,\n serializeGame,\n} from \"@core/useCases/serialization.js\";\n// Configuration\nexport type { EngineConfig };\n\n/**\n * Creates a new Kingdomino game engine instance.\n *\n * @param config - Configuration options for the engine\n * @returns A fully configured GameEngine instance\n *\n * @example\n * ```typescript\n * // Basic usage\n * const engine = createGameEngine({});\n *\n * // With logging\n * const engine = createGameEngine({ logging: true });\n *\n * // With event callbacks\n * const engine = createGameEngine({\n * events: {\n * onDominoPlaced: ({ lordId }) => console.log(`${lordId} placed`),\n * onGameEnd: () => console.log('Game over!'),\n * },\n * });\n * ```\n */\nexport const createGameEngine = (config: Partial<EngineConfig>): GameEngine => {\n const {\n createGameHandler,\n getModesHandler,\n getExtraRulesHandler,\n addPlayersHandler,\n addExtraRulesHandler,\n startGameHandler,\n chooseDominoHandler,\n placeDominoHandler,\n discardDominoHandler,\n getResultHandler,\n calculateScoreHandler,\n getValidPlacementsHandler,\n canPlaceDominoHandler,\n serializeGameHandler,\n deserializeGameHandler,\n getDynastyResultHandler,\n } = configureEngine(config);\n\n let engine: GameEngine = {\n getModes: (command) => getModesHandler(command),\n getExtraRules: (command) => getExtraRulesHandler(command),\n createGame: (command) => createGameHandler(command),\n addPlayers: (command) => addPlayersHandler(command),\n addExtraRules: (command) => addExtraRulesHandler(command),\n startGame: (command) => startGameHandler(command),\n chooseDomino: (command) => chooseDominoHandler(command),\n placeDomino: (command) => placeDominoHandler(command),\n discardDomino: (command) => discardDominoHandler(command),\n getResults: (command) => getResultHandler(command),\n calculateScore: (command) => calculateScoreHandler(command),\n getValidPlacements: (command) => getValidPlacementsHandler(command),\n canPlaceDomino: (command) => canPlaceDominoHandler(command),\n serialize: (command) => serializeGameHandler(command),\n deserialize: (command) => deserializeGameHandler(command),\n getDynastyResults: (command) => getDynastyResultHandler(command),\n };\n\n if (config.events) {\n engine = wrapWithEvents(engine, config.events);\n }\n\n if (config.debug) {\n const debugOptions: DebugOptions | undefined =\n typeof config.debug === \"object\" ? config.debug : undefined;\n engine = wrapWithDebug(engine, debugOptions);\n }\n\n return engine;\n};\n"],"mappings":"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","names":["err","durationMs","getResultUseCase","calculateScoreUseCase","result","shuffleMethod","uuidMethod","shuffleMethod","lord","next","updatedCurrentDominoes","uuidMethod","uuidMethod","shuffleMethod","createGameHandler","getModesHandler","getExtraRulesHandler","addPlayersHandler","addExtraRulesHandler","startGameHandler","chooseDominoHandler","placeDominoHandler","discardDominoHandler","getResultHandler","calculateScoreHandler","getValidPlacementsHandler","canPlaceDominoHandler","serializeGameHandler","deserializeGameHandler","getDynastyResultHandler"]}
1
+ {"version":3,"sources":["../src/core/domain/types/game.ts","../src/core/useCases/gameDebug.ts","../src/core/useCases/gameEvents.ts","../src/adapterServerside/consoleLogger.ts","../src/datasources/dominoes.json","../src/adapterServerside/jsonDominoes.ts","../src/datasources/modes.json","../src/adapterServerside/jsonModes.ts","../src/datasources/rules.json","../src/adapterServerside/jsonRules.ts","../src/adapterServerside/shuffle.ts","../src/adapterServerside/uuid.ts","../src/core/domain/errors/domainErrors.ts","../src/core/i18n/translations.ts","../src/utils/result.ts","../src/application/handlers/addExtraRulesHandler.ts","../src/application/handlers/addPlayersHandler.ts","../src/application/handlers/calculateScoreHandler.ts","../src/application/handlers/canPlaceDominoHandler.ts","../src/application/handlers/chooseDominoHandler.ts","../src/application/handlers/createGameHandler.ts","../src/application/handlers/discardDominoHandler.ts","../src/application/handlers/getDynastyResultHandler.ts","../src/application/handlers/getExtraRulesHandler.ts","../src/application/handlers/getModesHandler.ts","../src/application/handlers/getResultHandler.ts","../src/application/handlers/getValidPlacementsHandler.ts","../src/application/handlers/placeDominoHandler.ts","../src/core/useCases/serialization.ts","../src/application/handlers/serializeGameHandler.ts","../src/application/handlers/startGameHandler.ts","../src/core/domain/types/kingdom.ts","../src/core/domain/types/domino.ts","../src/core/domain/types/player.ts","../src/core/domain/entities/rule.ts","../src/utils/seededShuffle.ts","../src/core/useCases/addExtraRules.ts","../src/core/domain/entities/domino.ts","../src/core/domain/entities/kingdom.ts","../src/core/domain/entities/player.ts","../src/core/useCases/addPlayers.ts","../src/core/useCases/calculateScore.ts","../src/core/domain/entities/lord.ts","../src/core/useCases/chooseDomino.ts","../src/core/domain/entities/game.ts","../src/core/domain/entities/mode.ts","../src/core/useCases/createGame.ts","../src/core/useCases/getValidPlacements.ts","../src/core/useCases/discardDomino.ts","../src/core/useCases/getDynastyResult.ts","../src/core/useCases/getExtraRules.ts","../src/core/useCases/getModes.ts","../src/core/useCases/getResult.ts","../src/core/useCases/placeDomino.ts","../src/core/useCases/startGame.ts","../src/config.ts","../src/core/domain/entities/validateGameState.ts","../src/core/useCases/botRegistry.ts","../src/core/useCases/bot.ts","../src/core/useCases/gameActionLog.ts","../src/core/useCases/gameHistory.ts","../src/index.ts"],"sourcesContent":["import type { Result } from \"@utils/result.js\";\nimport type { Domino, RevealsDomino } from \"./domino.js\";\nimport type { Lord } from \"./lord.js\";\nimport type { GameMode } from \"./mode.js\";\nimport type { Player, PlayerActions } from \"./player.js\";\nimport type { SelectedRules } from \"./rule.js\";\nimport type { ObjectValues } from \"./utils.js\";\n\n/**\n * Represents the complete state of a Kingdomino game.\n * This is the main aggregate containing all game data.\n */\nexport type Game = {\n /** Unique identifier for the game */\n id: string;\n /** Remaining dominoes in the draw pile */\n dominoes: Domino[];\n /** Currently revealed dominoes available for picking */\n currentDominoes: RevealsDomino[];\n /** Players participating in the game with their kingdoms */\n players: Player[];\n /** Lords (player tokens) used for turn order and domino selection */\n lords: Lord[];\n /** Current turn number (1-based) */\n turn: number;\n /** Next required action or game step */\n nextAction: NextAction | NextStep;\n /** Active rules for this game */\n rules: SelectedRules;\n /** Game mode being played */\n mode: GameMode;\n /** Optional seed for deterministic shuffle (replays, sharing) */\n seed?: string;\n};\n\n/**\n * Available game steps representing phases of game setup and completion.\n */\nexport const gameSteps = {\n /** Waiting for players to be added */\n addPlayers: \"addPlayers\",\n /** Optional rules selection phase */\n options: \"options\",\n /** Ready to start the game */\n start: \"start\",\n /** Game has ended, results available */\n result: \"result\",\n} as const;\n\n/** Union type of all possible game steps */\nexport type GameSteps = ObjectValues<typeof gameSteps>;\n\n/**\n * Represents a player action that needs to be performed.\n * Used during active gameplay.\n */\nexport type NextAction = {\n /** Discriminator for action type */\n type: \"action\";\n /** ID of the lord who must perform the action */\n nextLord: string;\n /** The action the lord must perform */\n nextAction: PlayerActions;\n};\n\n/**\n * Represents a game phase transition.\n * Used during setup and game end.\n */\nexport type NextStep = {\n /** Discriminator for step type */\n type: \"step\";\n /** The current game step/phase */\n step: GameSteps;\n};\n\n/** Game state where a player action is required */\nexport type GameWithNextAction = Game & { nextAction: NextAction };\n\n/** Game state where a phase transition is occurring */\nexport type GameWithNextStep = Game & { nextAction: NextStep };\n\n/** Union of all possible game states */\nexport type GameState = GameWithNextAction | GameWithNextStep;\n\n/** Result wrapper for game state operations */\nexport type GameStateResult = Result<GameState>;\n\n/**\n * Type guard to check if the game requires a player action.\n * @param game - The game state to check\n * @returns True if the game is waiting for a player action\n */\nexport const isGameWithNextAction = (\n game: GameWithNextAction | GameWithNextStep\n): game is GameWithNextAction => {\n return game.nextAction.type === \"action\";\n};\n\n/**\n * Type guard to check if the game is in a phase transition.\n * @param game - The game state to check\n * @returns True if the game is transitioning between phases\n */\nexport const isGameWithNextStep = (\n game: GameWithNextAction | GameWithNextStep\n): game is GameWithNextStep => {\n return game.nextAction.type === \"step\";\n};\n\n/**\n * Represents the score calculation for a kingdom.\n */\nexport type Score = {\n /** Total points earned */\n points: number;\n /** Size of the largest contiguous property */\n maxPropertiesSize: number;\n /** Total number of crowns in the kingdom */\n totalCrowns: number;\n};\n\n/**\n * Score result for a specific player.\n */\nexport type ScoreResult = {\n /** Player's unique identifier */\n playerId: string;\n /** Player's display name */\n playerName: string;\n /** Detailed score breakdown */\n details: Score;\n};\n\n/**\n * Final result including ranking position.\n */\nexport type FinalResult = ScoreResult & {\n /** Player's final position (1 = winner) */\n position: number;\n};\n\n/** Game state with final results calculated */\nexport type GameWithResults = Game & { result: FinalResult[] };\n","import { isGameWithNextAction } from \"@core/domain/types/game.js\";\nimport type { GameState } from \"@core/domain/types/index.js\";\nimport type { GameEngine } from \"@core/portUserside/engine.js\";\n\n// ─── Types ──────────────────────────────────────────────────────────\n\n/**\n * Debug log verbosity level.\n * - `minimal`: method name + phase only\n * - `standard`: + game state summary + key params\n * - `verbose`: + full game state JSON dump\n */\nexport type DebugLogLevel = \"minimal\" | \"standard\" | \"verbose\";\n\n/**\n * Summary of the current game state, extracted for quick inspection.\n */\nexport type GameStateSummary = {\n gameId: string;\n turn: number;\n nextAction: string;\n playersCount: number;\n dominoesRemaining: number;\n currentDominoesCount: number;\n lordsCount: number;\n};\n\n/**\n * A single debug log entry emitted by the debug wrapper.\n */\nexport type DebugLogEntry = {\n timestamp: string;\n method: string;\n phase: \"before\" | \"after\" | \"error\";\n summary: GameStateSummary | null;\n params?: Record<string, unknown>;\n error?: string;\n durationMs?: number;\n fullState?: GameState;\n};\n\n/**\n * Custom debug logger interface.\n * Consumers can provide their own to redirect debug output.\n */\nexport type DebugLogger = {\n log: (entry: DebugLogEntry) => void;\n};\n\n/**\n * Configuration for the debug wrapper.\n */\nexport type DebugOptions = {\n /** Custom debug logger. Defaults to console-based logger. */\n logger?: DebugLogger;\n /** Verbosity level. Defaults to \"standard\". */\n level?: DebugLogLevel;\n};\n\n// ─── Helpers ────────────────────────────────────────────────────────\n\n/**\n * Extracts a concise summary from a game state object.\n */\nexport const summarizeGameState = (game: GameState): GameStateSummary => {\n const nextAction = isGameWithNextAction(game)\n ? `action:${game.nextAction.nextAction}`\n : `step:${game.nextAction.step}`;\n\n return {\n gameId: game.id,\n turn: game.turn,\n nextAction,\n playersCount: game.players.length,\n dominoesRemaining: game.dominoes.length,\n currentDominoesCount: game.currentDominoes.length,\n lordsCount: game.lords.length,\n };\n};\n\nconst defaultDebugLogger: DebugLogger = {\n log: (entry: DebugLogEntry) => {\n const phase = entry.phase.toUpperCase().padEnd(5);\n const base = `[KDomino:Debug] ${entry.timestamp} ${phase} ${entry.method}`;\n\n if (entry.phase === \"error\") {\n console.error(`${base} | error: ${entry.error}`);\n return;\n }\n\n if (entry.summary) {\n const s = entry.summary;\n console.log(\n `${base} | turn=${s.turn} next=${s.nextAction} players=${s.playersCount} dominoes=${s.dominoesRemaining}`,\n );\n } else {\n console.log(base);\n }\n },\n};\n\nconst isGameState = (value: unknown): value is GameState => {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"id\" in value &&\n \"nextAction\" in value &&\n \"players\" in value &&\n \"dominoes\" in value\n );\n};\n\ntype CommandWithGame = { game: GameState; [key: string]: unknown };\n\nconst hasGameInCommand = (cmd: unknown): cmd is CommandWithGame => {\n return (\n typeof cmd === \"object\" &&\n cmd !== null &&\n \"game\" in cmd &&\n isGameState((cmd as CommandWithGame).game)\n );\n};\n\nconst extractParams = (cmd: unknown): Record<string, unknown> | undefined => {\n if (typeof cmd !== \"object\" || cmd === null) return undefined;\n\n const record = cmd as Record<string, unknown>;\n const params: Record<string, unknown> = {};\n\n if (\"mode\" in record) params.mode = record.mode;\n if (\"lordId\" in record) params.lordId = record.lordId;\n if (\"dominoPick\" in record) params.dominoPick = record.dominoPick;\n if (\"position\" in record) params.position = record.position;\n if (\"rotation\" in record) params.rotation = record.rotation;\n if (\"players\" in record) params.players = record.players;\n if (\"extraRules\" in record) params.extraRules = record.extraRules;\n\n return Object.keys(params).length > 0 ? params : undefined;\n};\n\n// ─── Wrapper ────────────────────────────────────────────────────────\n\nconst wrapMethod = <TArgs, TResult>(\n method: string,\n fn: (cmd: TArgs) => TResult,\n logger: DebugLogger,\n level: DebugLogLevel,\n): ((cmd: TArgs) => TResult) => {\n return (cmd: TArgs) => {\n const timestamp = new Date().toISOString();\n\n // Before\n const beforeSummary =\n level !== \"minimal\" && hasGameInCommand(cmd)\n ? summarizeGameState(cmd.game)\n : null;\n\n const beforeEntry: DebugLogEntry = {\n timestamp,\n method,\n phase: \"before\",\n summary: beforeSummary,\n params: level !== \"minimal\" ? extractParams(cmd) : undefined,\n };\n\n logger.log(beforeEntry);\n\n // Execute\n const start = performance.now();\n let result: TResult;\n try {\n result = fn(cmd);\n } catch (err) {\n const durationMs = Math.round((performance.now() - start) * 100) / 100;\n const errorEntry: DebugLogEntry = {\n timestamp: new Date().toISOString(),\n method,\n phase: \"error\",\n summary: beforeSummary,\n error: err instanceof Error ? err.message : String(err),\n durationMs,\n };\n logger.log(errorEntry);\n throw err;\n }\n\n const durationMs = Math.round((performance.now() - start) * 100) / 100;\n\n // After\n const afterSummary =\n level !== \"minimal\" && isGameState(result)\n ? summarizeGameState(result as GameState)\n : null;\n\n const afterEntry: DebugLogEntry = {\n timestamp: new Date().toISOString(),\n method,\n phase: \"after\",\n summary: afterSummary,\n durationMs,\n fullState:\n level === \"verbose\" && isGameState(result)\n ? (result as GameState)\n : undefined,\n };\n\n logger.log(afterEntry);\n\n return result;\n };\n};\n\n/**\n * Wraps a GameEngine to emit detailed debug log entries before and after each method call.\n * Useful for UI developers to inspect engine behavior at every step.\n *\n * @param engine - The base game engine to wrap\n * @param options - Debug configuration (logger, verbosity level)\n * @returns A new GameEngine that emits debug logs\n *\n * @example\n * ```typescript\n * const debugEngine = wrapWithDebug(engine, { level: \"verbose\" });\n * let game = debugEngine.createGame({ mode: \"Classic\" });\n * // Console: [KDomino:Debug] ... BEFORE createGame\n * // Console: [KDomino:Debug] ... AFTER createGame | turn=0 ...\n * ```\n */\nexport const wrapWithDebug = (\n engine: GameEngine,\n options?: DebugOptions,\n): GameEngine => {\n const logger = options?.logger ?? defaultDebugLogger;\n const level = options?.level ?? \"standard\";\n\n return {\n getModes: wrapMethod(\"getModes\", engine.getModes, logger, level),\n getExtraRules: wrapMethod(\n \"getExtraRules\",\n engine.getExtraRules,\n logger,\n level,\n ),\n createGame: wrapMethod(\"createGame\", engine.createGame, logger, level),\n addPlayers: wrapMethod(\"addPlayers\", engine.addPlayers, logger, level),\n addExtraRules: wrapMethod(\n \"addExtraRules\",\n engine.addExtraRules,\n logger,\n level,\n ),\n startGame: wrapMethod(\"startGame\", engine.startGame, logger, level),\n chooseDomino: wrapMethod(\n \"chooseDomino\",\n engine.chooseDomino,\n logger,\n level,\n ),\n placeDomino: wrapMethod(\"placeDomino\", engine.placeDomino, logger, level),\n discardDomino: wrapMethod(\n \"discardDomino\",\n engine.discardDomino,\n logger,\n level,\n ),\n getResults: wrapMethod(\"getResults\", engine.getResults, logger, level),\n calculateScore: wrapMethod(\n \"calculateScore\",\n engine.calculateScore,\n logger,\n level,\n ),\n getValidPlacements: wrapMethod(\n \"getValidPlacements\",\n engine.getValidPlacements,\n logger,\n level,\n ),\n canPlaceDomino: wrapMethod(\n \"canPlaceDomino\",\n engine.canPlaceDomino,\n logger,\n level,\n ),\n serialize: wrapMethod(\"serialize\", engine.serialize, logger, level),\n deserialize: wrapMethod(\"deserialize\", engine.deserialize, logger, level),\n getDynastyResults: wrapMethod(\n \"getDynastyResults\",\n engine.getDynastyResults,\n logger,\n level,\n ),\n };\n};\n","import type {\n GameState,\n GameWithNextAction,\n GameWithNextStep,\n} from \"@core/domain/types/index.js\";\nimport { isGameWithNextStep } from \"@core/domain/types/game.js\";\nimport type { GameEngine } from \"@core/portUserside/engine.js\";\n\n// ─── Event Types ─────────────────────────────────────────────────────\n\n/**\n * Optional callbacks for game events.\n * Consumers provide these to react to state changes (UI updates, animations, logging).\n * All callbacks are optional — only the ones you provide will be called.\n *\n * @example\n * ```typescript\n * const engine = createGameEngine({\n * events: {\n * onDominoPlaced: ({ game, lordId }) => {\n * console.log(`Lord ${lordId} placed a domino`);\n * animatePlacement(game);\n * },\n * onTurnEnd: ({ turn }) => console.log(`Turn ${turn} ended`),\n * onGameEnd: () => showResultsScreen(),\n * },\n * });\n * ```\n */\nexport type GameEventCallbacks = {\n /** Called after a new game is created */\n onGameCreated?: (event: { game: GameWithNextStep }) => void;\n /** Called after players are added to the game */\n onPlayersAdded?: (event: { game: GameWithNextStep }) => void;\n /** Called after the game starts (first dominoes revealed) */\n onGameStarted?: (event: { game: GameWithNextAction }) => void;\n /** Called after a lord picks a domino */\n onDominoPicked?: (event: {\n game: GameState;\n lordId: string;\n dominoNumber: number;\n }) => void;\n /** Called after a lord places a domino on their kingdom */\n onDominoPlaced?: (event: { game: GameState; lordId: string }) => void;\n /** Called after a lord discards a domino (no valid placement) */\n onDominoDiscarded?: (event: { game: GameState; lordId: string }) => void;\n /** Called when a new turn begins */\n onTurnStart?: (event: { game: GameState; turn: number }) => void;\n /** Called when a turn ends (all lords have played) */\n onTurnEnd?: (event: { game: GameState; turn: number }) => void;\n /** Called when the game reaches the result phase */\n onGameEnd?: (event: { game: GameState }) => void;\n};\n\n// ─── Wrapper ─────────────────────────────────────────────────────────\n\nconst isGameEnded = (game: GameState): boolean =>\n isGameWithNextStep(game) && game.nextAction.step === \"result\";\n\n/**\n * Wraps a GameEngine to emit event callbacks after each state-changing method.\n * Read-only methods (getModes, calculateScore, etc.) are passed through unchanged.\n *\n * Derived events:\n * - `onTurnEnd` + `onTurnStart`: emitted when `chooseDomino` causes a turn increment\n * - `onGameEnd`: emitted when `placeDomino` or `discardDomino` transitions to the \"result\" step\n *\n * @param engine - The base game engine to wrap\n * @param callbacks - Optional event callbacks\n * @returns A new GameEngine that emits events\n */\nexport const wrapWithEvents = (\n engine: GameEngine,\n callbacks: GameEventCallbacks\n): GameEngine => ({\n // Read-only methods — pass through\n getModes: (cmd) => engine.getModes(cmd),\n getExtraRules: (cmd) => engine.getExtraRules(cmd),\n calculateScore: (cmd) => engine.calculateScore(cmd),\n getValidPlacements: (cmd) => engine.getValidPlacements(cmd),\n canPlaceDomino: (cmd) => engine.canPlaceDomino(cmd),\n serialize: (cmd) => engine.serialize(cmd),\n deserialize: (cmd) => engine.deserialize(cmd),\n getResults: (cmd) => engine.getResults(cmd),\n getDynastyResults: (cmd) => engine.getDynastyResults(cmd),\n\n // State-changing methods — emit events after execution\n createGame: (cmd) => {\n const game = engine.createGame(cmd);\n callbacks.onGameCreated?.({ game });\n return game;\n },\n\n addPlayers: (cmd) => {\n const game = engine.addPlayers(cmd);\n callbacks.onPlayersAdded?.({ game });\n return game;\n },\n\n addExtraRules: (cmd) => engine.addExtraRules(cmd),\n\n startGame: (cmd) => {\n const game = engine.startGame(cmd);\n callbacks.onGameStarted?.({ game });\n callbacks.onTurnStart?.({ game, turn: game.turn });\n return game;\n },\n\n chooseDomino: (cmd) => {\n const turnBefore = cmd.game.turn;\n const game = engine.chooseDomino(cmd);\n callbacks.onDominoPicked?.({\n game,\n lordId: cmd.lordId,\n dominoNumber: cmd.dominoPick,\n });\n\n // Detect turn transition\n if (game.turn !== turnBefore) {\n callbacks.onTurnEnd?.({ game, turn: turnBefore });\n callbacks.onTurnStart?.({ game, turn: game.turn });\n }\n\n return game;\n },\n\n placeDomino: (cmd) => {\n const game = engine.placeDomino(cmd);\n callbacks.onDominoPlaced?.({ game, lordId: cmd.lordId });\n\n if (isGameEnded(game)) {\n callbacks.onGameEnd?.({ game });\n }\n\n return game;\n },\n\n discardDomino: (cmd) => {\n const game = engine.discardDomino(cmd);\n callbacks.onDominoDiscarded?.({ game, lordId: cmd.lordId });\n\n if (isGameEnded(game)) {\n callbacks.onGameEnd?.({ game });\n }\n\n return game;\n },\n});\n","import type { Logger } from \"@core/portServerside/logger.js\";\n\n/**\n * Creates a lightweight console-based logger.\n * This is the default logger used when no custom logger is provided.\n * @param isLoggingEnabled - Whether logging is enabled\n * @returns A Logger instance that outputs to console\n */\nexport const consoleLogger = (isLoggingEnabled: boolean): Logger => {\n const formatMessage = (level: string, message: string): string => {\n const timestamp = new Date().toISOString();\n return `${timestamp} [KDomino_Engine] ${level}: ${message}`;\n };\n\n return {\n info: (message: string) => {\n if (isLoggingEnabled) {\n console.log(formatMessage(\"info\", message));\n }\n },\n error: (message: string) => {\n if (isLoggingEnabled) {\n console.error(formatMessage(\"error\", message));\n }\n },\n };\n};\n\n/**\n * A silent logger that does nothing.\n * Useful for testing or when logging should be completely disabled.\n */\nexport const silentLogger: Logger = {\n info: () => {},\n error: () => {},\n};\n","{\n \"Classic\": [\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 1\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 2\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 3\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 4\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 5\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 6\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 7\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 8\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 9\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 10\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 11\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"number\": 12\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 13\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 14\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 15\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"number\": 16\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 17\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 18\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 19\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 20\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 21\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"number\": 22\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 0\n },\n \"number\": 23\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 24\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 25\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 26\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 27\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 28\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 29\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 30\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 31\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 32\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 33\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 34\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 35\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 1\n },\n \"number\": 36\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 1\n },\n \"number\": 37\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 1\n },\n \"number\": 38\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"number\": 39\n },\n {\n \"left\": {\n \"type\": \"mine\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 40\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 2\n },\n \"number\": 41\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 2\n },\n \"number\": 42\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 2\n },\n \"number\": 43\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 2\n },\n \"number\": 44\n },\n {\n \"left\": {\n \"type\": \"mine\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 45\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 2\n },\n \"number\": 46\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 2\n },\n \"number\": 47\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 3\n },\n \"number\": 48\n }\n ]\n}\n","import type { Domino, Ground } from \"@core/domain/types/domino.js\";\nimport type { GameMode } from \"@core/domain/types/mode.js\";\nimport type { DominoesRepository } from \"@core/portServerside/dominoesRepository.js\";\nimport dominoesJson from \"../datasources/dominoes.json\" with { type: \"json\" };\n\nconst jsonDominoes = (): DominoesRepository => {\n const dominoes: Record<string, Domino[]> = {};\n\n for (const [key, value] of Object.entries(dominoesJson)) {\n const currentDominoes: Domino[] = [];\n value.forEach((domino) => {\n currentDominoes.push({\n left: {\n type: <Ground>domino.left.type,\n crowns: domino.left.crowns,\n },\n right: {\n type: <Ground>domino.right.type,\n crowns: domino.right.crowns,\n },\n number: domino.number,\n });\n });\n\n dominoes[key] = currentDominoes;\n }\n\n return {\n getForMode: (mode: GameMode) => {\n return dominoes[mode.name] || [];\n },\n };\n};\n\nexport default jsonDominoes;\n","[\n {\n \"name\": \"Classic\",\n \"description\": \"Original KingDomino rules\"\n }\n]","import type { GameMode } from \"@core/domain/types/mode.js\";\nimport type { ModeRepository } from \"@core/portServerside/modeRepository.js\";\nimport modesJson from \"../datasources/modes.json\" with { type: \"json\" };\n\nconst jsonModes = (): ModeRepository => {\n const modes: GameMode[] = [];\n\n modesJson.forEach((mode) => {\n modes.push({\n name: mode.name,\n description: mode.description,\n });\n });\n\n return {\n getAvailables: () => {\n return modes;\n },\n };\n};\n\nexport default jsonModes;\n","{\n \"commun\": [\n {\n \"playersLimit\": 1,\n \"lordsPerPlayer\": 1,\n \"maxDominoes\": 48,\n \"dominoesPerTurn\": 4,\n \"maxTurns\": 12,\n \"maxKingdomSize\": 5\n },\n {\n \"playersLimit\": 2,\n \"lordsPerPlayer\": 2,\n \"maxDominoes\": 24,\n \"dominoesPerTurn\": 4,\n \"maxTurns\": 6,\n \"maxKingdomSize\": 5\n },\n {\n \"playersLimit\": 3,\n \"lordsPerPlayer\": 1,\n \"maxDominoes\": 48,\n \"dominoesPerTurn\": 4,\n \"maxTurns\": 12,\n \"maxKingdomSize\": 5\n },\n {\n \"playersLimit\": 4,\n \"lordsPerPlayer\": 1,\n \"maxDominoes\": 48,\n \"dominoesPerTurn\": 4,\n \"maxTurns\": 12,\n \"maxKingdomSize\": 5\n }\n ],\n \"extra\": [\n {\n \"name\": \"The middle Kingdom\",\n \"description\": \"Gain 10 additional points if your castle is in the middle of the kingdom.\",\n \"mode\": [{ \"name\": \"Classic\", \"description\": \"King Domino classic mode\" }]\n },\n {\n \"name\": \"Harmony\",\n \"description\": \"Gain 5 additional points if your kingdom is complete (no discarded dominoes).\",\n \"mode\": [{ \"name\": \"Classic\", \"description\": \"King Domino classic mode\" }]\n },\n {\n \"name\": \"The Mighty Duel\",\n \"description\": \"Use all 48 dominoes and build a 7x7 kingdom. For 2 players only.\",\n \"mode\": [{ \"name\": \"Classic\", \"description\": \"King Domino classic mode\" }],\n \"playersLimit\": 2\n },\n {\n \"name\": \"Dynasty\",\n \"description\": \"Play 3 games in a row. The player with the highest total points wins.\",\n \"mode\": [{ \"name\": \"Classic\", \"description\": \"King Domino classic mode\" }]\n }\n ]\n}\n","import type { Rules } from \"@core/domain/types/rule.js\";\nimport type { RuleRepository } from \"@core/portServerside/ruleRepository.js\";\nimport rulesJson from \"../datasources/rules.json\" with { type: \"json\" };\n\nconst jsonRules = (): RuleRepository => {\n const rules: Rules = {\n basic: {},\n extraRules: [],\n };\n\n const commonRules = rulesJson.commun;\n const extraRules = rulesJson.extra;\n\n commonRules.forEach((rule) => {\n rules.basic[rule.playersLimit] = {\n lords: rule.lordsPerPlayer,\n maxDominoes: rule.maxDominoes,\n dominoesPerTurn: rule.dominoesPerTurn,\n maxTurns: rule.maxTurns,\n maxKingdomSize: rule.maxKingdomSize,\n };\n });\n\n extraRules.forEach((rule) => {\n rules.extraRules.push({\n name: rule.name,\n description: rule.description,\n mode: rule.mode,\n ...(\"playersLimit\" in rule && { playersLimit: rule.playersLimit }),\n });\n });\n\n return {\n getAll: () => {\n return rules;\n },\n getAllExtra: () => {\n return rules.extraRules;\n },\n };\n};\n\nexport default jsonRules;\n","import type { ShuffleMethod } from \"@core/portServerside/shuffleMethod.js\";\n\nexport const shuffleMethod: ShuffleMethod = <T>(array: T[]) => {\n for (let i = array.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [array[i], array[j]] = [array[j] as T, array[i] as T];\n }\n return array;\n};\n","import type { UuidMethod } from \"@core/portServerside/uuidMethod.js\";\n\nexport const uuidMethod: UuidMethod = () => {\n return globalThis.crypto.randomUUID();\n};\n","/**\n * Error codes for domain-level errors.\n * These codes can be used for i18n and programmatic error handling.\n */\nexport const ErrorCode = {\n // Game flow errors\n INVALID_STEP: \"INVALID_STEP\",\n STEP_EXECUTION_FAILED: \"STEP_EXECUTION_FAILED\",\n ACTION_EXECUTION_FAILED: \"ACTION_EXECUTION_FAILED\",\n\n // Entity not found errors\n LORD_NOT_FOUND: \"LORD_NOT_FOUND\",\n PLAYER_NOT_FOUND: \"PLAYER_NOT_FOUND\",\n DOMINO_NOT_FOUND: \"DOMINO_NOT_FOUND\",\n MODE_NOT_FOUND: \"MODE_NOT_FOUND\",\n\n // Validation errors\n INVALID_PLAYER_COUNT: \"INVALID_PLAYER_COUNT\",\n INVALID_PLAYER_NAME: \"INVALID_PLAYER_NAME\",\n INVALID_PLACEMENT: \"INVALID_PLACEMENT\",\n PLACEMENT_NOT_EMPTY: \"PLACEMENT_NOT_EMPTY\",\n PLACEMENT_NOT_ADJACENT: \"PLACEMENT_NOT_ADJACENT\",\n PLACEMENT_INVALID_TERRAIN: \"PLACEMENT_INVALID_TERRAIN\",\n PLACEMENT_OUT_OF_BOUNDS: \"PLACEMENT_OUT_OF_BOUNDS\",\n PLACEMENT_EXCEEDS_KINGDOM_SIZE: \"PLACEMENT_EXCEEDS_KINGDOM_SIZE\",\n\n // Action errors\n NOT_YOUR_TURN: \"NOT_YOUR_TURN\",\n CANNOT_PICK: \"CANNOT_PICK\",\n CANNOT_PLACE: \"CANNOT_PLACE\",\n DOMINO_ALREADY_PICKED: \"DOMINO_ALREADY_PICKED\",\n\n // History errors\n UNDO_UNAVAILABLE: \"UNDO_UNAVAILABLE\",\n REDO_UNAVAILABLE: \"REDO_UNAVAILABLE\",\n} as const;\n\nexport type ErrorCodeType = (typeof ErrorCode)[keyof typeof ErrorCode];\n\n/**\n * Structured domain error with code and context.\n */\nexport interface DomainError {\n /** Error code for programmatic handling */\n code: ErrorCodeType;\n /** Human-readable error message */\n message: string;\n /** Optional context data for debugging */\n context?: Record<string, unknown>;\n}\n\n/**\n * Creates a domain error object.\n */\nexport const createDomainError = (\n code: ErrorCodeType,\n message: string,\n context?: Record<string, unknown>,\n): DomainError => ({\n code,\n message,\n context,\n});\n\n/**\n * Base class for domain errors thrown by handlers.\n */\nexport class DomainException extends Error {\n public readonly code: ErrorCodeType;\n public readonly context?: Record<string, unknown>;\n\n constructor(error: DomainError) {\n super(error.message);\n this.name = \"DomainException\";\n this.code = error.code;\n this.context = error.context;\n }\n}\n\n/**\n * Error thrown when the game is in an invalid step for the requested action.\n */\nexport class InvalidStepError extends DomainException {\n constructor(message: string, context?: Record<string, unknown>) {\n super({\n code: ErrorCode.INVALID_STEP,\n message,\n context,\n });\n this.name = \"InvalidStepError\";\n }\n}\n\n/**\n * Error thrown when a step execution fails.\n */\nexport class StepExecutionError extends DomainException {\n constructor(\n message: string,\n code: ErrorCodeType = ErrorCode.STEP_EXECUTION_FAILED,\n context?: Record<string, unknown>,\n ) {\n super({\n code,\n message,\n context,\n });\n this.name = \"StepExecutionError\";\n }\n}\n\n/**\n * Error thrown when an action execution fails.\n */\nexport class ActionExecutionError extends DomainException {\n constructor(\n message: string,\n code: ErrorCodeType = ErrorCode.ACTION_EXECUTION_FAILED,\n context?: Record<string, unknown>,\n ) {\n super({\n code,\n message,\n context,\n });\n this.name = \"ActionExecutionError\";\n }\n}\n\n/**\n * Error thrown when a required entity is not found.\n */\nexport class NotFoundError extends DomainException {\n constructor(\n message: string,\n code: ErrorCodeType = ErrorCode.LORD_NOT_FOUND,\n context?: Record<string, unknown>,\n ) {\n super({\n code,\n message,\n context,\n });\n this.name = \"NotFoundError\";\n }\n}\n\n/**\n * Error thrown when validation fails.\n */\nexport class ValidationError extends DomainException {\n constructor(\n message: string,\n code: ErrorCodeType,\n context?: Record<string, unknown>,\n ) {\n super({\n code,\n message,\n context,\n });\n this.name = \"ValidationError\";\n }\n}\n\n/**\n * Error thrown when undo is requested but no previous state exists.\n */\nexport class UndoError extends DomainException {\n constructor(message = \"No state to undo\", context?: Record<string, unknown>) {\n super({\n code: ErrorCode.UNDO_UNAVAILABLE,\n message,\n context,\n });\n this.name = \"UndoError\";\n }\n}\n\n/**\n * Error thrown when redo is requested but no future state exists.\n */\nexport class RedoError extends DomainException {\n constructor(message = \"No state to redo\", context?: Record<string, unknown>) {\n super({\n code: ErrorCode.REDO_UNAVAILABLE,\n message,\n context,\n });\n this.name = \"RedoError\";\n }\n}\n","import {\n ErrorCode,\n type ErrorCodeType,\n} from \"@core/domain/errors/domainErrors.js\";\n\n/**\n * Translation keys for internationalization support.\n * Use these keys instead of hardcoded strings for translatable content.\n */\nexport const TranslationKey = {\n // Error messages\n ERROR_INVALID_STEP: \"error.invalidStep\",\n ERROR_STEP_EXECUTION_FAILED: \"error.stepExecutionFailed\",\n ERROR_ACTION_EXECUTION_FAILED: \"error.actionExecutionFailed\",\n ERROR_LORD_NOT_FOUND: \"error.lordNotFound\",\n ERROR_PLAYER_NOT_FOUND: \"error.playerNotFound\",\n ERROR_DOMINO_NOT_FOUND: \"error.dominoNotFound\",\n ERROR_MODE_NOT_FOUND: \"error.modeNotFound\",\n ERROR_INVALID_PLACEMENT: \"error.invalidPlacement\",\n ERROR_PLACEMENT_NOT_EMPTY: \"error.placementNotEmpty\",\n ERROR_PLACEMENT_NOT_ADJACENT: \"error.placementNotAdjacent\",\n ERROR_PLACEMENT_INVALID_TERRAIN: \"error.placementInvalidTerrain\",\n ERROR_PLACEMENT_OUT_OF_BOUNDS: \"error.placementOutOfBounds\",\n ERROR_PLACEMENT_EXCEEDS_KINGDOM_SIZE: \"error.placementExceedsKingdomSize\",\n ERROR_NOT_YOUR_TURN: \"error.notYourTurn\",\n ERROR_CANNOT_PICK: \"error.cannotPick\",\n ERROR_CANNOT_PLACE: \"error.cannotPlace\",\n ERROR_DOMINO_ALREADY_PICKED: \"error.dominoAlreadyPicked\",\n ERROR_INVALID_PLAYER_COUNT: \"error.invalidPlayerCount\",\n ERROR_INVALID_PLAYER_NAME: \"error.invalidPlayerName\",\n ERROR_UNDO_UNAVAILABLE: \"error.undoUnavailable\",\n ERROR_REDO_UNAVAILABLE: \"error.redoUnavailable\",\n\n // Game mode names\n MODE_CLASSIC: \"mode.classic\",\n\n // Extra rule names\n RULE_MIDDLE_KINGDOM: \"rule.middleKingdom\",\n RULE_HARMONY: \"rule.harmony\",\n\n // Ground types\n GROUND_CASTLE: \"ground.castle\",\n GROUND_WHEAT: \"ground.wheat\",\n GROUND_FOREST: \"ground.forest\",\n GROUND_SEA: \"ground.sea\",\n GROUND_PLAIN: \"ground.plain\",\n GROUND_SWAMP: \"ground.swamp\",\n GROUND_MINE: \"ground.mine\",\n\n // Game phases\n PHASE_ADD_PLAYERS: \"phase.addPlayers\",\n PHASE_OPTIONS: \"phase.options\",\n PHASE_START: \"phase.start\",\n PHASE_RESULT: \"phase.result\",\n\n // Actions\n ACTION_PICK_DOMINO: \"action.pickDomino\",\n ACTION_PLACE_DOMINO: \"action.placeDomino\",\n ACTION_PASS: \"action.pass\",\n} as const;\n\nexport type TranslationKeyType =\n (typeof TranslationKey)[keyof typeof TranslationKey];\n\n/**\n * Default English translations.\n */\nexport const defaultTranslations: Record<TranslationKeyType, string> = {\n // Error messages\n [TranslationKey.ERROR_INVALID_STEP]: \"Invalid game step\",\n [TranslationKey.ERROR_STEP_EXECUTION_FAILED]: \"Step execution failed\",\n [TranslationKey.ERROR_ACTION_EXECUTION_FAILED]: \"Action execution failed\",\n [TranslationKey.ERROR_LORD_NOT_FOUND]: \"Lord not found\",\n [TranslationKey.ERROR_PLAYER_NOT_FOUND]: \"Player not found\",\n [TranslationKey.ERROR_DOMINO_NOT_FOUND]: \"Domino not found\",\n [TranslationKey.ERROR_MODE_NOT_FOUND]: \"Game mode not found\",\n [TranslationKey.ERROR_INVALID_PLACEMENT]: \"Invalid placement\",\n [TranslationKey.ERROR_PLACEMENT_NOT_EMPTY]: \"Position is not empty\",\n [TranslationKey.ERROR_PLACEMENT_NOT_ADJACENT]:\n \"Not adjacent to existing tiles\",\n [TranslationKey.ERROR_PLACEMENT_INVALID_TERRAIN]:\n \"Terrain type does not match\",\n [TranslationKey.ERROR_PLACEMENT_OUT_OF_BOUNDS]: \"Placement is out of bounds\",\n [TranslationKey.ERROR_PLACEMENT_EXCEEDS_KINGDOM_SIZE]:\n \"Placement exceeds kingdom size\",\n [TranslationKey.ERROR_NOT_YOUR_TURN]: \"It is not your turn\",\n [TranslationKey.ERROR_CANNOT_PICK]: \"Cannot pick a domino now\",\n [TranslationKey.ERROR_CANNOT_PLACE]: \"Cannot place a domino now\",\n [TranslationKey.ERROR_DOMINO_ALREADY_PICKED]:\n \"Domino has already been picked\",\n [TranslationKey.ERROR_INVALID_PLAYER_COUNT]:\n \"Invalid number of players (1-4 required)\",\n [TranslationKey.ERROR_INVALID_PLAYER_NAME]:\n \"Player name must be at least 3 characters\",\n [TranslationKey.ERROR_UNDO_UNAVAILABLE]: \"No state to undo\",\n [TranslationKey.ERROR_REDO_UNAVAILABLE]: \"No state to redo\",\n\n // Game mode names\n [TranslationKey.MODE_CLASSIC]: \"Classic\",\n\n // Extra rule names\n [TranslationKey.RULE_MIDDLE_KINGDOM]: \"The Middle Kingdom\",\n [TranslationKey.RULE_HARMONY]: \"Harmony\",\n\n // Ground types\n [TranslationKey.GROUND_CASTLE]: \"Castle\",\n [TranslationKey.GROUND_WHEAT]: \"Wheat Field\",\n [TranslationKey.GROUND_FOREST]: \"Forest\",\n [TranslationKey.GROUND_SEA]: \"Sea\",\n [TranslationKey.GROUND_PLAIN]: \"Plain\",\n [TranslationKey.GROUND_SWAMP]: \"Swamp\",\n [TranslationKey.GROUND_MINE]: \"Mine\",\n\n // Game phases\n [TranslationKey.PHASE_ADD_PLAYERS]: \"Add Players\",\n [TranslationKey.PHASE_OPTIONS]: \"Game Options\",\n [TranslationKey.PHASE_START]: \"Start Game\",\n [TranslationKey.PHASE_RESULT]: \"Game Results\",\n\n // Actions\n [TranslationKey.ACTION_PICK_DOMINO]: \"Pick Domino\",\n [TranslationKey.ACTION_PLACE_DOMINO]: \"Place Domino\",\n [TranslationKey.ACTION_PASS]: \"Pass\",\n};\n\n/**\n * Maps ErrorCode values to their corresponding TranslationKey values.\n * Used by handlers to translate error codes into localized messages.\n */\nexport const errorCodeToTranslationKey: Record<\n ErrorCodeType,\n TranslationKeyType\n> = {\n [ErrorCode.INVALID_STEP]: TranslationKey.ERROR_INVALID_STEP,\n [ErrorCode.STEP_EXECUTION_FAILED]: TranslationKey.ERROR_STEP_EXECUTION_FAILED,\n [ErrorCode.ACTION_EXECUTION_FAILED]:\n TranslationKey.ERROR_ACTION_EXECUTION_FAILED,\n [ErrorCode.LORD_NOT_FOUND]: TranslationKey.ERROR_LORD_NOT_FOUND,\n [ErrorCode.PLAYER_NOT_FOUND]: TranslationKey.ERROR_PLAYER_NOT_FOUND,\n [ErrorCode.DOMINO_NOT_FOUND]: TranslationKey.ERROR_DOMINO_NOT_FOUND,\n [ErrorCode.MODE_NOT_FOUND]: TranslationKey.ERROR_MODE_NOT_FOUND,\n [ErrorCode.INVALID_PLAYER_COUNT]: TranslationKey.ERROR_INVALID_PLAYER_COUNT,\n [ErrorCode.INVALID_PLAYER_NAME]: TranslationKey.ERROR_INVALID_PLAYER_NAME,\n [ErrorCode.INVALID_PLACEMENT]: TranslationKey.ERROR_INVALID_PLACEMENT,\n [ErrorCode.PLACEMENT_NOT_EMPTY]: TranslationKey.ERROR_PLACEMENT_NOT_EMPTY,\n [ErrorCode.PLACEMENT_NOT_ADJACENT]:\n TranslationKey.ERROR_PLACEMENT_NOT_ADJACENT,\n [ErrorCode.PLACEMENT_INVALID_TERRAIN]:\n TranslationKey.ERROR_PLACEMENT_INVALID_TERRAIN,\n [ErrorCode.PLACEMENT_OUT_OF_BOUNDS]:\n TranslationKey.ERROR_PLACEMENT_OUT_OF_BOUNDS,\n [ErrorCode.PLACEMENT_EXCEEDS_KINGDOM_SIZE]:\n TranslationKey.ERROR_PLACEMENT_EXCEEDS_KINGDOM_SIZE,\n [ErrorCode.NOT_YOUR_TURN]: TranslationKey.ERROR_NOT_YOUR_TURN,\n [ErrorCode.CANNOT_PICK]: TranslationKey.ERROR_CANNOT_PICK,\n [ErrorCode.CANNOT_PLACE]: TranslationKey.ERROR_CANNOT_PLACE,\n [ErrorCode.DOMINO_ALREADY_PICKED]: TranslationKey.ERROR_DOMINO_ALREADY_PICKED,\n [ErrorCode.UNDO_UNAVAILABLE]: TranslationKey.ERROR_UNDO_UNAVAILABLE,\n [ErrorCode.REDO_UNAVAILABLE]: TranslationKey.ERROR_REDO_UNAVAILABLE,\n};\n\n/**\n * Translates an error code to a localized message.\n * Convenience function combining errorCodeToTranslationKey lookup and translation.\n */\nexport const translateErrorCode = (\n translator: Translator,\n code: ErrorCodeType,\n params?: Record<string, string | number>,\n): string => {\n const key = errorCodeToTranslationKey[code];\n return translator.t(key, params);\n};\n\n/**\n * Translator interface for custom translations.\n */\nexport interface Translator {\n /**\n * Translate a key to the current language.\n * @param key - The translation key\n * @param params - Optional parameters for interpolation\n * @returns The translated string\n */\n t(key: TranslationKeyType, params?: Record<string, string | number>): string;\n}\n\n/**\n * Creates a translator with the provided translations.\n * Falls back to default English translations for missing keys.\n *\n * @param translations - Custom translations to use\n * @returns A translator instance\n */\nexport const createTranslator = (\n translations: Partial<Record<TranslationKeyType, string>> = {},\n): Translator => {\n const mergedTranslations = { ...defaultTranslations, ...translations };\n\n return {\n t(\n key: TranslationKeyType,\n params?: Record<string, string | number>,\n ): string {\n let text = mergedTranslations[key] || key;\n\n // Simple parameter interpolation: {{param}}\n if (params) {\n for (const [paramKey, value] of Object.entries(params)) {\n text = text.replace(\n new RegExp(`\\\\{\\\\{${paramKey}\\\\}\\\\}`, \"g\"),\n String(value),\n );\n }\n }\n\n return text;\n },\n };\n};\n\n/**\n * Default translator using English translations.\n */\nexport const defaultTranslator: Translator = createTranslator();\n","export type Result<T> = Ok<T> | Err;\n\nexport interface Ok<T> {\n readonly tag: \"Ok\";\n readonly value: T;\n}\n\nexport interface Err {\n readonly tag: \"Err\";\n readonly error: string;\n}\n\nexport const ok = <T>(value: T): Ok<T> => ({ tag: \"Ok\", value });\nexport const err = (error: string): Err => ({ tag: \"Err\", error });\n\nexport const isOk = <T>(result: Result<T>): result is Ok<T> =>\n result.tag === \"Ok\";\nexport const isErr = <T>(result: Result<T>): result is Err =>\n result.tag === \"Err\";\n\nexport const unwrap = <T>(result: Ok<T> | Err): T => {\n if (result.tag === \"Err\") {\n throw new Error(result.error);\n }\n return result.value;\n};\n","import type { AddExtraRulesCommand } from \"@application/commands/addExtraRulesCommand.js\";\nimport {\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n StepExecutionError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameWithNextStep,\n isGameWithNextStep,\n} from \"@core/domain/types/game.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport { translateErrorCode } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { AddExtraRulesUseCase } from \"@core/useCases/addExtraRules.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype AddExtraRulesHandler = (command: AddExtraRulesCommand) => GameWithNextStep;\n\nexport const addExtraRulesHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: AddExtraRulesUseCase,\n ): AddExtraRulesHandler =>\n (command: AddExtraRulesCommand) => {\n const { game, extraRules } = command;\n logger.info(`Adding extra rules to game: ${game.id}`);\n logger.info(`Extra rules: ${extraRules}`);\n\n if (!isGameWithNextStep(game)) {\n logger.error(\n `Invalid game, required nextAction type: 'step' but got: ${game.nextAction.type}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n { expected: \"step\", actual: game.nextAction.type, gameId: game.id },\n );\n }\n\n if (game.nextAction.step !== \"options\") {\n logger.error(\n `Required game with options step but got: ${game.nextAction.step}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n { expected: \"options\", actual: game.nextAction.step, gameId: game.id },\n );\n }\n\n const result = useCase(game, extraRules);\n\n if (isErr(result)) {\n logger.error(`Error adding extra rules: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new StepExecutionError(translateErrorCode(translator, code), code, {\n gameId: game.id,\n extraRules: command.extraRules,\n });\n }\n\n logger.info(`Extra rules added to game: ${game.id}`);\n return result.value;\n };\n","import type { AddPlayersCommand } from \"@application/commands/addPlayersCommand.js\";\nimport {\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n StepExecutionError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameWithNextStep,\n isGameWithNextStep,\n} from \"@core/domain/types/game.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport { translateErrorCode } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { AddPlayersUseCase } from \"@core/useCases/addPlayers.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype AddPlayersHandler = (command: AddPlayersCommand) => GameWithNextStep;\n\nexport const addPlayersHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: AddPlayersUseCase,\n ): AddPlayersHandler =>\n (command: AddPlayersCommand) => {\n const { game, players } = command;\n\n logger.info(`Adding players to game: ${game.id}`);\n\n if (!isGameWithNextStep(game)) {\n logger.error(\n `Invalid game, required nextAction type: 'step' but got: ${game.nextAction.type}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n { expected: \"step\", actual: game.nextAction.type, gameId: game.id },\n );\n }\n\n if (game.nextAction.step !== \"addPlayers\") {\n logger.error(\n `Required game with addPlayers step but got: ${game.nextAction.step}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"addPlayers\",\n actual: game.nextAction.step,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(game, players);\n\n if (isErr(result)) {\n logger.error(`Error adding players: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new StepExecutionError(translateErrorCode(translator, code), code, {\n gameId: game.id,\n players: command.players,\n });\n }\n\n logger.info(`Players added to game: ${game.id}`);\n return result.value;\n };\n","import type { CalculateScoreCommand } from \"@application/commands/calculateScoreCommand.js\";\nimport type { Score } from \"@core/domain/types/game.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { CalculateScoreUseCase } from \"@core/useCases/calculateScore.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype CalculateScoreHandler = (command: CalculateScoreCommand) => Score;\n\nexport const calculateScoreHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: CalculateScoreUseCase,\n ): CalculateScoreHandler =>\n (command) => {\n const { kingdom } = command;\n logger.info(`Calculating score for kingdom`);\n const result = useCase(kingdom);\n\n if (isErr(result)) {\n logger.error(`Error calculating score: ${result.error}`);\n throw new Error(result.error);\n }\n\n logger.info(`Score calculated: ${result.value}`);\n return result.value;\n };\n","import type { CanPlaceDominoCommand } from \"@application/commands/canPlaceDominoCommand.js\";\nimport type { Domino, Kingdom } from \"@core/domain/types/index.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\n\ntype CanPlaceDominoUseCase = (\n kingdom: Kingdom,\n domino: Domino,\n maxKingdomSize?: number,\n) => boolean;\n\ntype CanPlaceDominoHandler = (command: CanPlaceDominoCommand) => boolean;\n\n/**\n * Creates a handler for checking if a domino can be placed.\n */\nexport const canPlaceDominoHandler = (\n logger: Logger,\n translator: Translator,\n useCase: CanPlaceDominoUseCase,\n): CanPlaceDominoHandler => {\n return (command) => {\n logger.info(`Checking if domino ${command.domino.number} can be placed`);\n const canPlace = useCase(\n command.kingdom,\n command.domino,\n command.maxKingdomSize,\n );\n logger.info(`Can place domino: ${canPlace}`);\n return canPlace;\n };\n};\n","import type { ChooseDominoCommand } from \"@application/commands/chooseDominoCommand.js\";\nimport {\n ActionExecutionError,\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameWithNextAction,\n isGameWithNextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport { translateErrorCode } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { ChooseDominoUseCase } from \"@core/useCases/chooseDomino.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype ChooseDominoHandler = (command: ChooseDominoCommand) => GameWithNextAction;\n\nexport const chooseDominoHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: ChooseDominoUseCase,\n ): ChooseDominoHandler =>\n (command: ChooseDominoCommand) => {\n const { game, lordId, dominoPick } = command;\n logger.info(\n `Choosing domino: ${dominoPick} for lord: ${lordId} in game: ${game.id}`,\n );\n\n if (!isGameWithNextAction(game)) {\n logger.error(\n `Invalid game, required nextAction type: 'action' but got: ${game.nextAction.type}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n { expected: \"action\", actual: game.nextAction.type, gameId: game.id },\n );\n }\n\n if (game.nextAction.nextAction !== \"pickDomino\") {\n logger.error(\n `Required game with pickDomino action but got: ${game.nextAction.nextAction}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"pickDomino\",\n actual: game.nextAction.nextAction,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(game, lordId, dominoPick);\n\n if (isErr(result)) {\n logger.error(`Error choosing domino: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new ActionExecutionError(\n translateErrorCode(translator, code),\n code,\n {\n gameId: game.id,\n lordId: command.lordId,\n dominoPick: command.dominoPick,\n },\n );\n }\n\n logger.info(\n `Domino chosen: ${dominoPick} for lord: ${lordId} in game: ${game.id}`,\n );\n return result.value;\n };\n","import type { CreateGameCommand } from \"@application/commands/createGameCommand.js\";\nimport {\n type ErrorCodeType,\n StepExecutionError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { GameWithNextStep } from \"@core/domain/types/game.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport { translateErrorCode } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { CreateGameUseCase } from \"@core/useCases/createGame.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype CreateGameHandler = (command: CreateGameCommand) => GameWithNextStep;\n\nexport const createGameHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: CreateGameUseCase,\n ): CreateGameHandler =>\n (command: CreateGameCommand) => {\n logger.info(`Creating game with mode: ${command.mode}`);\n const result = useCase(command.mode, command.seed);\n\n if (isErr(result)) {\n logger.error(`Error creating game: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new StepExecutionError(translateErrorCode(translator, code), code, {\n mode: command.mode,\n });\n }\n\n logger.info(`Game created: ${result.value.id}`);\n return result.value;\n };\n","import type { DiscardDominoCommand } from \"@application/commands/discardDominoCommand.js\";\nimport {\n ActionExecutionError,\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameState,\n isGameWithNextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport { translateErrorCode } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { DiscardDominoUseCase } from \"@core/useCases/discardDomino.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype DiscardDominoHandler = (command: DiscardDominoCommand) => GameState;\n\nexport const discardDominoHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: DiscardDominoUseCase,\n ): DiscardDominoHandler =>\n (command: DiscardDominoCommand) => {\n const { game, lordId } = command;\n logger.info(`Discarding domino for lord: ${lordId} in game: ${game.id}`);\n\n if (!isGameWithNextAction(game)) {\n logger.error(\n `Invalid game, required nextAction type: 'action' but got: ${game.nextAction.type}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n { expected: \"action\", actual: game.nextAction.type, gameId: game.id },\n );\n }\n\n if (game.nextAction.nextAction !== \"placeDomino\") {\n logger.error(\n `Required game with placeDomino action but got: ${game.nextAction.nextAction}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"placeDomino\",\n actual: game.nextAction.nextAction,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(game, lordId);\n\n if (isErr(result)) {\n logger.error(`Error discarding domino: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new ActionExecutionError(\n translateErrorCode(translator, code),\n code,\n { gameId: game.id, lordId: command.lordId },\n );\n }\n\n if (isGameWithNextAction(result.value)) {\n logger.info(`Domino discarded: ${lordId} in game: ${game.id}`);\n return result.value;\n }\n\n logger.info(`Domino discarded: ${lordId} in game: ${game.id}`);\n return result.value;\n };\n","import type { GetDynastyResultCommand } from \"@application/commands/getDynastyResultCommand.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type {\n DynastyResult,\n GetDynastyResultUseCase,\n} from \"@core/useCases/getDynastyResult.js\";\n\ntype GetDynastyResultHandler = (\n command: GetDynastyResultCommand,\n) => DynastyResult[];\n\nexport const getDynastyResultHandler = (\n logger: Logger,\n translator: Translator,\n useCase: GetDynastyResultUseCase,\n): GetDynastyResultHandler => {\n return (command) => {\n logger.info(\n `Calculating dynasty results for ${command.games.length} games`,\n );\n const results = useCase(command.games);\n logger.info(`Dynasty results calculated`);\n return results;\n };\n};\n","import type { GetExtraRulesCommand } from \"@application/commands/getExtraRulesCommand.js\";\nimport {\n ErrorCode,\n type ErrorCodeType,\n NotFoundError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { ExtraRule } from \"@core/domain/types/rule.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport { translateErrorCode } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { GetExtraRulesUseCase } from \"@core/useCases/getExtraRules.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype GetExtraRulesHandler = (command: GetExtraRulesCommand) => ExtraRule[];\n\nexport const getExtraRulesHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: GetExtraRulesUseCase,\n ): GetExtraRulesHandler =>\n (command: GetExtraRulesCommand) => {\n const { mode, players } = command;\n logger.info(\n `Getting extra rules for mode: ${mode} and players: ${players}`,\n );\n const result = useCase(mode, players);\n\n if (isErr(result)) {\n logger.error(`Error getting extra rules: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new NotFoundError(translateErrorCode(translator, code), code, {\n mode: command.mode,\n });\n }\n\n logger.info(`Extra rules retrieved: ${result.value}`);\n return result.value;\n };\n","import type { GetModesCommand } from \"@application/commands/getModesCommand.js\";\nimport {\n ErrorCode,\n type ErrorCodeType,\n NotFoundError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { GameMode } from \"@core/domain/types/mode.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport { translateErrorCode } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { GetModesUseCase } from \"@core/useCases/getModes.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype GetModesHandler = (command: GetModesCommand) => GameMode[];\n\nexport const getModesHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: GetModesUseCase,\n ): GetModesHandler =>\n (_command: GetModesCommand) => {\n logger.info(\"Getting modes\");\n const result = useCase();\n\n if (isErr(result)) {\n logger.error(`Error getting modes: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new NotFoundError(translateErrorCode(translator, code), code);\n }\n\n logger.info(`Modes retrieved: ${result.value}`);\n return result.value;\n };\n","import type { GetResultCommand } from \"@application/commands/getResultCommand.js\";\nimport {\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n NotFoundError,\n StepExecutionError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameWithResults,\n isGameWithNextStep,\n type ScoreResult,\n} from \"@core/domain/types/game.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport { translateErrorCode } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { CalculateScoreUseCase } from \"@core/useCases/calculateScore.js\";\nimport type { GetResultUseCase } from \"@core/useCases/getResult.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype GetResultHandler = (command: GetResultCommand) => GameWithResults;\n\nexport const getResultHandler =\n (\n logger: Logger,\n translator: Translator,\n useCases: {\n getResultUseCase: GetResultUseCase;\n calculateScoreUseCase: CalculateScoreUseCase;\n },\n ): GetResultHandler =>\n (command: GetResultCommand) => {\n const { getResultUseCase, calculateScoreUseCase } = useCases;\n const { game } = command;\n logger.info(`Getting result for game: ${game.id}`);\n\n if (!isGameWithNextStep(game)) {\n logger.error(\n `Invalid game, required nextAction type: 'step' but got: ${game.nextAction.type}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n { expected: \"step\", actual: game.nextAction.type, gameId: game.id },\n );\n }\n\n if (game.nextAction.step !== \"result\") {\n logger.error(\n `Required game with result step but got: ${game.nextAction.step}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n { expected: \"result\", actual: game.nextAction.step, gameId: game.id },\n );\n }\n\n const { players } = game;\n\n const scoreResult: ScoreResult[] = players.map((player) => {\n const { kingdom } = player;\n const result = calculateScoreUseCase(kingdom);\n\n if (isErr(result)) {\n logger.error(`Error when calculating score: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new StepExecutionError(\n translateErrorCode(translator, code),\n code,\n {\n gameId: game.id,\n },\n );\n }\n\n return {\n playerId: player.id,\n playerName: player.name,\n details: {\n ...result.value,\n },\n };\n });\n\n const result = getResultUseCase(game, scoreResult);\n\n if (isErr(result)) {\n logger.error(`Error getting result: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new NotFoundError(translateErrorCode(translator, code), code, {\n gameId: game.id,\n });\n }\n\n logger.info(`Result retrieved for game: ${game.id}`);\n return result.value;\n };\n","import type { GetValidPlacementsCommand } from \"@application/commands/getValidPlacementsCommand.js\";\nimport type { Domino, Kingdom } from \"@core/domain/types/index.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { ValidPlacement } from \"@core/useCases/getValidPlacements.js\";\n\ntype GetValidPlacementsUseCase = (\n kingdom: Kingdom,\n domino: Domino,\n maxKingdomSize?: number,\n) => ValidPlacement[];\n\ntype GetValidPlacementsHandler = (\n command: GetValidPlacementsCommand,\n) => ValidPlacement[];\n\n/**\n * Creates a handler for getting valid placements.\n */\nexport const getValidPlacementsHandler = (\n logger: Logger,\n translator: Translator,\n useCase: GetValidPlacementsUseCase,\n): GetValidPlacementsHandler => {\n return (command) => {\n logger.info(\n `Getting valid placements for domino: ${command.domino.number}`,\n );\n const placements = useCase(\n command.kingdom,\n command.domino,\n command.maxKingdomSize,\n );\n logger.info(`Found ${placements.length} valid placements`);\n return placements;\n };\n};\n","import type { PlaceDominoCommand } from \"@application/commands/placeDominoCommand.js\";\nimport {\n ActionExecutionError,\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameState,\n isGameWithNextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport { translateErrorCode } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { PlaceDominoUseCase } from \"@core/useCases/placeDomino.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype PlaceDominoHandler = (command: PlaceDominoCommand) => GameState;\n\nexport const placeDominoHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: PlaceDominoUseCase,\n ): PlaceDominoHandler =>\n (command: PlaceDominoCommand) => {\n const { game, lordId, position, rotation } = command;\n logger.info(\n `Placing domino: ${lordId} in position: ${JSON.stringify(\n position,\n )} with rotation: ${rotation} in game: ${game.id}`,\n );\n\n if (!isGameWithNextAction(game)) {\n logger.error(\n `Invalid game, required nextAction type: 'action' but got: ${game.nextAction.type}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n { expected: \"action\", actual: game.nextAction.type, gameId: game.id },\n );\n }\n\n if (game.nextAction.nextAction !== \"placeDomino\") {\n logger.error(\n `Required game with placeDomino action but got: ${game.nextAction.nextAction}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"placeDomino\",\n actual: game.nextAction.nextAction,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(game, lordId, position, rotation);\n\n if (isErr(result)) {\n logger.error(`Error placing domino: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new ActionExecutionError(\n translateErrorCode(translator, code),\n code,\n {\n gameId: game.id,\n lordId: command.lordId,\n position: command.position,\n rotation: command.rotation,\n },\n );\n }\n\n if (isGameWithNextAction(result.value)) {\n logger.info(\n `Domino placed: ${lordId} in position: ${JSON.stringify(\n position,\n )} with rotation: ${rotation} in game: ${game.id}`,\n );\n return result.value;\n }\n\n logger.info(\n `Domino placed: ${lordId} in position: ${JSON.stringify(\n position,\n )} with rotation: ${rotation} in game: ${game.id}`,\n );\n return result.value;\n };\n","import type { GameState } from \"@core/domain/types/index.js\";\nimport { ok, err, type Result } from \"@utils/result.js\";\n\n/**\n * Serialization format version for backwards compatibility.\n */\nconst SERIALIZATION_VERSION = 1;\n\n/**\n * Serialized game data structure.\n */\ninterface SerializedGame {\n version: number;\n data: GameState;\n timestamp: string;\n}\n\n/**\n * Serializes a game state to a JSON string.\n * The serialized string includes version information for future compatibility.\n *\n * @param game - The game state to serialize\n * @returns JSON string representation of the game\n */\nexport const serializeGame = (game: GameState): string => {\n const serialized: SerializedGame = {\n version: SERIALIZATION_VERSION,\n data: game,\n timestamp: new Date().toISOString(),\n };\n return JSON.stringify(serialized);\n};\n\n/**\n * Deserializes a JSON string back to a game state.\n * Validates the structure and version before returning.\n *\n * @param json - The JSON string to deserialize\n * @returns Result containing the game state or an error\n */\nexport const deserializeGame = (json: string): Result<GameState> => {\n try {\n const parsed = JSON.parse(json) as SerializedGame;\n\n // Validate structure\n if (!parsed.version || !parsed.data) {\n return err(\"Invalid serialized game format\");\n }\n\n // Check version compatibility\n if (parsed.version > SERIALIZATION_VERSION) {\n return err(\n `Unsupported serialization version: ${parsed.version}. Current version: ${SERIALIZATION_VERSION}`\n );\n }\n\n // Validate essential game properties\n const game = parsed.data;\n if (!game.id || !game.players || !game.lords || !game.nextAction) {\n return err(\"Invalid game state structure\");\n }\n\n return ok(game);\n } catch (error) {\n return err(`Failed to parse game JSON: ${(error as Error).message}`);\n }\n};\n\n/**\n * Creates a save point for the current game state.\n * Includes metadata for debugging and restore purposes.\n */\nexport interface GameSavePoint {\n /** Serialized game data */\n serialized: string;\n /** When the save was created */\n createdAt: string;\n /** Game ID for reference */\n gameId: string;\n /** Current turn number */\n turn: number;\n}\n\n/**\n * Creates a save point from a game state.\n *\n * @param game - The game state to save\n * @returns A save point object with metadata\n */\nexport const createSavePoint = (game: GameState): GameSavePoint => {\n return {\n serialized: serializeGame(game),\n createdAt: new Date().toISOString(),\n gameId: game.id,\n turn: game.turn,\n };\n};\n\n/**\n * Restores a game state from a save point.\n *\n * @param savePoint - The save point to restore from\n * @returns Result containing the restored game state or an error\n */\nexport const restoreFromSavePoint = (\n savePoint: GameSavePoint\n): Result<GameState> => {\n return deserializeGame(savePoint.serialized);\n};\n","import type {\n DeserializeGameCommand,\n SerializeGameCommand,\n} from \"@application/commands/serializeGameCommand.js\";\nimport {\n type ErrorCodeType,\n StepExecutionError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { GameState } from \"@core/domain/types/index.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport { translateErrorCode } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport {\n deserializeGame,\n serializeGame,\n} from \"@core/useCases/serialization.js\";\nimport { isErr, unwrap } from \"@utils/result.js\";\n\ntype SerializeGameHandler = (command: SerializeGameCommand) => string;\ntype DeserializeGameHandler = (command: DeserializeGameCommand) => GameState;\n\n/**\n * Creates a handler for serializing game state.\n */\nexport const serializeGameHandler = (\n logger: Logger,\n _translator: Translator,\n): SerializeGameHandler => {\n return (command) => {\n logger.info(`Serializing game: ${command.game.id}`);\n const serialized = serializeGame(command.game);\n logger.info(`Game serialized successfully`);\n return serialized;\n };\n};\n\n/**\n * Creates a handler for deserializing game state.\n */\nexport const deserializeGameHandler = (\n logger: Logger,\n translator: Translator,\n): DeserializeGameHandler => {\n return (command) => {\n logger.info(`Deserializing game from JSON`);\n const result = deserializeGame(command.json);\n\n if (isErr(result)) {\n logger.error(`Failed to deserialize game: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new StepExecutionError(translateErrorCode(translator, code), code);\n }\n\n const game = unwrap(result);\n logger.info(`Game deserialized successfully: ${game.id}`);\n return game;\n };\n};\n","import type { StartGameCommand } from \"@application/commands/startGameCommand.js\";\nimport {\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n StepExecutionError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameWithNextAction,\n isGameWithNextStep,\n} from \"@core/domain/types/game.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport { translateErrorCode } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { StartGameUseCase } from \"@core/useCases/startGame.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype StartGameHandler = (command: StartGameCommand) => GameWithNextAction;\n\nexport const startGameHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: StartGameUseCase,\n ): StartGameHandler =>\n (command: StartGameCommand) => {\n const { game } = command;\n logger.info(`Starting game: ${game.id}`);\n\n if (!isGameWithNextStep(game)) {\n logger.error(\n `Invalid game, required nextAction type: 'step' but got: ${game.nextAction.type}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n { expected: \"step\", actual: game.nextAction.type, gameId: game.id },\n );\n }\n\n if (\n game.nextAction.step !== \"start\" &&\n game.nextAction.step !== \"options\"\n ) {\n logger.error(\n `Required game with start step or options step but got: ${game.nextAction.step}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"start|options\",\n actual: game.nextAction.step,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(game);\n\n if (isErr(result)) {\n logger.error(`Error starting game: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new StepExecutionError(translateErrorCode(translator, code), code, {\n gameId: game.id,\n });\n }\n\n logger.info(`Game started: ${game.id}`);\n return result.value;\n };\n","import type { EmptyTile, Tile } from \"./domino.js\";\n\n/**\n * Represents a position on the kingdom grid.\n * Origin (0,0) is at the top-left corner.\n */\nexport type Position = {\n /** Column index (0-8, left to right) */\n x: number;\n /** Row index (0-8, top to bottom) */\n y: number;\n};\n\n/**\n * Rotation angle for domino placement.\n * - 0: Horizontal, left tile at position, right tile to the east\n * - 90: Vertical, left tile at position, right tile to the south\n * - 180: Horizontal, right tile at position, left tile to the east\n * - 270: Vertical, right tile at position, left tile to the south\n */\nexport type Rotation = 0 | 90 | 180 | 270;\n\n/**\n * Represents a player's kingdom as a 2D grid of tiles.\n * The grid is 9x9 to allow for the 5x5 maximum kingdom size\n * with the castle at any position.\n */\nexport type Kingdom = (Tile | EmptyTile)[][];\n\n/**\n * The size of the kingdom grid (9x9).\n * This allows for a 5x5 kingdom with the castle placed anywhere.\n */\nexport const GRIDSIZE = 9;\n\n/**\n * Maximum kingdom size (5x5 in standard rules, 7x7 for Mighty Duel).\n */\nexport const MAX_KINGDOM_SIZE = 5;\n","/**\n * All possible ground/terrain types in Kingdomino.\n * Each type can form contiguous properties for scoring.\n */\nexport const GROUND = [\n \"castle\",\n \"wheat\",\n \"forest\",\n \"sea\",\n \"plain\",\n \"swamp\",\n \"mine\",\n] as const;\n\n/** Union type of all terrain types */\nexport type Ground = (typeof GROUND)[number];\n\n/** Special ground type for empty/unplaced tiles */\nexport type EmptyGround = \"empty\";\n\n/** Number of crowns on a tile (0-3) */\nexport type Crown = number;\n\n/**\n * Represents a single tile with terrain and crowns.\n * Two tiles form a domino.\n */\nexport type Tile = {\n /** The terrain type of this tile */\n type: Ground;\n /** Number of crowns (0-3), multiplier for scoring */\n crowns: Crown;\n};\n\n/**\n * Represents an empty/unplaced tile on the kingdom grid.\n */\nexport type EmptyTile = {\n /** Always \"empty\" for unplaced tiles */\n type: EmptyGround;\n /** Empty tiles have no crowns */\n crowns: 0;\n};\n\n/**\n * Represents a domino piece consisting of two connected tiles.\n * Dominoes are the main game pieces that players place on their kingdoms.\n */\nexport type Domino = {\n /** The left tile of the domino */\n left: Tile;\n /** The right tile of the domino */\n right: Tile;\n /** Unique number identifying this domino (1-48 in Classic mode) */\n number: number;\n};\n\n/**\n * Represents a domino that has been revealed for player selection.\n * Contains selection state for the current turn.\n */\nexport type RevealsDomino = {\n /** The actual domino piece */\n domino: Domino;\n /** Whether this domino has been picked by a lord */\n picked: boolean;\n /** ID of the lord who picked this domino, or null if unpicked */\n lordId: string | null;\n /** Display position in the revealed set (for UI ordering) */\n position: number;\n};\n","import type { Kingdom } from \"./kingdom.js\";\nimport type { ObjectValues } from \"./utils.js\";\n\n/**\n * Represents a player in the game.\n */\nexport type Player = {\n /** Unique identifier for the player */\n id: string;\n /** Display name of the player */\n name: string;\n /** The player's kingdom grid where dominoes are placed */\n kingdom: Kingdom;\n /** If set, this player is controlled by a bot with the named strategy */\n bot?: { strategyName: string };\n};\n\n/**\n * Payload for creating a new player.\n */\nexport type PlayerPayload = {\n /** Display name for the player (minimum 3 characters) */\n name: string;\n};\n\n/** Array of player creation payloads */\nexport type PlayersPayload = PlayerPayload[];\n\n/** Array of players */\nexport type Players = Player[];\n\n/**\n * Available actions a player can perform during their turn.\n */\nexport const playerActions = {\n /** Place a previously picked domino on the kingdom */\n placeDomino: \"placeDomino\",\n /** Pick a domino from the revealed set */\n pickDomino: \"pickDomino\",\n /** Pass/discard when no valid placement exists */\n pass: \"pass\",\n} as const;\n\n/** Union type of all player actions */\nexport type PlayerActions = ObjectValues<typeof playerActions>;\n","import { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type { ExtraRule } from \"@core/domain/types/rule.js\";\nimport { ok, err, type Result } from \"@utils/result.js\";\n\nexport const getAvailablesExtraRules = (\n extraRules: ExtraRule[],\n mode: string,\n numberOfPlayers: number\n): Result<ExtraRule[]> => {\n const availableExtraRules = extraRules.filter((rule) => {\n return (\n rule.mode.filter((m) => m.name === mode).length > 0 &&\n (!rule.playersLimit || rule.playersLimit === numberOfPlayers)\n );\n });\n\n if (availableExtraRules.length === 0) {\n return err(ErrorCode.STEP_EXECUTION_FAILED);\n }\n\n return ok(availableExtraRules);\n};\n\nexport const toExtraRule = (\n rule: string,\n extraRules: ExtraRule[]\n): Result<ExtraRule> => {\n const foundRule = extraRules.find((r) => r.name === rule);\n\n if (!foundRule) {\n return err(ErrorCode.STEP_EXECUTION_FAILED);\n }\n\n return ok(foundRule);\n};\n","import type { ShuffleMethod } from \"@core/portServerside/shuffleMethod.js\";\n\nconst hashSeed = (str: string): number => {\n let hash = 2166136261;\n for (let i = 0; i < str.length; i++) {\n hash ^= str.charCodeAt(i);\n hash = Math.imul(hash, 16777619);\n }\n return hash >>> 0;\n};\n\nconst mulberry32 = (seed: number): (() => number) => {\n let state = seed;\n return () => {\n state |= 0;\n state = (state + 0x6d2b79f5) | 0;\n let t = Math.imul(state ^ (state >>> 15), 1 | state);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n};\n\nexport const createSeededShuffle = (\n seed: string,\n salt: string\n): ShuffleMethod => {\n const numericSeed = hashSeed(`${seed}|${salt}`);\n const random = mulberry32(numericSeed);\n\n return <T>(array: T[]): T[] => {\n const result = [...array];\n for (let i = result.length - 1; i > 0; i--) {\n const j = Math.floor(random() * (i + 1));\n [result[i], result[j]] = [result[j] as T, result[i] as T];\n }\n return result;\n };\n};\n","import {\n gameSteps,\n type ExtraRule,\n type GameWithNextStep,\n type NextStep,\n} from \"@core/domain/types/index.js\";\nimport { isErr, ok, type Result } from \"@utils/result.js\";\nimport type { RuleRepository } from \"@core/portServerside/ruleRepository.js\";\nimport type { DominoesRepository } from \"@core/portServerside/dominoesRepository.js\";\nimport type { ShuffleMethod } from \"@core/portServerside/shuffleMethod.js\";\nimport { toExtraRule } from \"@core/domain/entities/rule.js\";\nimport { createSeededShuffle } from \"@utils/seededShuffle.js\";\n\nexport type AddExtraRulesUseCase = (\n game: GameWithNextStep,\n rules: string[]\n) => Result<GameWithNextStep>;\n\nexport const addExtraRulesUseCase =\n (deps: {\n ruleRepository: RuleRepository;\n dominoesRepository: DominoesRepository;\n shuffleMethod: ShuffleMethod;\n }): AddExtraRulesUseCase =>\n (game, rules) => {\n const { ruleRepository, dominoesRepository, shuffleMethod } = deps;\n const availableExtraRules = ruleRepository.getAllExtra();\n\n const newExtraRules: ExtraRule[] = [];\n\n for (const rule of rules) {\n const result = toExtraRule(rule, availableExtraRules);\n\n if (isErr(result)) {\n return result;\n }\n\n newExtraRules.push(result.value);\n }\n\n // The Mighty Duel overrides basic rules for 2-player games\n let updatedBasic = game.rules.basic;\n let updatedDominoes = game.dominoes;\n const hasMightyDuel = newExtraRules.some((r) => r.name === \"The Mighty Duel\");\n if (hasMightyDuel) {\n updatedBasic = {\n ...updatedBasic,\n maxDominoes: 48,\n maxTurns: 12,\n maxKingdomSize: 7,\n };\n // Reload and shuffle all 48 dominoes\n const allDominoes = dominoesRepository.getForMode(game.mode);\n if (allDominoes) {\n const shuffle = game.seed\n ? createSeededShuffle(game.seed, \"mighty-duel\")\n : shuffleMethod;\n updatedDominoes = shuffle(allDominoes);\n }\n }\n\n const updatedRules = {\n basic: updatedBasic,\n extra: newExtraRules,\n };\n\n const next: NextStep = {\n type: \"step\",\n step: gameSteps.start,\n };\n\n const updatedGame: GameWithNextStep = {\n ...game,\n dominoes: updatedDominoes,\n rules: updatedRules,\n nextAction: next,\n };\n\n return ok(updatedGame);\n };\n","import {\n GROUND,\n type Crown,\n type EmptyGround,\n type EmptyTile,\n type Ground,\n type Tile,\n} from \"@core/domain/types/domino.js\";\n\nconst isGround = (ground: any): ground is Ground => {\n return GROUND.includes(ground);\n};\n\nexport const createTile = (\n ground: Ground | EmptyGround,\n crowns: Crown = 0\n): Tile | EmptyTile => {\n if (isGround(ground)) {\n return { type: ground, crowns } as Tile;\n }\n return { type: ground, crowns: 0 } as EmptyTile;\n};\n","import {\n type Domino,\n type EmptyTile,\n GRIDSIZE,\n MAX_KINGDOM_SIZE,\n type Kingdom,\n type Position,\n type Rotation,\n type Tile,\n} from \"@core/domain/types/index.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport {err, isErr, isOk, ok, type Result} from \"@utils/result.js\";\nimport {createTile} from \"./domino.js\";\n\nexport const createEmptyKingdom = (): Kingdom => {\n const emptyTile = createTile(\"empty\");\n return Array.from({length: GRIDSIZE}, () =>\n Array.from({length: GRIDSIZE}, () => emptyTile)\n );\n};\n\nexport const placeCastle = (kingdom: Kingdom): Kingdom => {\n const castle = createTile(\"castle\");\n const newKingdom = deepCopyKingdom(kingdom);\n newKingdom[4]![4] = castle;\n return newKingdom;\n};\n\nexport const placeTile = (\n kingdom: Kingdom,\n position: Position,\n tile: Tile\n): Kingdom => {\n const newKingdom = deepCopyKingdom(kingdom);\n newKingdom[position.y]![position.x] = tile;\n return newKingdom;\n};\n\nexport const getTile = (\n kingdom: Kingdom,\n position: Position\n): Result<Tile | EmptyTile> => {\n const tile = kingdom[position.y]?.[position.x];\n if (!tile) {\n return err(ErrorCode.PLACEMENT_OUT_OF_BOUNDS);\n }\n return ok(tile);\n};\n\nexport const calculateDominoPosition = (\n position: Position,\n rotation: Rotation,\n domino: Domino\n): [{ tile: Tile; position: Position }, { tile: Tile; position: Position }] => {\n let firstTile: {\n tile: Tile;\n position: Position;\n };\n let secondTile: {\n tile: Tile;\n position: Position;\n };\n\n switch (rotation) {\n case 0: // horizontal, left to right\n firstTile = {\n tile: domino.left,\n position: {\n x: position.x,\n y: position.y,\n },\n };\n secondTile = {\n tile: domino.right,\n position: {\n x: position.x + 1,\n y: position.y,\n },\n };\n break;\n case 90: // vertical, top to bottom\n firstTile = {\n tile: domino.left,\n position: {\n x: position.x,\n y: position.y,\n },\n };\n secondTile = {\n tile: domino.right,\n position: {\n x: position.x,\n y: position.y + 1,\n },\n };\n break;\n case 180: // horizontal, right to left\n firstTile = {\n tile: domino.right,\n position: {\n x: position.x,\n y: position.y,\n },\n };\n secondTile = {\n tile: domino.left,\n position: {\n x: position.x + 1,\n y: position.y,\n },\n };\n break;\n case 270: // vertical, bottom to top\n firstTile = {\n tile: domino.right,\n position: {\n x: position.x,\n y: position.y,\n },\n };\n secondTile = {\n tile: domino.left,\n position: {\n x: position.x,\n y: position.y + 1,\n },\n };\n break;\n }\n\n return [firstTile, secondTile];\n};\n\nexport const placeDomino = (\n kingdom: Kingdom,\n position: Position,\n rotation: Rotation,\n domino: Domino,\n maxKingdomSize: number = MAX_KINGDOM_SIZE\n): Result<Kingdom> => {\n const [firstTile, secondTile] = calculateDominoPosition(\n position,\n rotation,\n domino\n );\n\n const isFreePlaceResult = isFreePlace(\n kingdom,\n firstTile.position,\n secondTile.position\n );\n if (isErr(isFreePlaceResult)) {\n return isFreePlaceResult;\n }\n\n if (exceedsMaxSize(kingdom, firstTile.position, secondTile.position, maxKingdomSize)) {\n return err(ErrorCode.PLACEMENT_EXCEEDS_KINGDOM_SIZE);\n }\n\n const adjacentTiles = isAdjacent(\n kingdom,\n firstTile.position,\n secondTile.position\n );\n\n if (adjacentTiles.length === 0) {\n return err(ErrorCode.PLACEMENT_NOT_ADJACENT);\n }\n\n const hasValidAdjacentTiles = hasValidAdjacent(adjacentTiles, [\n firstTile.tile,\n secondTile.tile,\n ]);\n\n if (!hasValidAdjacentTiles) {\n return err(ErrorCode.PLACEMENT_INVALID_TERRAIN);\n }\n\n return ok(placeTiles(kingdom, [firstTile, secondTile]));\n};\n\nconst placeTiles = (\n kingdom: Kingdom,\n tiles: { tile: Tile; position: Position }[]\n) => {\n let newKingdom = deepCopyKingdom(kingdom);\n for (const { tile, position } of tiles) {\n newKingdom = placeTile(newKingdom, position, tile);\n }\n return newKingdom;\n};\n\nconst isFreePlace = (\n kingdom: Kingdom,\n firstPosition: Position,\n secondPosition: Position\n): Result<boolean> => {\n const firstTile = getTile(kingdom, firstPosition);\n const secondTile = getTile(kingdom, secondPosition);\n\n if (isErr(firstTile)) {\n return firstTile;\n }\n\n if (isErr(secondTile)) {\n return secondTile;\n }\n\n if (firstTile.value.type !== \"empty\" || secondTile.value.type !== \"empty\") {\n return err(ErrorCode.PLACEMENT_NOT_EMPTY);\n }\n\n return ok(true);\n};\n\nconst isAdjacent = (\n kingdom: Kingdom,\n firstPosition: Position,\n secondPosition: Position\n): Tile[] => {\n const offsets = [\n { x: -1, y: 0 },\n { x: 1, y: 0 },\n { x: 0, y: -1 },\n { x: 0, y: 1 },\n ];\n\n const isOwnPosition = (x: number, y: number) =>\n (x === firstPosition.x && y === firstPosition.y) ||\n (x === secondPosition.x && y === secondPosition.y);\n\n const adjacentTiles: Tile[] = [];\n\n for (const pos of [firstPosition, secondPosition]) {\n for (const offset of offsets) {\n const nx = pos.x + offset.x;\n const ny = pos.y + offset.y;\n if (isOwnPosition(nx, ny)) continue;\n const tile = getTile(kingdom, { x: nx, y: ny });\n if (isOk(tile) && tile.value.type !== \"empty\") {\n adjacentTiles.push(tile.value);\n }\n }\n }\n\n return adjacentTiles;\n};\n\nconst hasValidAdjacent = (\n adjacentTiles: (Tile | EmptyTile)[],\n tiles: Tile[]\n): boolean => {\n return adjacentTiles.some((adjacentTile) => {\n return tiles.some((tile) => {\n return tile.type === adjacentTile.type || adjacentTile.type === \"castle\";\n });\n });\n};\n\nexport const checkCastleIsInMiddle = (kingdom: Kingdom): boolean => {\n // Find castle coordinates\n let castleX: number | undefined;\n let castleY: number | undefined;\n\n for (let y = 0; y < kingdom.length; y++) {\n const x = kingdom[y]!.findIndex((tile) => tile.type === \"castle\");\n if (x !== -1) {\n castleX = x;\n castleY = y;\n break;\n }\n }\n\n if (castleX === undefined || castleY === undefined) {\n return false;\n }\n\n const bbox = getBoundingBox(kingdom);\n if (!bbox) return false;\n\n // Castle must be at the exact center of the bounding box\n const centerX = (bbox.minX + bbox.maxX) / 2;\n const centerY = (bbox.minY + bbox.maxY) / 2;\n\n return castleX === centerX && castleY === centerY;\n};\n\nexport const getBoundingBox = (\n kingdom: Kingdom\n): { minX: number; maxX: number; minY: number; maxY: number } | null => {\n let minX = Infinity;\n let maxX = -Infinity;\n let minY = Infinity;\n let maxY = -Infinity;\n\n for (let y = 0; y < kingdom.length; y++) {\n for (let x = 0; x < kingdom[y]!.length; x++) {\n if (kingdom[y]![x]!.type !== \"empty\") {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n }\n }\n\n if (minX === Infinity) return null;\n return { minX, maxX, minY, maxY };\n};\n\nconst exceedsMaxSize = (\n kingdom: Kingdom,\n firstPosition: Position,\n secondPosition: Position,\n maxSize: number = MAX_KINGDOM_SIZE\n): boolean => {\n const bbox = getBoundingBox(kingdom);\n\n let minX = bbox?.minX ?? Infinity;\n let maxX = bbox?.maxX ?? -Infinity;\n let minY = bbox?.minY ?? Infinity;\n let maxY = bbox?.maxY ?? -Infinity;\n\n for (const pos of [firstPosition, secondPosition]) {\n if (pos.x < minX) minX = pos.x;\n if (pos.x > maxX) maxX = pos.x;\n if (pos.y < minY) minY = pos.y;\n if (pos.y > maxY) maxY = pos.y;\n }\n\n return (maxX - minX + 1) > maxSize || (maxY - minY + 1) > maxSize;\n};\n\nexport const countDominoes = (kingdom: Kingdom): number => {\n const notEmpties = kingdom.flat().filter((tile) => tile.type !== \"empty\");\n // -1 because the castle is not a domino\n return (notEmpties.length - 1) / 2;\n};\n\nconst deepCopyKingdom = (kingdom: Kingdom): Kingdom => {\n return kingdom.map((line) => line.map((tile) => ({ ...tile })));\n};\n","import { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport { type Result, err, ok, isErr } from \"@utils/result.js\";\nimport type { Player } from \"@core/domain/types/player.js\";\nimport type { Kingdom } from \"@core/domain/types/kingdom.js\";\n\nconst MINPLAYERSNAMELENGTH = 3;\n\nexport const validatePlayer = (name: string): Result<string> => {\n if (!name || name.trim().length < MINPLAYERSNAMELENGTH) {\n return err(ErrorCode.INVALID_PLAYER_NAME);\n }\n\n return ok(name);\n};\n\nexport const createPlayer = (\n playerName: string,\n id: string,\n kingdom: Kingdom,\n bot?: { strategyName: string }\n): Result<Player> => {\n const name = validatePlayer(playerName);\n\n if (isErr(name)) {\n return name;\n }\n\n return ok({\n name: name.value,\n id,\n kingdom,\n ...(bot && { bot }),\n });\n};\n","import {\n createEmptyKingdom,\n placeCastle,\n} from \"@core/domain/entities/kingdom.js\";\nimport { createPlayer } from \"@core/domain/entities/player.js\";\nimport type {\n GameWithNextStep,\n NextStep,\n Players,\n} from \"@core/domain/types/index.js\";\nimport type { RuleRepository } from \"@core/portServerside/ruleRepository.js\";\nimport type { ShuffleMethod } from \"@core/portServerside/shuffleMethod.js\";\nimport type { UuidMethod } from \"@core/portServerside/uuidMethod.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport { err, isErr, ok, type Result } from \"@utils/result.js\";\nimport { createSeededShuffle } from \"@utils/seededShuffle.js\";\nimport type { PlayerInput } from \"@application/commands/addPlayersCommand.js\";\n\nexport type AddPlayersUseCase = (\n game: GameWithNextStep,\n players: PlayerInput[]\n) => Result<GameWithNextStep>;\n\nconst normalizePlayerInput = (\n input: PlayerInput\n): { name: string; bot?: { strategyName: string } } => {\n if (typeof input === \"string\") {\n return { name: input };\n }\n return { name: input.name, bot: input.bot };\n};\n\nexport const addPlayersUseCase =\n (deps: {\n uuidMethod: UuidMethod;\n shuffleMethod: ShuffleMethod;\n ruleRepository: RuleRepository;\n }): AddPlayersUseCase =>\n (game, players) => {\n const { uuidMethod, shuffleMethod, ruleRepository } = deps;\n\n if (!players || players.length < 1 || players.length > 4) {\n return err(ErrorCode.INVALID_PLAYER_COUNT);\n }\n\n const newPlayers: Players = [];\n\n for (const player of players) {\n const { name, bot } = normalizePlayerInput(player);\n let kingdom = createEmptyKingdom();\n kingdom = placeCastle(kingdom);\n let id = uuidMethod();\n const newPlayer = createPlayer(name, id, kingdom, bot);\n\n if (isErr(newPlayer)) {\n return newPlayer;\n }\n\n newPlayers.push(newPlayer.value);\n }\n\n // set rules\n const rules = ruleRepository.getAll();\n const basicRules = rules.basic[newPlayers.length];\n\n if (!basicRules) {\n return err(ErrorCode.STEP_EXECUTION_FAILED);\n }\n\n // updateDominoes\n const dominoes = game.dominoes;\n const { maxDominoes } = basicRules;\n const shuffle = game.seed\n ? createSeededShuffle(game.seed, \"dominoes\")\n : shuffleMethod;\n const shuffledDominoes = shuffle(dominoes);\n const splicedDominoes = shuffledDominoes.slice(0, maxDominoes);\n const next: NextStep = {\n type: \"step\",\n step: \"options\",\n };\n\n const updatedGame: GameWithNextStep = {\n ...game,\n players: newPlayers,\n dominoes: splicedDominoes,\n rules: {\n ...game.rules,\n basic: basicRules,\n },\n nextAction: next,\n };\n\n return ok(updatedGame);\n };\n","import type { Kingdom, Score } from \"@core/domain/types/index.js\";\nimport { ok, type Result } from \"@utils/result.js\";\n\nexport type CalculateScoreUseCase = (kingdom: Kingdom) => Result<Score>;\n\ntype Property = {\n size: number;\n crowns: number;\n};\n\nexport const calculateScoreUseCase: CalculateScoreUseCase = (kingdom) => {\n const rows = kingdom.length;\n const cols = kingdom[0]!.length;\n const visited: boolean[][] = kingdom.map((row) => row.map(() => false));\n const properties: Property[] = [];\n\n const directions = [\n [-1, 0],\n [1, 0],\n [0, -1],\n [0, 1],\n ];\n\n for (let y = 0; y < rows; y++) {\n for (let x = 0; x < cols; x++) {\n const tile = kingdom[y]![x]!;\n if (visited[y]![x] || tile.type === \"empty\" || tile.type === \"castle\") {\n continue;\n }\n\n // BFS flood-fill for this property\n const type = tile.type;\n let size = 0;\n let crowns = 0;\n const queue: [number, number][] = [[x, y]];\n visited[y]![x] = true;\n\n while (queue.length > 0) {\n const [cx, cy] = queue.pop()!;\n const current = kingdom[cy]![cx]!;\n size++;\n crowns += current.crowns;\n\n for (const [dx, dy] of directions) {\n const nx = cx + (dx as number);\n const ny = cy + (dy as number);\n if (\n nx >= 0 &&\n ny >= 0 &&\n nx < cols &&\n ny < rows &&\n !visited[ny]![nx] &&\n kingdom[ny]![nx]!.type === type\n ) {\n visited[ny]![nx] = true;\n queue.push([nx, ny]);\n }\n }\n }\n\n properties.push({ size, crowns });\n }\n }\n\n if (properties.length === 0) {\n return ok({\n points: 0,\n maxPropertiesSize: 0,\n totalCrowns: 0,\n });\n }\n\n let points = 0;\n let maxPropertiesSize = 0;\n let totalCrowns = 0;\n\n for (const property of properties) {\n points += property.size * property.crowns;\n if (property.size > maxPropertiesSize) {\n maxPropertiesSize = property.size;\n }\n totalCrowns += property.crowns;\n }\n\n return ok({\n points,\n maxPropertiesSize,\n totalCrowns,\n });\n};\n","import type { NextAction } from \"@core/domain/types/game.js\";\nimport type { Lord } from \"@core/domain/types/lord.js\";\nimport { playerActions } from \"@core/domain/types/player.js\";\n\nexport const createLord = (id: string, playerId: string): Lord => {\n return {\n id,\n playerId,\n turnEnded: false,\n hasPick: false,\n hasPlace: true,\n };\n};\n\nconst hasPick = (lord: Lord): boolean => lord.hasPick;\nconst hasPlace = (lord: Lord): boolean => lord.hasPlace;\nconst hasTurnEnded = (lord: Lord): boolean => lord.turnEnded;\n\nexport const canPass = (lord: Lord): boolean => {\n return !hasPick(lord) && !hasPlace(lord) && !hasTurnEnded(lord);\n};\n\nexport const canPick = (lord: Lord): boolean => {\n return !hasPick(lord) && hasPlace(lord) && !hasTurnEnded(lord);\n};\n\nexport const canPlaceAndDominoPickedIsDefined = (\n lord: Lord\n): lord is Required<Lord & Pick<Lord, \"dominoPicked\">> => {\n return (\n !hasPick(lord) &&\n !hasPlace(lord) &&\n !hasTurnEnded(lord) &&\n lord.dominoPicked !== undefined\n );\n};\n\nexport const updateLordOrder = (lords: Lord[]): Lord[] => {\n return [...lords].sort((a, b) => {\n return (a.dominoPicked?.number ?? 0) - (b.dominoPicked?.number ?? 0);\n });\n};\n\nexport const resetLordsActions = (lords: Lord[]): Lord[] => {\n return lords.map((lord) => ({\n ...lord,\n turnEnded: false,\n hasPick: false,\n hasPlace: false,\n }));\n};\n\nexport const nextLordWithAction = (lords: Lord[]): NextAction => {\n const nextLord = findNextLord(lords);\n\n return {\n type: \"action\",\n nextLord: nextLord.id,\n nextAction: hasPlace(nextLord)\n ? playerActions.pickDomino\n : playerActions.placeDomino,\n };\n};\n\nconst findNextLord = (lords: Lord[]): Lord => {\n const lord = lords.find((lord) => !hasTurnEnded(lord));\n if (!lord) {\n return lords[0]!;\n }\n return lord;\n};\n\nexport const allLordsHavePlayed = (lords: Lord[]): boolean => {\n return lords.every((lord) => lord.turnEnded);\n};\n","import {\n allLordsHavePlayed,\n canPick,\n nextLordWithAction,\n resetLordsActions,\n updateLordOrder,\n} from \"@core/domain/entities/lord.js\";\nimport type { GameWithNextAction } from \"@core/domain/types/game.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport { err, ok, type Result } from \"@utils/result.js\";\n\nexport type ChooseDominoUseCase = (\n game: GameWithNextAction,\n lordId: string,\n dominoPick: number\n) => Result<GameWithNextAction>;\n\nexport const chooseDominoUseCase: ChooseDominoUseCase = (\n game,\n lordId,\n dominoPick\n) => {\n const currentLord = game.lords.find(\n (lord) => lord.id === game.nextAction.nextLord\n );\n\n if (!currentLord) {\n return err(ErrorCode.LORD_NOT_FOUND);\n }\n\n if (currentLord.id !== lordId) {\n return err(ErrorCode.NOT_YOUR_TURN);\n }\n\n if (!canPick(currentLord)) {\n return err(ErrorCode.CANNOT_PICK);\n }\n\n // Check if dominoPick is valid choice\n const selectedDomino = game.currentDominoes.find(\n (domino) => domino.domino.number === dominoPick\n );\n\n if (!selectedDomino) {\n return err(ErrorCode.DOMINO_NOT_FOUND);\n }\n\n if (selectedDomino.picked) {\n return err(ErrorCode.DOMINO_ALREADY_PICKED);\n }\n\n // update currentDominoes\n const updatedCurrentDominoes = game.currentDominoes.map((domino) =>\n domino.domino.number === dominoPick\n ? { ...domino, picked: true, lordId: currentLord.id }\n : domino\n );\n\n // update lords\n const updatedLords = game.lords.map((lord) =>\n lord.id === currentLord.id\n ? { ...lord, hasPick: true, turnEnded: true, dominoPicked: selectedDomino.domino }\n : lord\n );\n\n const turnEnded = allLordsHavePlayed(updatedLords);\n\n if (turnEnded) {\n const lords = resetLordsActions(updateLordOrder(updatedLords));\n const updatedTurn = game.turn + 1;\n const next = nextLordWithAction(lords);\n const dominoesCopy = [...game.dominoes];\n const dominoesDrawn = dominoesCopy.splice(\n 0,\n game.rules.basic.dominoesPerTurn\n );\n dominoesDrawn.sort((a, b) => a.number - b.number);\n const updatedCurrentDominoes = dominoesDrawn.map((domino, index) => {\n return {\n domino,\n picked: false,\n lordId: null,\n position: index + 1,\n };\n });\n\n return ok({\n ...game,\n currentDominoes: updatedCurrentDominoes,\n dominoes: dominoesCopy,\n lords,\n turn: updatedTurn,\n nextAction: next,\n });\n }\n\n const next = nextLordWithAction(updatedLords);\n\n // update state\n const updatedState = {\n ...game,\n currentDominoes: updatedCurrentDominoes,\n lords: updatedLords,\n nextAction: next,\n };\n\n return ok(updatedState);\n};\n","import {\n gameSteps,\n type Domino,\n type GameMode,\n type GameWithNextStep,\n} from \"@core/domain/types/index.js\";\n\nexport const create = (payload: {\n id: string;\n mode: GameMode;\n dominoes: Domino[];\n seed?: string;\n}): GameWithNextStep => {\n const { id, mode, dominoes, seed } = payload;\n return {\n id,\n dominoes,\n currentDominoes: [],\n players: [],\n lords: [],\n turn: 0,\n nextAction: {\n type: \"step\",\n step: gameSteps.addPlayers,\n },\n rules: {\n basic: {\n lords: 0,\n maxDominoes: 0,\n dominoesPerTurn: 0,\n maxTurns: 0,\n maxKingdomSize: 5,\n },\n extra: [],\n },\n mode,\n ...(seed !== undefined && { seed }),\n };\n};\n","import { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport { err, ok, type Result } from \"@utils/result.js\";\nimport type { GameMode } from \"@core/domain/types/mode.js\";\n\nconst findMode = (\n mode: string,\n availableMode: GameMode[]\n): GameMode | undefined => {\n return availableMode.find((m) => m.name === mode);\n};\n\nexport const createMode = (\n mode: string,\n availableMode: GameMode[]\n): Result<GameMode> => {\n const foundMode = findMode(mode, availableMode);\n if (foundMode) {\n return ok(foundMode);\n }\n\n return err(ErrorCode.MODE_NOT_FOUND);\n};\n","import { create } from \"@core/domain/entities/game.js\";\nimport { createMode } from \"@core/domain/entities/mode.js\";\nimport type { GameWithNextStep } from \"@core/domain/types/game.js\";\nimport type { DominoesRepository } from \"@core/portServerside/dominoesRepository.js\";\nimport type { ModeRepository } from \"@core/portServerside/modeRepository.js\";\nimport type { UuidMethod } from \"@core/portServerside/uuidMethod.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport { err, isErr, ok, type Result } from \"@utils/result.js\";\n\nexport type CreateGameUseCase = (\n mode: string,\n seed?: string\n) => Result<GameWithNextStep>;\n\nexport const createGameUseCase =\n (deps: {\n modeRepository: ModeRepository;\n dominoesRepository: DominoesRepository;\n uuidMethod: UuidMethod;\n }): CreateGameUseCase =>\n (mode, seed) => {\n const { modeRepository, dominoesRepository, uuidMethod } = deps;\n const id = uuidMethod();\n const gameSeed = seed ?? uuidMethod();\n const availableMode = modeRepository.getAvailables();\n const newMode = createMode(mode, availableMode);\n\n if (isErr(newMode)) {\n return newMode;\n }\n\n const dominoes = dominoesRepository.getForMode(newMode.value);\n\n if (!dominoes || dominoes.length === 0) {\n return err(ErrorCode.DOMINO_NOT_FOUND);\n }\n\n const payload = {\n id,\n mode: newMode.value,\n dominoes,\n seed: gameSeed,\n };\n\n const newGame = create(payload);\n\n return ok(newGame);\n };\n","import type { Kingdom, Position, Rotation, Domino } from \"@core/domain/types/index.js\";\nimport { GRIDSIZE, MAX_KINGDOM_SIZE } from \"@core/domain/types/kingdom.js\";\nimport { placeDomino } from \"@core/domain/entities/kingdom.js\";\nimport { isOk } from \"@utils/result.js\";\n\n/**\n * Represents a valid placement position with rotation.\n */\nexport type ValidPlacement = {\n position: Position;\n rotation: Rotation;\n};\n\nexport type GetValidPlacementsUseCase = (\n kingdom: Kingdom,\n domino: Domino,\n maxKingdomSize?: number\n) => ValidPlacement[];\n\n/**\n * Finds all valid placements for a domino on a kingdom grid.\n * Tests all positions and rotations to determine where the domino can be placed.\n *\n * @param kingdom - The current state of the kingdom grid\n * @param domino - The domino to place\n * @param maxKingdomSize - Maximum kingdom size (default: 5)\n * @returns Array of valid placements (position + rotation combinations)\n */\nexport const getValidPlacementsUseCase: GetValidPlacementsUseCase = (\n kingdom,\n domino,\n maxKingdomSize = MAX_KINGDOM_SIZE\n) => {\n const validPlacements: ValidPlacement[] = [];\n const rotations: Rotation[] = [0, 90, 180, 270];\n\n // Try each position on the grid\n for (let y = 0; y < GRIDSIZE; y++) {\n for (let x = 0; x < GRIDSIZE; x++) {\n const position: Position = { x, y };\n\n // Try each rotation\n for (const rotation of rotations) {\n const result = placeDomino(kingdom, position, rotation, domino, maxKingdomSize);\n if (isOk(result)) {\n validPlacements.push({ position, rotation });\n }\n }\n }\n }\n\n return validPlacements;\n};\n\n/**\n * Checks if a domino can be placed anywhere on the kingdom.\n *\n * @param kingdom - The current state of the kingdom grid\n * @param domino - The domino to check\n * @param maxKingdomSize - Maximum kingdom size (default: 5)\n * @returns True if at least one valid placement exists\n */\nexport const canPlaceDominoUseCase = (\n kingdom: Kingdom,\n domino: Domino,\n maxKingdomSize: number = MAX_KINGDOM_SIZE\n): boolean => {\n const rotations: Rotation[] = [0, 90, 180, 270];\n\n // Check each position on the grid\n for (let y = 0; y < GRIDSIZE; y++) {\n for (let x = 0; x < GRIDSIZE; x++) {\n const position: Position = { x, y };\n\n // Check each rotation - return early if any placement is valid\n for (const rotation of rotations) {\n const result = placeDomino(kingdom, position, rotation, domino, maxKingdomSize);\n if (isOk(result)) {\n return true;\n }\n }\n }\n }\n\n return false;\n};\n","import {\n allLordsHavePlayed,\n canPass,\n nextLordWithAction,\n} from \"@core/domain/entities/lord.js\";\nimport {\n gameSteps,\n type GameState,\n type GameStateResult,\n type GameWithNextAction,\n type NextAction,\n type NextStep,\n} from \"@core/domain/types/game.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport { canPlaceDominoUseCase } from \"./getValidPlacements.js\";\nimport { err, ok } from \"@utils/result.js\";\n\nexport type DiscardDominoUseCase = (\n game: GameWithNextAction,\n lordId: string\n) => GameStateResult;\n\nexport const discardDominoUseCase: DiscardDominoUseCase = (game, lordId) => {\n const nextAction = game.nextAction;\n\n const currentLord = game.lords.find(\n (lord) => lord.id === nextAction.nextLord\n );\n\n if (!currentLord) {\n return err(ErrorCode.LORD_NOT_FOUND);\n }\n\n if (currentLord.id !== lordId) {\n return err(ErrorCode.NOT_YOUR_TURN);\n }\n\n if (!canPass(currentLord)) {\n return err(ErrorCode.CANNOT_PLACE);\n }\n\n if (currentLord.dominoPicked) {\n const currentPlayer = game.players.find(\n (player) => player.id === currentLord.playerId\n );\n\n if (currentPlayer && canPlaceDominoUseCase(currentPlayer.kingdom, currentLord.dominoPicked, game.rules.basic.maxKingdomSize)) {\n return err(ErrorCode.CANNOT_PLACE);\n }\n }\n\n const maxTurns = game.rules.basic.maxTurns;\n const currentTurn = game.turn;\n const isLastTurn = currentTurn === maxTurns;\n\n const updatedLord = game.lords.map((lord) => {\n if (lord.id === currentLord.id) {\n if (isLastTurn) {\n return {\n ...lord,\n turnEnded: true,\n hasPlace: true,\n };\n }\n\n return {\n ...lord,\n hasPlace: true,\n };\n }\n return lord;\n });\n\n let updatedGame: GameState;\n\n const resultStep: NextStep = {\n type: \"step\",\n step: gameSteps.result,\n };\n\n if (isLastTurn && allLordsHavePlayed(updatedLord)) {\n updatedGame = {\n ...game,\n lords: updatedLord,\n nextAction: resultStep,\n };\n } else {\n updatedGame = {\n ...game,\n lords: updatedLord,\n nextAction: <NextAction>nextLordWithAction(updatedLord),\n };\n }\n\n return ok(updatedGame);\n};\n","import type { FinalResult, GameWithResults } from \"@core/domain/types/index.js\";\n\nexport type DynastyResult = {\n playerId: string;\n playerName: string;\n totalPoints: number;\n gamesPoints: number[];\n position: number;\n};\n\nexport type GetDynastyResultUseCase = (\n games: GameWithResults[]\n) => DynastyResult[];\n\nexport const getDynastyResultUseCase: GetDynastyResultUseCase = (games) => {\n // Collect all unique players\n const playerMap = new Map<string, { name: string; points: number[] }>();\n\n for (const game of games) {\n for (const result of game.result) {\n const existing = playerMap.get(result.playerId);\n if (existing) {\n existing.points.push(result.details.points);\n } else {\n playerMap.set(result.playerId, {\n name: result.playerName,\n points: [result.details.points],\n });\n }\n }\n }\n\n // Calculate totals and sort\n const results: Omit<DynastyResult, \"position\">[] = [];\n for (const [playerId, data] of playerMap) {\n results.push({\n playerId,\n playerName: data.name,\n totalPoints: data.points.reduce((sum, p) => sum + p, 0),\n gamesPoints: data.points,\n });\n }\n\n results.sort((a, b) => b.totalPoints - a.totalPoints);\n\n // Assign positions with tie detection\n const finalResults: DynastyResult[] = [];\n for (let i = 0; i < results.length; i++) {\n const current = results[i]!;\n const previous = i > 0 ? finalResults[i - 1]! : null;\n const position =\n previous && current.totalPoints === previous.totalPoints\n ? previous.position\n : i + 1;\n finalResults.push({ ...current, position });\n }\n\n return finalResults;\n};\n","import { getAvailablesExtraRules } from \"@core/domain/entities/rule.js\";\nimport type { GameMode } from \"@core/domain/types/mode.js\";\nimport type { ExtraRule } from \"@core/domain/types/rule.js\";\nimport type { RuleRepository } from \"@core/portServerside/ruleRepository.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport { err, type Result } from \"@utils/result.js\";\n\nexport type GetExtraRulesUseCase = (\n mode: GameMode[\"name\"],\n players: number\n) => Result<ExtraRule[]>;\n\nexport const getExtraRulesUseCase =\n (deps: { ruleRepository: RuleRepository }): GetExtraRulesUseCase =>\n (mode: GameMode[\"name\"], players: number): Result<ExtraRule[]> => {\n const { ruleRepository } = deps;\n\n const allExtraRules = ruleRepository.getAllExtra();\n\n if (!allExtraRules) {\n return err(ErrorCode.STEP_EXECUTION_FAILED);\n }\n\n return getAvailablesExtraRules(allExtraRules, mode, players);\n };\n","import type { GameMode } from \"@core/domain/types/mode.js\";\nimport type { ModeRepository } from \"@core/portServerside/modeRepository.js\";\nimport { ok, type Result } from \"@utils/result.js\";\n\nexport type GetModesUseCase = () => Result<GameMode[]>;\n\nexport const getModesUseCase =\n (deps: { modeRepository: ModeRepository }): GetModesUseCase =>\n (): Result<GameMode[]> => {\n const { modeRepository } = deps;\n return ok(modeRepository.getAvailables());\n };\n","import {\n checkCastleIsInMiddle,\n countDominoes,\n} from \"@core/domain/entities/kingdom.js\";\nimport type {\n FinalResult,\n GameWithNextStep,\n GameWithResults,\n ScoreResult,\n} from \"@core/domain/types/index.js\";\nimport { err, ok, type Result } from \"@utils/result.js\";\n\nexport type GetResultUseCase = (\n game: GameWithNextStep,\n scoreResult: ScoreResult[]\n) => Result<GameWithResults>;\n\nexport const getResultUseCase: GetResultUseCase = (game, scoreResult) => {\n const { rules } = game;\n const { basic, extra } = rules;\n\n const finalScoreResult = scoreResult.map((score): ScoreResult => {\n let finalScore = score.details.points;\n\n const player = game.players.find((p) => p.id === score.playerId);\n if (!player) {\n return score;\n }\n\n const { kingdom } = player;\n\n if (extra.length > 0) {\n extra.forEach((extraRule) => {\n if (extraRule.name === \"The middle Kingdom\") {\n const castleIsInMiddle = checkCastleIsInMiddle(kingdom);\n if (castleIsInMiddle) {\n finalScore += 10;\n }\n }\n\n if (extraRule.name === \"Harmony\") {\n const totalDominoes = countDominoes(kingdom);\n const dominoLimit = basic.maxDominoes;\n const totalPlayers = game.players.length;\n const dominoesPerPlayer = dominoLimit / totalPlayers;\n if (totalDominoes === dominoesPerPlayer) {\n finalScore += 5;\n }\n }\n });\n }\n\n return {\n ...score,\n details: {\n ...score.details,\n points: finalScore,\n },\n };\n });\n\n // Order players by score, then by maxPropertiesSize (per official rules, no further tiebreaker)\n finalScoreResult.sort((a, b) => {\n if (a.details.points !== b.details.points) {\n return b.details.points - a.details.points;\n }\n return b.details.maxPropertiesSize - a.details.maxPropertiesSize;\n });\n\n const result: FinalResult[] = [];\n\n let isTie = false;\n result.push({\n playerId: finalScoreResult[0]!.playerId,\n playerName: finalScoreResult[0]!.playerName,\n details: finalScoreResult[0]!.details,\n position: 1,\n });\n\n for (let i = 1; i < finalScoreResult.length; i++) {\n const currentScore = finalScoreResult[i];\n const previousScore = finalScoreResult[i - 1];\n if (\n previousScore &&\n currentScore &&\n currentScore.details.points === previousScore.details.points &&\n currentScore.details.maxPropertiesSize ===\n previousScore.details.maxPropertiesSize\n ) {\n isTie = true;\n }\n\n if (isTie) {\n result.push({\n ...currentScore!,\n position: result[i - 1]!.position,\n });\n } else {\n result.push({\n ...currentScore!,\n position: i + 1,\n });\n }\n\n isTie = false;\n }\n\n return ok({\n ...game,\n result: result,\n });\n};\n","import { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport { err, isErr, ok } from \"@utils/result.js\";\nimport {\n gameSteps,\n type GameState,\n type GameStateResult,\n type GameWithNextAction,\n type NextAction,\n type NextStep,\n} from \"@core/domain/types/game.js\";\nimport {\n allLordsHavePlayed,\n canPlaceAndDominoPickedIsDefined,\n nextLordWithAction,\n} from \"@core/domain/entities/lord.js\";\nimport { placeDomino } from \"@core/domain/entities/kingdom.js\";\nimport type {\n Position,\n Rotation,\n} from \"@core/domain/types/kingdom.js\";\n\nexport type PlaceDominoUseCase = (\n game: GameWithNextAction,\n lordId: string,\n position: Position,\n rotation: Rotation\n) => GameStateResult;\n\nexport const placeDominoUseCase: PlaceDominoUseCase = (\n game,\n lordId,\n position,\n rotation\n) => {\n const nextAction = game.nextAction;\n\n const currentLord = game.lords.find(\n (lord) => lord.id === nextAction.nextLord\n );\n\n if (!currentLord) {\n return err(ErrorCode.LORD_NOT_FOUND);\n }\n\n if (currentLord.id !== lordId) {\n return err(ErrorCode.NOT_YOUR_TURN);\n }\n\n if (!canPlaceAndDominoPickedIsDefined(currentLord)) {\n return err(ErrorCode.CANNOT_PLACE);\n }\n\n const domino = currentLord.dominoPicked;\n\n const currentPlayer = game.players.find(\n (player) => player.id === currentLord.playerId\n );\n\n if (!currentPlayer) {\n return err(ErrorCode.PLAYER_NOT_FOUND);\n }\n\n const updatedKingdom = placeDomino(\n currentPlayer.kingdom,\n position,\n rotation,\n domino,\n game.rules.basic.maxKingdomSize\n );\n\n if (isErr(updatedKingdom)) {\n return updatedKingdom;\n }\n\n const updatedPlayers = game.players.map((player) => {\n if (player.id === currentPlayer.id) {\n player.kingdom = updatedKingdom.value;\n }\n return player;\n });\n\n const maxTurns = game.rules.basic.maxTurns;\n const currentTurn = game.turn;\n const isLastTurn = currentTurn === maxTurns;\n\n const updatedLords = game.lords.map((lord) => {\n if (lord.id === currentLord.id) {\n if (isLastTurn) {\n return {\n ...lord,\n turnEnded: true,\n hasPlace: true,\n };\n }\n return {\n ...lord,\n hasPlace: true,\n };\n }\n return lord;\n });\n\n let updatedGame: GameState;\n\n const resultStep: NextStep = {\n type: \"step\",\n step: gameSteps.result,\n };\n\n if (isLastTurn && allLordsHavePlayed(updatedLords)) {\n updatedGame = {\n ...game,\n lords: updatedLords,\n nextAction: resultStep,\n players: updatedPlayers,\n };\n } else {\n updatedGame = {\n ...game,\n lords: updatedLords,\n nextAction: <NextAction>nextLordWithAction(updatedLords),\n players: updatedPlayers,\n };\n }\n\n return ok(updatedGame);\n};\n","import { createLord } from \"@core/domain/entities/lord\";\nimport type {\n GameWithNextAction,\n GameWithNextStep,\n NextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Lord } from \"@core/domain/types/lord.js\";\nimport { playerActions } from \"@core/domain/types/player.js\";\nimport type { ShuffleMethod } from \"@core/portServerside/shuffleMethod.js\";\nimport type { UuidMethod } from \"@core/portServerside/uuidMethod.js\";\nimport { ok, type Result } from \"@utils/result.js\";\nimport { createSeededShuffle } from \"@utils/seededShuffle.js\";\n\nexport type StartGameUseCase = (\n game: GameWithNextStep\n) => Result<GameWithNextAction>;\n\nexport const startGameUseCase =\n (deps: {\n uuidMethod: UuidMethod;\n shuffleMethod: ShuffleMethod;\n }): StartGameUseCase =>\n (game) => {\n const { uuidMethod, shuffleMethod } = deps;\n const {\n rules: {\n basic: { lords: maxLords, dominoesPerTurn },\n },\n players,\n dominoes,\n } = game;\n\n const numberOfPlayers = players.length;\n\n const newLords: Lord[] = [];\n\n for (let i = 0; i < numberOfPlayers; i++) {\n for (let j = 0; j < maxLords; j++) {\n const lord = createLord(uuidMethod(), players[i]!.id);\n newLords.push(lord);\n }\n }\n\n const shuffle = game.seed\n ? createSeededShuffle(game.seed, \"lords\")\n : shuffleMethod;\n const shuffledLords = shuffle(newLords);\n const dominoesCopy = [...dominoes];\n const dominoesDrawn = dominoesCopy.splice(0, dominoesPerTurn);\n dominoesDrawn.sort((a, b) => a.number - b.number);\n const nextAction: NextAction = {\n type: \"action\",\n nextLord: shuffledLords[0]!.id,\n nextAction: playerActions.pickDomino,\n };\n\n const newState: GameWithNextAction = {\n ...game,\n lords: shuffledLords,\n nextAction,\n dominoes: dominoesCopy,\n currentDominoes: dominoesDrawn.map((domino, index) => {\n return {\n domino,\n picked: false,\n lordId: null,\n position: index + 1,\n };\n }),\n };\n\n return ok(newState);\n };\n","import { consoleLogger, silentLogger } from \"@adapter/consoleLogger.js\";\nimport jsonDominoes from \"@adapter/jsonDominoes.js\";\nimport jsonModes from \"@adapter/jsonModes.js\";\nimport jsonRules from \"@adapter/jsonRules.js\";\nimport { shuffleMethod } from \"@adapter/shuffle.js\";\nimport { uuidMethod } from \"@adapter/uuid.js\";\nimport { addExtraRulesHandler } from \"@application/handlers/addExtraRulesHandler.js\";\nimport { addPlayersHandler } from \"@application/handlers/addPlayersHandler.js\";\nimport { calculateScoreHandler } from \"@application/handlers/calculateScoreHandler.js\";\nimport { canPlaceDominoHandler } from \"@application/handlers/canPlaceDominoHandler.js\";\nimport { chooseDominoHandler } from \"@application/handlers/chooseDominoHandler.js\";\nimport { createGameHandler } from \"@application/handlers/createGameHandler.js\";\nimport { discardDominoHandler } from \"@application/handlers/discardDominoHandler.js\";\nimport { getDynastyResultHandler } from \"@application/handlers/getDynastyResultHandler.js\";\nimport { getExtraRulesHandler } from \"@application/handlers/getExtraRulesHandler.js\";\nimport { getModesHandler } from \"@application/handlers/getModesHandler.js\";\nimport { getResultHandler } from \"@application/handlers/getResultHandler.js\";\nimport { getValidPlacementsHandler } from \"@application/handlers/getValidPlacementsHandler.js\";\nimport { placeDominoHandler } from \"@application/handlers/placeDominoHandler.js\";\nimport {\n deserializeGameHandler,\n serializeGameHandler,\n} from \"@application/handlers/serializeGameHandler.js\";\nimport { startGameHandler } from \"@application/handlers/startGameHandler.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport type { GameEngine } from \"@core/portUserside/engine.js\";\nimport { defaultTranslator } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { ShuffleMethod } from \"@core/portServerside/shuffleMethod.js\";\nimport type { UuidMethod } from \"@core/portServerside/uuidMethod.js\";\nimport { addExtraRulesUseCase } from \"@core/useCases/addExtraRules.js\";\nimport { addPlayersUseCase } from \"@core/useCases/addPlayers.js\";\nimport { calculateScoreUseCase } from \"@core/useCases/calculateScore.js\";\nimport { chooseDominoUseCase } from \"@core/useCases/chooseDomino.js\";\nimport { createGameUseCase } from \"@core/useCases/createGame.js\";\nimport { discardDominoUseCase } from \"@core/useCases/discardDomino.js\";\nimport type { DebugOptions } from \"@core/useCases/gameDebug.js\";\nimport type { GameEventCallbacks } from \"@core/useCases/gameEvents.js\";\nimport { getDynastyResultUseCase } from \"@core/useCases/getDynastyResult.js\";\nimport { getExtraRulesUseCase } from \"@core/useCases/getExtraRules.js\";\nimport { getModesUseCase } from \"@core/useCases/getModes.js\";\nimport { getResultUseCase } from \"@core/useCases/getResult.js\";\nimport {\n canPlaceDominoUseCase,\n getValidPlacementsUseCase,\n} from \"@core/useCases/getValidPlacements.js\";\nimport { placeDominoUseCase } from \"@core/useCases/placeDomino.js\";\nimport { startGameUseCase } from \"@core/useCases/startGame.js\";\n\n/**\n * Configuration options for the game engine.\n */\nexport type EngineConfig = {\n /** Custom UUID generation method. Defaults to crypto.randomUUID() */\n uuidMethod?: UuidMethod;\n /** Custom shuffle method. Defaults to Fisher-Yates algorithm */\n shuffleMethod?: ShuffleMethod;\n /** Enable console logging. Defaults to false */\n logging?: boolean;\n /** Custom logger instance. When provided, takes precedence over 'logging' option */\n logger?: Logger;\n /** Optional event callbacks for UI/animation integration */\n events?: GameEventCallbacks;\n /** Custom translator for i18n error messages. Defaults to English */\n translator?: Translator;\n /** Enable debug mode with detailed logging. Pass `true` for defaults or a `DebugOptions` object. */\n debug?: boolean | DebugOptions;\n};\n\nexport type ConfiguredHandlers = {\n createGameHandler: GameEngine[\"createGame\"];\n getModesHandler: GameEngine[\"getModes\"];\n getExtraRulesHandler: GameEngine[\"getExtraRules\"];\n addPlayersHandler: GameEngine[\"addPlayers\"];\n addExtraRulesHandler: GameEngine[\"addExtraRules\"];\n startGameHandler: GameEngine[\"startGame\"];\n chooseDominoHandler: GameEngine[\"chooseDomino\"];\n placeDominoHandler: GameEngine[\"placeDomino\"];\n discardDominoHandler: GameEngine[\"discardDomino\"];\n getResultHandler: GameEngine[\"getResults\"];\n calculateScoreHandler: GameEngine[\"calculateScore\"];\n getValidPlacementsHandler: GameEngine[\"getValidPlacements\"];\n canPlaceDominoHandler: GameEngine[\"canPlaceDomino\"];\n serializeGameHandler: GameEngine[\"serialize\"];\n deserializeGameHandler: GameEngine[\"deserialize\"];\n getDynastyResultHandler: GameEngine[\"getDynastyResults\"];\n};\n\nexport const configureEngine = (config: Partial<EngineConfig>): ConfiguredHandlers => {\n const modeRepository = jsonModes();\n const dominoesRepository = jsonDominoes();\n const ruleRepository = jsonRules();\n const uuid = config.uuidMethod || uuidMethod;\n const shuffle = config.shuffleMethod || shuffleMethod;\n const translator = config.translator || defaultTranslator;\n\n // Logger priority: custom logger > logging flag > silent\n const logger = config.logger\n ? config.logger\n : config.logging\n ? consoleLogger(true)\n : silentLogger;\n\n return {\n createGameHandler: createGameHandler(\n logger,\n translator,\n createGameUseCase({\n modeRepository,\n dominoesRepository,\n uuidMethod: uuid,\n }),\n ),\n getModesHandler: getModesHandler(\n logger,\n translator,\n getModesUseCase({ modeRepository }),\n ),\n getExtraRulesHandler: getExtraRulesHandler(\n logger,\n translator,\n getExtraRulesUseCase({ ruleRepository }),\n ),\n addPlayersHandler: addPlayersHandler(\n logger,\n translator,\n addPlayersUseCase({\n uuidMethod: uuid,\n shuffleMethod: shuffle,\n ruleRepository,\n }),\n ),\n addExtraRulesHandler: addExtraRulesHandler(\n logger,\n translator,\n addExtraRulesUseCase({\n ruleRepository,\n dominoesRepository,\n shuffleMethod: shuffle,\n }),\n ),\n startGameHandler: startGameHandler(\n logger,\n translator,\n startGameUseCase({ uuidMethod: uuid, shuffleMethod: shuffle }),\n ),\n chooseDominoHandler: chooseDominoHandler(\n logger,\n translator,\n chooseDominoUseCase,\n ),\n placeDominoHandler: placeDominoHandler(\n logger,\n translator,\n placeDominoUseCase,\n ),\n discardDominoHandler: discardDominoHandler(\n logger,\n translator,\n discardDominoUseCase,\n ),\n getResultHandler: getResultHandler(logger, translator, {\n getResultUseCase,\n calculateScoreUseCase,\n }),\n calculateScoreHandler: calculateScoreHandler(\n logger,\n translator,\n calculateScoreUseCase,\n ),\n getValidPlacementsHandler: getValidPlacementsHandler(\n logger,\n translator,\n getValidPlacementsUseCase,\n ),\n canPlaceDominoHandler: canPlaceDominoHandler(\n logger,\n translator,\n canPlaceDominoUseCase,\n ),\n serializeGameHandler: serializeGameHandler(logger, translator),\n deserializeGameHandler: deserializeGameHandler(logger, translator),\n getDynastyResultHandler: getDynastyResultHandler(\n logger,\n translator,\n getDynastyResultUseCase,\n ),\n };\n};\n","import { GROUND } from \"@core/domain/types/domino.js\";\nimport type { Game } from \"@core/domain/types/game.js\";\nimport { gameSteps } from \"@core/domain/types/game.js\";\nimport { GRIDSIZE } from \"@core/domain/types/kingdom.js\";\nimport { playerActions } from \"@core/domain/types/player.js\";\nimport type { ValidationIssue, ValidationSeverity } from \"@core/domain/types/validation.js\";\n\nconst issue = (\n path: string,\n code: string,\n message: string,\n severity: ValidationSeverity = \"error\",\n): ValidationIssue => ({ path, code, message, severity });\n\nconst isNonEmptyString = (value: unknown): value is string =>\n typeof value === \"string\" && value.length > 0;\n\nconst isNonNegativeInteger = (value: unknown): value is number =>\n typeof value === \"number\" && Number.isInteger(value) && value >= 0;\n\nconst isPositiveInteger = (value: unknown): value is number =>\n typeof value === \"number\" && Number.isInteger(value) && value > 0;\n\nconst validGrounds = new Set<string>([...GROUND, \"empty\"]);\nconst validPlayerActions = new Set<string>(Object.values(playerActions));\nconst validGameSteps = new Set<string>(Object.values(gameSteps));\n\n// --- Validation sub-functions ---\n\nconst validateGameStructure = (game: Game): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n\n if (!isNonEmptyString(game.id)) {\n issues.push(issue(\"id\", \"INVALID_ID\", \"Game id must be a non-empty string\"));\n }\n if (!isNonNegativeInteger(game.turn)) {\n issues.push(issue(\"turn\", \"INVALID_TURN\", \"Turn must be a non-negative integer\"));\n }\n if (!Array.isArray(game.dominoes)) {\n issues.push(issue(\"dominoes\", \"INVALID_DOMINOES\", \"Dominoes must be an array\"));\n }\n if (!Array.isArray(game.currentDominoes)) {\n issues.push(issue(\"currentDominoes\", \"INVALID_CURRENT_DOMINOES\", \"CurrentDominoes must be an array\"));\n }\n if (!Array.isArray(game.players)) {\n issues.push(issue(\"players\", \"INVALID_PLAYERS\", \"Players must be an array\"));\n }\n if (!Array.isArray(game.lords)) {\n issues.push(issue(\"lords\", \"INVALID_LORDS\", \"Lords must be an array\"));\n }\n if (!game.rules || typeof game.rules !== \"object\") {\n issues.push(issue(\"rules\", \"INVALID_RULES\", \"Rules must be an object\"));\n } else {\n if (!game.rules.basic || typeof game.rules.basic !== \"object\") {\n issues.push(issue(\"rules.basic\", \"INVALID_BASIC_RULES\", \"Rules.basic must be an object\"));\n }\n if (!Array.isArray(game.rules.extra)) {\n issues.push(issue(\"rules.extra\", \"INVALID_EXTRA_RULES\", \"Rules.extra must be an array\"));\n }\n }\n if (!game.mode || typeof game.mode !== \"object\") {\n issues.push(issue(\"mode\", \"INVALID_MODE\", \"Mode must be an object\"));\n } else {\n if (!isNonEmptyString(game.mode.name)) {\n issues.push(issue(\"mode.name\", \"INVALID_MODE_NAME\", \"Mode name must be a non-empty string\"));\n }\n }\n if (!game.nextAction || typeof game.nextAction !== \"object\") {\n issues.push(issue(\"nextAction\", \"INVALID_NEXT_ACTION\", \"NextAction must be an object\"));\n } else if (game.nextAction.type !== \"action\" && game.nextAction.type !== \"step\") {\n issues.push(issue(\"nextAction.type\", \"INVALID_NEXT_ACTION_TYPE\", \"NextAction.type must be 'action' or 'step'\"));\n }\n\n return issues;\n};\n\nconst validateTile = (tile: unknown, path: string): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n if (!tile || typeof tile !== \"object\") {\n issues.push(issue(path, \"INVALID_TILE\", `Tile at ${path} must be an object`));\n return issues;\n }\n const t = tile as Record<string, unknown>;\n if (typeof t.type !== \"string\" || !validGrounds.has(t.type)) {\n issues.push(issue(`${path}.type`, \"INVALID_TILE_TYPE\", `Invalid terrain type at ${path}`));\n }\n if (typeof t.crowns !== \"number\" || t.crowns < 0) {\n issues.push(issue(`${path}.crowns`, \"INVALID_TILE_CROWNS\", `Invalid crowns at ${path}`));\n }\n return issues;\n};\n\nconst validatePlayers = (game: Game): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n if (!Array.isArray(game.players)) return issues;\n\n const playerIds = new Set<string>();\n for (let i = 0; i < game.players.length; i++) {\n const player = game.players[i]!;\n const path = `players[${i}]`;\n\n if (!isNonEmptyString(player.id)) {\n issues.push(issue(`${path}.id`, \"INVALID_PLAYER_ID\", `Player id must be a non-empty string`));\n } else if (playerIds.has(player.id)) {\n issues.push(issue(`${path}.id`, \"DUPLICATE_PLAYER_ID\", `Duplicate player id: ${player.id}`));\n } else {\n playerIds.add(player.id);\n }\n\n if (typeof player.name !== \"string\" || player.name.length < 3) {\n issues.push(issue(`${path}.name`, \"INVALID_PLAYER_NAME\", `Player name must be at least 3 characters`));\n }\n\n // Kingdom validation\n if (!Array.isArray(player.kingdom)) {\n issues.push(issue(`${path}.kingdom`, \"INVALID_KINGDOM\", `Kingdom must be a 2D array`));\n continue;\n }\n if (player.kingdom.length !== GRIDSIZE) {\n issues.push(issue(`${path}.kingdom`, \"INVALID_KINGDOM_GRID\", `Kingdom must have ${GRIDSIZE} rows, got ${player.kingdom.length}`));\n continue;\n }\n\n let castleCount = 0;\n for (let y = 0; y < player.kingdom.length; y++) {\n const row = player.kingdom[y]!;\n if (!Array.isArray(row) || row.length !== GRIDSIZE) {\n issues.push(issue(`${path}.kingdom[${y}]`, \"INVALID_KINGDOM_ROW\", `Kingdom row ${y} must have ${GRIDSIZE} columns`));\n continue;\n }\n for (let x = 0; x < row.length; x++) {\n const cell = row[x]!;\n issues.push(...validateTile(cell, `${path}.kingdom[${y}][${x}]`));\n if (cell && typeof cell === \"object\" && (cell as Record<string, unknown>).type === \"castle\") {\n castleCount++;\n }\n }\n }\n if (castleCount === 0) {\n issues.push(issue(`${path}.kingdom`, \"MISSING_CASTLE\", `Kingdom must have exactly one castle tile`, \"warning\"));\n } else if (castleCount > 1) {\n issues.push(issue(`${path}.kingdom`, \"MULTIPLE_CASTLES\", `Kingdom has ${castleCount} castle tiles, expected 1`));\n }\n }\n\n return issues;\n};\n\nconst validateDominoes = (game: Game): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n const allNumbers = new Set<number>();\n\n // Validate draw pile dominoes\n if (Array.isArray(game.dominoes)) {\n for (let i = 0; i < game.dominoes.length; i++) {\n const domino = game.dominoes[i]!;\n const path = `dominoes[${i}]`;\n\n if (!isPositiveInteger(domino.number)) {\n issues.push(issue(`${path}.number`, \"INVALID_DOMINO_NUMBER\", `Domino number must be a positive integer`));\n } else if (allNumbers.has(domino.number)) {\n issues.push(issue(`${path}.number`, \"DUPLICATE_DOMINO_NUMBER\", `Duplicate domino number: ${domino.number}`));\n } else {\n allNumbers.add(domino.number);\n }\n issues.push(...validateTile(domino.left, `${path}.left`));\n issues.push(...validateTile(domino.right, `${path}.right`));\n }\n }\n\n // Validate current (revealed) dominoes\n if (Array.isArray(game.currentDominoes)) {\n for (let i = 0; i < game.currentDominoes.length; i++) {\n const revealed = game.currentDominoes[i]!;\n const path = `currentDominoes[${i}]`;\n\n if (!revealed.domino || typeof revealed.domino !== \"object\") {\n issues.push(issue(`${path}.domino`, \"INVALID_REVEALED_DOMINO\", `Revealed domino must be an object`));\n continue;\n }\n\n const domino = revealed.domino;\n if (!isPositiveInteger(domino.number)) {\n issues.push(issue(`${path}.domino.number`, \"INVALID_DOMINO_NUMBER\", `Domino number must be a positive integer`));\n } else if (allNumbers.has(domino.number)) {\n issues.push(issue(`${path}.domino.number`, \"DUPLICATE_DOMINO_NUMBER\", `Duplicate domino number: ${domino.number}`));\n } else {\n allNumbers.add(domino.number);\n }\n issues.push(...validateTile(domino.left, `${path}.domino.left`));\n issues.push(...validateTile(domino.right, `${path}.domino.right`));\n\n // picked/lordId consistency\n if (revealed.picked && revealed.lordId === null) {\n issues.push(issue(`${path}`, \"PICKED_WITHOUT_LORD\", `Domino is marked as picked but has no lordId`));\n }\n if (!revealed.picked && revealed.lordId !== null) {\n issues.push(issue(`${path}`, \"UNPICKED_WITH_LORD\", `Domino is not picked but has a lordId`));\n }\n }\n }\n\n // Validate dominos picked by lords\n // Note: lord.dominoPicked is a copy of the domino from currentDominoes,\n // so the same number legitimately appears in both places.\n if (Array.isArray(game.lords)) {\n const lordPickedNumbers = new Set<number>();\n for (let i = 0; i < game.lords.length; i++) {\n const lord = game.lords[i]!;\n if (lord.dominoPicked) {\n const path = `lords[${i}].dominoPicked`;\n const domino = lord.dominoPicked;\n if (!isPositiveInteger(domino.number)) {\n issues.push(issue(`${path}.number`, \"INVALID_DOMINO_NUMBER\", `Domino number must be a positive integer`));\n } else if (lordPickedNumbers.has(domino.number)) {\n issues.push(issue(`${path}.number`, \"DUPLICATE_DOMINO_NUMBER\", `Duplicate domino number among lords: ${domino.number}`));\n } else {\n lordPickedNumbers.add(domino.number);\n }\n issues.push(...validateTile(domino.left, `${path}.left`));\n issues.push(...validateTile(domino.right, `${path}.right`));\n }\n }\n }\n\n return issues;\n};\n\nconst validateLords = (game: Game): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n if (!Array.isArray(game.lords)) return issues;\n\n const playerIds = new Set<string>(\n Array.isArray(game.players) ? game.players.map((p) => p.id) : [],\n );\n const lordIds = new Set<string>();\n\n for (let i = 0; i < game.lords.length; i++) {\n const lord = game.lords[i]!;\n const path = `lords[${i}]`;\n\n if (!isNonEmptyString(lord.id)) {\n issues.push(issue(`${path}.id`, \"INVALID_LORD_ID\", `Lord id must be a non-empty string`));\n } else if (lordIds.has(lord.id)) {\n issues.push(issue(`${path}.id`, \"DUPLICATE_LORD_ID\", `Duplicate lord id: ${lord.id}`));\n } else {\n lordIds.add(lord.id);\n }\n\n if (!isNonEmptyString(lord.playerId)) {\n issues.push(issue(`${path}.playerId`, \"INVALID_LORD_PLAYER_ID\", `Lord playerId must be a non-empty string`));\n } else if (playerIds.size > 0 && !playerIds.has(lord.playerId)) {\n issues.push(issue(`${path}.playerId`, \"LORD_PLAYER_NOT_FOUND\", `Lord references non-existent player: ${lord.playerId}`));\n }\n\n if (lord.turnEnded && (!lord.hasPick || !lord.hasPlace)) {\n issues.push(issue(path, \"INCONSISTENT_LORD_FLAGS\", `Lord has turnEnded=true but hasPick=${lord.hasPick}, hasPlace=${lord.hasPlace}`, \"warning\"));\n }\n }\n\n return issues;\n};\n\nconst validateGameFlow = (game: Game): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n if (!game.nextAction || typeof game.nextAction !== \"object\") return issues;\n\n const nextAction = game.nextAction;\n\n if (nextAction.type === \"action\") {\n const action = nextAction as { type: \"action\"; nextLord?: unknown; nextAction?: unknown };\n\n if (!isNonEmptyString(action.nextLord)) {\n issues.push(issue(\"nextAction.nextLord\", \"INVALID_NEXT_LORD\", \"nextLord must be a non-empty string\"));\n } else if (Array.isArray(game.lords) && !game.lords.some((l) => l.id === action.nextLord)) {\n issues.push(issue(\"nextAction.nextLord\", \"NEXT_LORD_NOT_FOUND\", `nextLord references non-existent lord: ${action.nextLord as string}`));\n }\n\n if (typeof action.nextAction !== \"string\" || !validPlayerActions.has(action.nextAction as string)) {\n issues.push(issue(\"nextAction.nextAction\", \"INVALID_PLAYER_ACTION\", `nextAction must be one of: ${[...validPlayerActions].join(\", \")}`));\n }\n } else if (nextAction.type === \"step\") {\n const step = nextAction as { type: \"step\"; step?: unknown };\n\n if (typeof step.step !== \"string\" || !validGameSteps.has(step.step as string)) {\n issues.push(issue(\"nextAction.step\", \"INVALID_GAME_STEP\", `step must be one of: ${[...validGameSteps].join(\", \")}`));\n }\n }\n\n return issues;\n};\n\nconst isSetupPhase = (game: Game): boolean => {\n if (game.nextAction?.type !== \"step\") return false;\n const step = (game.nextAction as { step: string }).step;\n return step === \"addPlayers\" || step === \"options\" || step === \"start\";\n};\n\nconst validateRules = (game: Game): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n if (!game.rules || typeof game.rules !== \"object\") return issues;\n\n // During setup phases (before players are added), basic rules may have zero values\n const allowZero = isSetupPhase(game);\n\n const basic = game.rules.basic;\n if (basic && typeof basic === \"object\") {\n const fields = [\"lords\", \"maxDominoes\", \"dominoesPerTurn\", \"maxTurns\", \"maxKingdomSize\"] as const;\n for (const field of fields) {\n const check = allowZero ? isNonNegativeInteger : isPositiveInteger;\n if (!check(basic[field])) {\n issues.push(issue(`rules.basic.${field}`, \"INVALID_BASIC_RULE_VALUE\", `rules.basic.${field} must be a positive integer`));\n }\n }\n }\n\n if (Array.isArray(game.rules.extra)) {\n for (let i = 0; i < game.rules.extra.length; i++) {\n const rule = game.rules.extra[i]!;\n if (!isNonEmptyString(rule.name)) {\n issues.push(issue(`rules.extra[${i}].name`, \"INVALID_EXTRA_RULE_NAME\", `Extra rule name must be a non-empty string`));\n }\n }\n }\n\n return issues;\n};\n\n/**\n * Validates the integrity of a game state.\n *\n * Use this function after deserializing or restoring a persisted game state\n * to detect corruptions before resuming gameplay.\n *\n * @param game - The game state to validate\n * @returns An array of validation issues. Empty array means the state is valid.\n *\n * @example\n * ```typescript\n * const issues = validateGameState(game);\n * if (issues.length > 0) {\n * console.error(\"Game state is corrupted:\", issues);\n * }\n * ```\n */\nexport const validateGameState = (game: Game): ValidationIssue[] => {\n const issues: ValidationIssue[] = [];\n\n issues.push(...validateGameStructure(game));\n issues.push(...validatePlayers(game));\n issues.push(...validateDominoes(game));\n issues.push(...validateLords(game));\n issues.push(...validateGameFlow(game));\n issues.push(...validateRules(game));\n\n return issues;\n};\n","import type { BotStrategy } from \"./bot.js\";\nimport {\n randomStrategy,\n greedyStrategy,\n advancedStrategy,\n expertStrategy,\n} from \"./bot.js\";\n\n/**\n * Built-in strategy names.\n */\nexport type StrategyName = \"random\" | \"greedy\" | \"advanced\" | \"expert\";\n\nconst defaultStrategies: Record<string, BotStrategy> = {\n random: randomStrategy,\n greedy: greedyStrategy,\n advanced: advancedStrategy,\n expert: expertStrategy,\n};\n\n/**\n * Resolves a strategy by name. Checks custom strategies first, then defaults.\n * Returns undefined if the name is not found.\n */\nexport const getStrategy = (\n name: string,\n custom?: Record<string, BotStrategy>\n): BotStrategy | undefined => {\n return custom?.[name] ?? defaultStrategies[name];\n};\n\n/**\n * Returns the list of built-in strategy names.\n */\nexport const getStrategyNames = (): string[] => Object.keys(defaultStrategies);\n","import type {\n Domino,\n RevealsDomino,\n Kingdom,\n GameWithNextAction,\n GameState,\n Score,\n} from \"@core/domain/types/index.js\";\nimport { isGameWithNextAction } from \"@core/domain/types/game.js\";\nimport type { ValidPlacement } from \"./getValidPlacements.js\";\nimport type { GameEngine } from \"@core/portUserside/engine.js\";\nimport { placeDomino } from \"@core/domain/entities/kingdom.js\";\nimport { calculateScoreUseCase } from \"./calculateScore.js\";\nimport { getValidPlacementsUseCase } from \"./getValidPlacements.js\";\nimport { isOk } from \"@utils/result.js\";\nimport { getStrategy } from \"./botRegistry.js\";\n\n// ─── Types ───────────────────────────────────────────────────────────\n\n/**\n * Context provided to a bot strategy when choosing a domino to pick.\n */\nexport type PickContext = {\n game: GameWithNextAction;\n lordId: string;\n availableDominoes: RevealsDomino[];\n};\n\n/**\n * Context provided to a bot strategy when choosing where to place a domino.\n */\nexport type PlaceContext = {\n game: GameWithNextAction;\n lordId: string;\n domino: Domino;\n kingdom: Kingdom;\n validPlacements: ValidPlacement[];\n};\n\n/**\n * A bot strategy that decides which domino to pick and where to place it.\n * Strategies are stateless — all information comes from the context.\n */\nexport type BotStrategy = {\n chooseDomino: (context: PickContext) => number;\n choosePlacement: (context: PlaceContext) => ValidPlacement | null;\n};\n\n// ─── Helpers ─────────────────────────────────────────────────────────\n\nconst scoreKingdom = (kingdom: Kingdom): number => {\n const result = calculateScoreUseCase(kingdom);\n return isOk(result) ? result.value.points : 0;\n};\n\nconst simulatePlacement = (\n kingdom: Kingdom,\n domino: Domino,\n placement: ValidPlacement,\n maxKingdomSize: number\n): Kingdom | null => {\n const result = placeDomino(\n kingdom,\n placement.position,\n placement.rotation,\n domino,\n maxKingdomSize\n );\n return isOk(result) ? result.value : null;\n};\n\nconst bestPlacementScore = (\n kingdom: Kingdom,\n domino: Domino,\n placements: ValidPlacement[],\n maxKingdomSize: number\n): { placement: ValidPlacement; score: number; kingdom: Kingdom } | null => {\n let best: { placement: ValidPlacement; score: number; kingdom: Kingdom } | null = null;\n\n for (const placement of placements) {\n const newKingdom = simulatePlacement(kingdom, domino, placement, maxKingdomSize);\n if (!newKingdom) continue;\n const score = scoreKingdom(newKingdom);\n if (!best || score > best.score) {\n best = { placement, score, kingdom: newKingdom };\n }\n }\n\n return best;\n};\n\nconst getMaxKingdomSize = (game: GameWithNextAction): number =>\n game.rules.basic.maxKingdomSize;\n\nconst getLordAndPlayer = (game: GameWithNextAction, lordId: string) => {\n const lord = game.lords.find((l) => l.id === lordId);\n const player = lord\n ? game.players.find((p) => p.id === lord.playerId)\n : undefined;\n return { lord, player };\n};\n\nconst getNextBatchDominoes = (game: GameWithNextAction): Domino[] => {\n const perTurn = game.rules.basic.dominoesPerTurn;\n return [...game.dominoes]\n .slice(0, perTurn)\n .sort((a, b) => a.number - b.number);\n};\n\n// ─── Random Strategy ─────────────────────────────────────────────────\n\n/**\n * Bot strategy that makes random choices.\n * Picks a random available domino and places it at a random valid position.\n */\nexport const randomStrategy: BotStrategy = {\n chooseDomino: (context) => {\n const { availableDominoes } = context;\n const idx = Math.floor(Math.random() * availableDominoes.length);\n return availableDominoes[idx]!.domino.number;\n },\n\n choosePlacement: (context) => {\n const { validPlacements } = context;\n if (validPlacements.length === 0) return null;\n const idx = Math.floor(Math.random() * validPlacements.length);\n return validPlacements[idx]!;\n },\n};\n\n// ─── Greedy Strategy ─────────────────────────────────────────────────\n\n/**\n * Bot strategy that maximizes the immediate score.\n * Evaluates every valid placement and picks the one yielding the highest score.\n * When picking a domino, simulates the best placement for each option.\n */\nexport const greedyStrategy: BotStrategy = {\n chooseDomino: (context) => {\n const { game, lordId, availableDominoes } = context;\n const { player } = getLordAndPlayer(game, lordId);\n if (!player) return availableDominoes[0]!.domino.number;\n\n const maxSize = getMaxKingdomSize(game);\n let bestScore = -1;\n let bestPick = availableDominoes[0]!.domino.number;\n\n for (const rd of availableDominoes) {\n const placements = getValidPlacementsUseCase(\n player.kingdom,\n rd.domino,\n maxSize\n );\n const result = bestPlacementScore(\n player.kingdom,\n rd.domino,\n placements,\n maxSize\n );\n const score = result ? result.score : 0;\n if (score > bestScore) {\n bestScore = score;\n bestPick = rd.domino.number;\n }\n }\n\n return bestPick;\n },\n\n choosePlacement: (context) => {\n const { game, domino, kingdom, validPlacements } = context;\n if (validPlacements.length === 0) return null;\n\n const maxSize = getMaxKingdomSize(game);\n const result = bestPlacementScore(kingdom, domino, validPlacements, maxSize);\n return result ? result.placement : validPlacements[0]!;\n },\n};\n\n// ─── Advanced Strategy ───────────────────────────────────────────────\n\nconst evaluateWithLookahead = (\n kingdom: Kingdom,\n maxSize: number,\n nextDominoes: Domino[]\n): number => {\n if (nextDominoes.length === 0) return 0;\n\n let bestNextScore = 0;\n for (const nextDomino of nextDominoes) {\n const nextPlacements = getValidPlacementsUseCase(kingdom, nextDomino, maxSize);\n const result = bestPlacementScore(kingdom, nextDomino, nextPlacements, maxSize);\n if (result && result.score > bestNextScore) {\n bestNextScore = result.score;\n }\n }\n\n return bestNextScore;\n};\n\n/**\n * Bot strategy with 1-turn lookahead.\n * When making decisions, considers not just the immediate score but also\n * the best possible score achievable in the next turn by peeking at\n * the upcoming domino batch from the draw pile.\n */\nexport const advancedStrategy: BotStrategy = {\n chooseDomino: (context) => {\n const { game, lordId, availableDominoes } = context;\n const { player } = getLordAndPlayer(game, lordId);\n if (!player) return availableDominoes[0]!.domino.number;\n\n const maxSize = getMaxKingdomSize(game);\n const nextBatch = getNextBatchDominoes(game);\n\n let bestCombinedScore = -1;\n let bestPick = availableDominoes[0]!.domino.number;\n\n for (const rd of availableDominoes) {\n const placements = getValidPlacementsUseCase(\n player.kingdom,\n rd.domino,\n maxSize\n );\n const result = bestPlacementScore(\n player.kingdom,\n rd.domino,\n placements,\n maxSize\n );\n\n const immediateScore = result ? result.score : scoreKingdom(player.kingdom);\n const kingdomAfter = result ? result.kingdom : player.kingdom;\n const futureScore = evaluateWithLookahead(kingdomAfter, maxSize, nextBatch);\n const combined = immediateScore + futureScore * 0.8;\n\n if (combined > bestCombinedScore) {\n bestCombinedScore = combined;\n bestPick = rd.domino.number;\n }\n }\n\n return bestPick;\n },\n\n choosePlacement: (context) => {\n const { game, domino, kingdom, validPlacements } = context;\n if (validPlacements.length === 0) return null;\n\n const maxSize = getMaxKingdomSize(game);\n const nextBatch = getNextBatchDominoes(game);\n\n let bestCombinedScore = -1;\n let bestPlacement: ValidPlacement = validPlacements[0]!;\n\n for (const placement of validPlacements) {\n const newKingdom = simulatePlacement(kingdom, domino, placement, maxSize);\n if (!newKingdom) continue;\n\n const immediateScore = scoreKingdom(newKingdom);\n const futureScore = evaluateWithLookahead(newKingdom, maxSize, nextBatch);\n const combined = immediateScore + futureScore * 0.8;\n\n if (combined > bestCombinedScore) {\n bestCombinedScore = combined;\n bestPlacement = placement;\n }\n }\n\n return bestPlacement;\n },\n};\n\n// ─── Expert Strategy ─────────────────────────────────────────────────\n\n/** Maximum placements to evaluate per domino at each depth level (beam width) */\nconst EXPERT_BEAM_WIDTH = 2;\n\n/** Maximum search depth for the expert strategy */\nconst EXPERT_MAX_DEPTH = 2;\n\n/**\n * Ranks placements by immediate score gain (greedy heuristic)\n * and returns only the top N candidates for deeper evaluation.\n */\nconst topPlacements = (\n kingdom: Kingdom,\n domino: Domino,\n placements: ValidPlacement[],\n maxSize: number,\n limit: number\n): ValidPlacement[] => {\n if (placements.length <= limit) return placements;\n\n const scored = placements\n .map((p) => {\n const k = simulatePlacement(kingdom, domino, p, maxSize);\n return { placement: p, score: k ? scoreKingdom(k) : 0 };\n })\n .sort((a, b) => b.score - a.score);\n\n return scored.slice(0, limit).map((s) => s.placement);\n};\n\nconst expertEvaluate = (\n kingdom: Kingdom,\n remainingDominoes: Domino[],\n dominoesPerTurn: number,\n maxSize: number,\n depth: number\n): number => {\n if (depth <= 0 || remainingDominoes.length === 0) {\n return scoreKingdom(kingdom);\n }\n\n // Get next batch (sorted by number, as the engine does)\n const batch = [...remainingDominoes]\n .slice(0, dominoesPerTurn)\n .sort((a, b) => a.number - b.number);\n const afterBatch = remainingDominoes.slice(dominoesPerTurn);\n\n let bestScore = scoreKingdom(kingdom);\n\n for (const domino of batch) {\n const allPlacements = getValidPlacementsUseCase(kingdom, domino, maxSize);\n\n if (allPlacements.length === 0) {\n const score = expertEvaluate(\n kingdom,\n afterBatch,\n dominoesPerTurn,\n maxSize,\n depth - 1\n );\n if (score > bestScore) bestScore = score;\n continue;\n }\n\n // Prune: only evaluate top candidates by greedy score\n const candidates = topPlacements(\n kingdom,\n domino,\n allPlacements,\n maxSize,\n EXPERT_BEAM_WIDTH\n );\n\n for (const placement of candidates) {\n const newKingdom = simulatePlacement(kingdom, domino, placement, maxSize);\n if (!newKingdom) continue;\n\n const score = expertEvaluate(\n newKingdom,\n afterBatch,\n dominoesPerTurn,\n maxSize,\n depth - 1\n );\n if (score > bestScore) bestScore = score;\n }\n }\n\n return bestScore;\n};\n\n/**\n * Bot strategy that searches the game tree with beam-search pruning.\n * Explores all remaining turns, but limits the number of placements\n * evaluated per domino to the top candidates (by greedy score).\n * Since kingdoms are independent, this is a solo optimization (no adversarial search needed).\n */\nexport const expertStrategy: BotStrategy = {\n chooseDomino: (context) => {\n const { game, lordId, availableDominoes } = context;\n const { player } = getLordAndPlayer(game, lordId);\n if (!player) return availableDominoes[0]!.domino.number;\n\n const maxSize = getMaxKingdomSize(game);\n const perTurn = game.rules.basic.dominoesPerTurn;\n const turnsLeft = Math.min(\n game.rules.basic.maxTurns - game.turn,\n EXPERT_MAX_DEPTH\n );\n\n let bestScore = -1;\n let bestPick = availableDominoes[0]!.domino.number;\n\n for (const rd of availableDominoes) {\n const allPlacements = getValidPlacementsUseCase(\n player.kingdom,\n rd.domino,\n maxSize\n );\n\n if (allPlacements.length === 0) {\n const score = expertEvaluate(\n player.kingdom,\n game.dominoes,\n perTurn,\n maxSize,\n turnsLeft\n );\n if (score > bestScore) {\n bestScore = score;\n bestPick = rd.domino.number;\n }\n continue;\n }\n\n const candidates = topPlacements(\n player.kingdom,\n rd.domino,\n allPlacements,\n maxSize,\n EXPERT_BEAM_WIDTH\n );\n\n for (const placement of candidates) {\n const newKingdom = simulatePlacement(\n player.kingdom,\n rd.domino,\n placement,\n maxSize\n );\n if (!newKingdom) continue;\n\n const score = expertEvaluate(\n newKingdom,\n game.dominoes,\n perTurn,\n maxSize,\n turnsLeft\n );\n if (score > bestScore) {\n bestScore = score;\n bestPick = rd.domino.number;\n }\n }\n }\n\n return bestPick;\n },\n\n choosePlacement: (context) => {\n const { game, domino, kingdom, validPlacements } = context;\n if (validPlacements.length === 0) return null;\n\n const maxSize = getMaxKingdomSize(game);\n const perTurn = game.rules.basic.dominoesPerTurn;\n const turnsLeft = Math.min(\n game.rules.basic.maxTurns - game.turn,\n EXPERT_MAX_DEPTH\n );\n\n let bestScore = -1;\n let bestPlacement: ValidPlacement = validPlacements[0]!;\n\n for (const placement of validPlacements) {\n const newKingdom = simulatePlacement(kingdom, domino, placement, maxSize);\n if (!newKingdom) continue;\n\n const score = expertEvaluate(\n newKingdom,\n game.dominoes,\n perTurn,\n maxSize,\n turnsLeft\n );\n if (score > bestScore) {\n bestScore = score;\n bestPlacement = placement;\n }\n }\n\n return bestPlacement;\n },\n};\n\n// ─── playBotTurn ─────────────────────────────────────────────────────\n\n/**\n * Executes a single bot turn using the given strategy and engine.\n * Reads the current game state to determine the required action,\n * asks the strategy for a decision, and executes it via the engine.\n *\n * @param engine - The game engine instance\n * @param game - Current game state (must require a player action)\n * @param strategy - The bot strategy to use for decisions\n * @returns Updated game state after the bot's action\n */\nexport const playBotTurn = (\n engine: GameEngine,\n game: GameWithNextAction,\n strategy: BotStrategy\n): GameState => {\n const lordId = game.nextAction.nextLord;\n const action = game.nextAction.nextAction;\n\n if (action === \"pickDomino\") {\n const availableDominoes = game.currentDominoes.filter((d) => !d.picked);\n const dominoPick = strategy.chooseDomino({\n game,\n lordId,\n availableDominoes,\n });\n return engine.chooseDomino({ game, lordId, dominoPick });\n }\n\n if (action === \"placeDomino\") {\n const { lord, player } = getLordAndPlayer(game, lordId);\n if (!lord?.dominoPicked || !player) {\n return engine.discardDomino({ game, lordId });\n }\n\n const domino = lord.dominoPicked;\n const kingdom = player.kingdom;\n const maxSize = getMaxKingdomSize(game);\n const validPlacements = getValidPlacementsUseCase(kingdom, domino, maxSize);\n\n const placement = strategy.choosePlacement({\n game,\n lordId,\n domino,\n kingdom,\n validPlacements,\n });\n\n if (!placement) {\n return engine.discardDomino({ game, lordId });\n }\n\n return engine.placeDomino({\n game,\n lordId,\n position: placement.position,\n rotation: placement.rotation,\n });\n }\n\n // action === \"pass\"\n return engine.discardDomino({ game, lordId });\n};\n\n// ─── Mixed human/bot helpers ────────────────────────────────────────\n\n/**\n * Checks if the current turn belongs to a bot player.\n */\nexport const isBotTurn = (game: GameWithNextAction): boolean => {\n const lordId = game.nextAction.nextLord;\n const lord = game.lords.find((l) => l.id === lordId);\n const player = lord\n ? game.players.find((p) => p.id === lord.playerId)\n : undefined;\n return !!player?.bot;\n};\n\n/**\n * Plays all consecutive bot turns until a human turn or game end is reached.\n * Resolves each bot's strategy by name from the registry (or custom map).\n * Falls back to randomStrategy if the strategy name is not found.\n *\n * @param engine - The game engine instance\n * @param game - Current game state\n * @param customStrategies - Optional custom strategy map (name → BotStrategy)\n * @returns Updated game state paused at the next human turn or game end\n */\nexport const playBotTurns = (\n engine: GameEngine,\n game: GameState,\n customStrategies?: Record<string, BotStrategy>\n): GameState => {\n let current = game;\n\n while (isGameWithNextAction(current) && isBotTurn(current)) {\n const lordId = current.nextAction.nextLord;\n const lord = current.lords.find((l) => l.id === lordId);\n const player = lord\n ? current.players.find((p) => p.id === lord.playerId)\n : undefined;\n const strategyName = player?.bot?.strategyName ?? \"random\";\n const strategy =\n getStrategy(strategyName, customStrategies) ?? randomStrategy;\n current = playBotTurn(engine, current, strategy);\n }\n\n return current;\n};\n","import type {\n GameState,\n Position,\n Rotation,\n} from \"@core/domain/types/index.js\";\nimport type { GameEngine } from \"@core/portUserside/engine.js\";\nimport type { PlayerInput } from \"@application/commands/addPlayersCommand.js\";\n\n// ─── Types ──────────────────────────────────────────────────────────\n\n/**\n * The types of state-changing actions that can be recorded.\n */\nexport type ActionType =\n | \"createGame\"\n | \"addPlayers\"\n | \"addExtraRules\"\n | \"startGame\"\n | \"chooseDomino\"\n | \"placeDomino\"\n | \"discardDomino\";\n\n/**\n * Payload types for each action, containing only the command parameters\n * (excluding the game state, which is too large to store).\n */\nexport type ActionPayloadMap = {\n createGame: { mode: string; seed?: string };\n addPlayers: { players: PlayerInput[] };\n addExtraRules: { extraRules: string[] };\n startGame: Record<string, never>;\n chooseDomino: { lordId: string; dominoPick: number };\n placeDomino: { lordId: string; position: Position; rotation: Rotation };\n discardDomino: { lordId: string };\n};\n\n/**\n * A single recorded action in the game log.\n */\nexport type ActionEntry<T extends ActionType = ActionType> = {\n /** Auto-incrementing index (0-based) */\n id: number;\n /** Timestamp when the action was recorded (Date.now()) */\n timestamp: number;\n /** The type of action performed */\n action: T;\n /** Command parameters (excludes game state) */\n payload: ActionPayloadMap[T];\n /** Turn number after the action was applied */\n turn: number;\n};\n\n/**\n * An immutable log of all actions performed during a game.\n * Can be used to replay a game or analyze player decisions.\n *\n * @example\n * ```typescript\n * const { engine, getLog } = wrapWithActionLog(baseEngine);\n * let game = engine.createGame({ mode: 'Classic' });\n * game = engine.addPlayers({ game, players: ['Alice', 'Bob'] });\n * // ... play the game ...\n * const log = getLog();\n * console.log(log.entries); // all actions recorded\n * ```\n */\nexport type GameActionLog = {\n /** The game ID this log belongs to */\n gameId: string;\n /** Immutable array of recorded actions */\n entries: readonly ActionEntry[];\n};\n\n// ─── Construction ───────────────────────────────────────────────────\n\n/**\n * Creates an empty action log for a game.\n */\nexport const createActionLog = (gameId: string): GameActionLog => ({\n gameId,\n entries: [],\n});\n\n/**\n * Appends an action to the log (immutable — returns a new log).\n */\nexport const appendAction = (\n log: GameActionLog,\n entry: Omit<ActionEntry, \"id\" | \"timestamp\">,\n): GameActionLog => ({\n ...log,\n entries: [\n ...log.entries,\n {\n ...entry,\n id: log.entries.length,\n timestamp: Date.now(),\n },\n ],\n});\n\n// ─── Queries ────────────────────────────────────────────────────────\n\n/**\n * Returns all entries in the log.\n */\nexport const getActions = (log: GameActionLog): readonly ActionEntry[] =>\n log.entries;\n\n/**\n * Returns entries filtered by action type.\n */\nexport const getActionsByType = (\n log: GameActionLog,\n type: ActionType,\n): readonly ActionEntry[] => log.entries.filter((e) => e.action === type);\n\n/**\n * Returns entries filtered by turn number.\n */\nexport const getActionsByTurn = (\n log: GameActionLog,\n turn: number,\n): readonly ActionEntry[] => log.entries.filter((e) => e.turn === turn);\n\n// ─── Engine Wrapper ─────────────────────────────────────────────────\n\n/**\n * Wraps a GameEngine to automatically record every state-changing action.\n * Read-only methods are passed through unchanged.\n *\n * @param engine - The base game engine to wrap\n * @returns An object with the wrapped engine and a getLog() accessor\n *\n * @example\n * ```typescript\n * const { engine: logged, getLog } = wrapWithActionLog(baseEngine);\n * let game = logged.createGame({ mode: 'Classic' });\n * // ... play ...\n * const log = getLog(); // retrieve the full action log\n * ```\n */\nexport const wrapWithActionLog = (\n engine: GameEngine,\n): { engine: GameEngine; getLog: () => GameActionLog } => {\n let log = createActionLog(\"\");\n\n const record = <T extends ActionType>(\n action: T,\n payload: ActionPayloadMap[T],\n turn: number,\n ): void => {\n log = appendAction(log, { action, payload, turn });\n };\n\n const wrappedEngine: GameEngine = {\n // Read-only methods — pass through\n getModes: (cmd) => engine.getModes(cmd),\n getExtraRules: (cmd) => engine.getExtraRules(cmd),\n calculateScore: (cmd) => engine.calculateScore(cmd),\n getValidPlacements: (cmd) => engine.getValidPlacements(cmd),\n canPlaceDomino: (cmd) => engine.canPlaceDomino(cmd),\n serialize: (cmd) => engine.serialize(cmd),\n deserialize: (cmd) => engine.deserialize(cmd),\n getResults: (cmd) => engine.getResults(cmd),\n getDynastyResults: (cmd) => engine.getDynastyResults(cmd),\n\n // State-changing methods — record after execution\n createGame: (cmd) => {\n const game = engine.createGame(cmd);\n log = createActionLog(game.id);\n record(\"createGame\", { mode: cmd.mode, seed: cmd.seed }, game.turn);\n return game;\n },\n\n addPlayers: (cmd) => {\n const game = engine.addPlayers(cmd);\n record(\"addPlayers\", { players: cmd.players }, game.turn);\n return game;\n },\n\n addExtraRules: (cmd) => {\n const game = engine.addExtraRules(cmd);\n record(\"addExtraRules\", { extraRules: cmd.extraRules }, game.turn);\n return game;\n },\n\n startGame: (cmd) => {\n const game = engine.startGame(cmd);\n record(\"startGame\", {}, game.turn);\n return game;\n },\n\n chooseDomino: (cmd) => {\n const game = engine.chooseDomino(cmd);\n record(\n \"chooseDomino\",\n { lordId: cmd.lordId, dominoPick: cmd.dominoPick },\n game.turn,\n );\n return game;\n },\n\n placeDomino: (cmd) => {\n const game = engine.placeDomino(cmd);\n record(\n \"placeDomino\",\n {\n lordId: cmd.lordId,\n position: cmd.position,\n rotation: cmd.rotation,\n },\n game.turn,\n );\n return game;\n },\n\n discardDomino: (cmd) => {\n const game = engine.discardDomino(cmd);\n record(\"discardDomino\", { lordId: cmd.lordId }, game.turn);\n return game;\n },\n };\n\n return {\n engine: wrappedEngine,\n getLog: () => log,\n };\n};\n\n// ─── Replay ─────────────────────────────────────────────────────────\n\n/**\n * Replays all actions from a log on a fresh engine to reconstruct the final game state.\n * The engine should use the same configuration (especially shuffleMethod) as the original game\n * to guarantee deterministic results when a seed is present.\n *\n * @param engine - A game engine instance (should match original config)\n * @param log - The action log to replay\n * @returns The final game state after replaying all actions\n */\nexport const replayActions = (\n engine: GameEngine,\n log: GameActionLog,\n): GameState => {\n if (log.entries.length === 0) {\n throw new Error(\"Cannot replay an empty action log\");\n }\n\n const firstEntry = log.entries[0];\n if (firstEntry?.action !== \"createGame\") {\n throw new Error(\"Action log must start with a createGame action\");\n }\n\n const firstPayload = firstEntry.payload as ActionPayloadMap[\"createGame\"];\n let game: GameState = engine.createGame({\n mode: firstPayload.mode,\n seed: firstPayload.seed,\n });\n\n for (let i = 1; i < log.entries.length; i++) {\n const entry = log.entries[i];\n if (!entry) continue;\n\n switch (entry.action) {\n case \"createGame\": {\n const payload = entry.payload as ActionPayloadMap[\"createGame\"];\n game = engine.createGame({ mode: payload.mode, seed: payload.seed });\n break;\n }\n case \"addPlayers\": {\n const payload = entry.payload as ActionPayloadMap[\"addPlayers\"];\n game = engine.addPlayers({ game, players: payload.players });\n break;\n }\n case \"addExtraRules\": {\n const payload = entry.payload as ActionPayloadMap[\"addExtraRules\"];\n game = engine.addExtraRules({\n game,\n extraRules: payload.extraRules,\n });\n break;\n }\n case \"startGame\": {\n game = engine.startGame({ game });\n break;\n }\n case \"chooseDomino\": {\n const payload = entry.payload as ActionPayloadMap[\"chooseDomino\"];\n game = engine.chooseDomino({\n game,\n lordId: payload.lordId,\n dominoPick: payload.dominoPick,\n });\n break;\n }\n case \"placeDomino\": {\n const payload = entry.payload as ActionPayloadMap[\"placeDomino\"];\n game = engine.placeDomino({\n game,\n lordId: payload.lordId,\n position: payload.position,\n rotation: payload.rotation,\n });\n break;\n }\n case \"discardDomino\": {\n const payload = entry.payload as ActionPayloadMap[\"discardDomino\"];\n game = engine.discardDomino({\n game,\n lordId: payload.lordId,\n });\n break;\n }\n }\n }\n\n return game;\n};\n","import type { GameState } from \"@core/domain/types/index.js\";\nimport { UndoError, RedoError } from \"@core/domain/errors/domainErrors.js\";\n\n/**\n * Manages a history of game states for undo/redo support.\n * Uses a snapshot-based approach: each state is stored as a full GameState.\n *\n * @example\n * ```typescript\n * let history = createGameHistory(initialGame);\n * const newGame = engine.chooseDomino({ game: history.current, ... });\n * history = pushState(history, newGame);\n * history = undo(history); // back to initialGame\n * history = redo(history); // forward to newGame\n * ```\n */\nexport type GameHistory = {\n /** The current game state */\n current: GameState;\n /** Stack of previous states (most recent last) */\n past: GameState[];\n /** Stack of undone states (most recent last) */\n future: GameState[];\n};\n\n/**\n * Creates a new game history initialized with a game state.\n *\n * @param initialState - The starting game state\n * @returns A new GameHistory with empty past and future\n */\nexport const createGameHistory = (initialState: GameState): GameHistory => ({\n current: initialState,\n past: [],\n future: [],\n});\n\n/**\n * Records a new game state in the history.\n * The current state is pushed to the past stack, and the future stack is cleared\n * (branching from a previous undo point discards the old future).\n *\n * @param history - The current history\n * @param newState - The new game state to record\n * @returns Updated history with the new state as current\n */\nexport const pushState = (\n history: GameHistory,\n newState: GameState\n): GameHistory => ({\n current: newState,\n past: [...history.past, history.current],\n future: [],\n});\n\n/**\n * Reverts to the previous game state.\n * The current state is moved to the future stack for potential redo.\n *\n * @param history - The current history\n * @returns Updated history with the previous state as current\n * @throws {UndoError} If there is no previous state to revert to\n */\nexport const undo = (history: GameHistory): GameHistory => {\n if (history.past.length === 0) {\n throw new UndoError();\n }\n\n const previous = history.past[history.past.length - 1]!;\n return {\n current: previous,\n past: history.past.slice(0, -1),\n future: [...history.future, history.current],\n };\n};\n\n/**\n * Re-applies a previously undone game state.\n * The current state is moved to the past stack.\n *\n * @param history - The current history\n * @returns Updated history with the next undone state as current\n * @throws {RedoError} If there is no undone state to re-apply\n */\nexport const redo = (history: GameHistory): GameHistory => {\n if (history.future.length === 0) {\n throw new RedoError();\n }\n\n const next = history.future[history.future.length - 1]!;\n return {\n current: next,\n past: [...history.past, history.current],\n future: history.future.slice(0, -1),\n };\n};\n\n/**\n * Checks whether an undo operation is available.\n */\nexport const canUndo = (history: GameHistory): boolean =>\n history.past.length > 0;\n\n/**\n * Checks whether a redo operation is available.\n */\nexport const canRedo = (history: GameHistory): boolean =>\n history.future.length > 0;\n\n/**\n * Clears the undo/redo history, keeping only the current state.\n *\n * @param history - The current history\n * @returns A new history with empty past and future\n */\nexport const clearHistory = (history: GameHistory): GameHistory => ({\n current: history.current,\n past: [],\n future: [],\n});\n\n/**\n * Returns the number of states in the past and future stacks.\n */\nexport const getHistorySize = (\n history: GameHistory\n): { past: number; future: number } => ({\n past: history.past.length,\n future: history.future.length,\n});\n","import type { GameEngine } from \"@core/portUserside/engine\";\nimport { type DebugOptions, wrapWithDebug } from \"@core/useCases/gameDebug.js\";\nimport { wrapWithEvents } from \"@core/useCases/gameEvents.js\";\nimport { configureEngine, type EngineConfig } from \"./config.js\";\n\n// Commands\nexport * from \"@application/commands/index.js\";\nexport { validateGameState } from \"@core/domain/entities/validateGameState.js\";\n// Domain errors\nexport * from \"@core/domain/errors/domainErrors.js\";\n// Domain types\nexport * from \"@core/domain/types/index.js\";\n// i18n\nexport * from \"@core/i18n/translations.js\";\n// Ports\nexport * from \"@core/portServerside/index.js\";\nexport * from \"@core/portUserside/engine.js\";\n// Bot / AI player\nexport {\n advancedStrategy,\n type BotStrategy,\n expertStrategy,\n greedyStrategy,\n isBotTurn,\n type PickContext,\n type PlaceContext,\n playBotTurn,\n playBotTurns,\n randomStrategy,\n} from \"@core/useCases/bot.js\";\n// Bot strategy registry\nexport {\n getStrategy,\n getStrategyNames,\n type StrategyName,\n} from \"@core/useCases/botRegistry.js\";\n// Action log (game history / replay)\nexport {\n type ActionEntry,\n type ActionPayloadMap,\n type ActionType,\n appendAction,\n createActionLog,\n type GameActionLog,\n getActions,\n getActionsByTurn,\n getActionsByType,\n replayActions,\n wrapWithActionLog,\n} from \"@core/useCases/gameActionLog.js\";\n// Debug mode\nexport {\n type DebugLogEntry,\n type DebugLogger,\n type DebugLogLevel,\n type DebugOptions,\n type GameStateSummary,\n summarizeGameState,\n wrapWithDebug,\n} from \"@core/useCases/gameDebug.js\";\n// Game events\nexport {\n type GameEventCallbacks,\n wrapWithEvents,\n} from \"@core/useCases/gameEvents.js\";\n// History (undo/redo)\nexport {\n canRedo,\n canUndo,\n clearHistory,\n createGameHistory,\n type GameHistory,\n getHistorySize,\n pushState,\n redo,\n undo,\n} from \"@core/useCases/gameHistory.js\";\nexport type { DynastyResult } from \"@core/useCases/getDynastyResult.js\";\n// Use cases (for advanced usage)\nexport type { ValidPlacement } from \"@core/useCases/getValidPlacements.js\";\nexport {\n createSavePoint,\n deserializeGame,\n type GameSavePoint,\n restoreFromSavePoint,\n serializeGame,\n} from \"@core/useCases/serialization.js\";\n// Configuration\nexport type { EngineConfig };\n\n/**\n * Creates a new Kingdomino game engine instance.\n *\n * @param config - Configuration options for the engine\n * @returns A fully configured GameEngine instance\n *\n * @example\n * ```typescript\n * // Basic usage\n * const engine = createGameEngine({});\n *\n * // With logging\n * const engine = createGameEngine({ logging: true });\n *\n * // With event callbacks\n * const engine = createGameEngine({\n * events: {\n * onDominoPlaced: ({ lordId }) => console.log(`${lordId} placed`),\n * onGameEnd: () => console.log('Game over!'),\n * },\n * });\n * ```\n */\nexport const createGameEngine = (config: Partial<EngineConfig>): GameEngine => {\n const {\n createGameHandler,\n getModesHandler,\n getExtraRulesHandler,\n addPlayersHandler,\n addExtraRulesHandler,\n startGameHandler,\n chooseDominoHandler,\n placeDominoHandler,\n discardDominoHandler,\n getResultHandler,\n calculateScoreHandler,\n getValidPlacementsHandler,\n canPlaceDominoHandler,\n serializeGameHandler,\n deserializeGameHandler,\n getDynastyResultHandler,\n } = configureEngine(config);\n\n let engine: GameEngine = {\n getModes: (command) => getModesHandler(command),\n getExtraRules: (command) => getExtraRulesHandler(command),\n createGame: (command) => createGameHandler(command),\n addPlayers: (command) => addPlayersHandler(command),\n addExtraRules: (command) => addExtraRulesHandler(command),\n startGame: (command) => startGameHandler(command),\n chooseDomino: (command) => chooseDominoHandler(command),\n placeDomino: (command) => placeDominoHandler(command),\n discardDomino: (command) => discardDominoHandler(command),\n getResults: (command) => getResultHandler(command),\n calculateScore: (command) => calculateScoreHandler(command),\n getValidPlacements: (command) => getValidPlacementsHandler(command),\n canPlaceDomino: (command) => canPlaceDominoHandler(command),\n serialize: (command) => serializeGameHandler(command),\n deserialize: (command) => deserializeGameHandler(command),\n getDynastyResults: (command) => getDynastyResultHandler(command),\n };\n\n if (config.events) {\n engine = wrapWithEvents(engine, config.events);\n }\n\n if (config.debug) {\n const debugOptions: DebugOptions | undefined =\n typeof config.debug === \"object\" ? config.debug : undefined;\n engine = wrapWithDebug(engine, debugOptions);\n }\n\n return engine;\n};\n"],"mappings":";AAsCO,IAAM,YAAY;AAAA;AAAA,EAEvB,YAAY;AAAA;AAAA,EAEZ,SAAS;AAAA;AAAA,EAET,OAAO;AAAA;AAAA,EAEP,QAAQ;AACV;AA8CO,IAAM,uBAAuB,CAClC,SAC+B;AAC/B,SAAO,KAAK,WAAW,SAAS;AAClC;AAOO,IAAM,qBAAqB,CAChC,SAC6B;AAC7B,SAAO,KAAK,WAAW,SAAS;AAClC;;;AC5CO,IAAM,qBAAqB,CAAC,SAAsC;AACvE,QAAM,aAAa,qBAAqB,IAAI,IACxC,UAAU,KAAK,WAAW,UAAU,KACpC,QAAQ,KAAK,WAAW,IAAI;AAEhC,SAAO;AAAA,IACL,QAAQ,KAAK;AAAA,IACb,MAAM,KAAK;AAAA,IACX;AAAA,IACA,cAAc,KAAK,QAAQ;AAAA,IAC3B,mBAAmB,KAAK,SAAS;AAAA,IACjC,sBAAsB,KAAK,gBAAgB;AAAA,IAC3C,YAAY,KAAK,MAAM;AAAA,EACzB;AACF;AAEA,IAAM,qBAAkC;AAAA,EACtC,KAAK,CAAC,UAAyB;AAC7B,UAAM,QAAQ,MAAM,MAAM,YAAY,EAAE,OAAO,CAAC;AAChD,UAAM,OAAO,mBAAmB,MAAM,SAAS,IAAI,KAAK,IAAI,MAAM,MAAM;AAExE,QAAI,MAAM,UAAU,SAAS;AAC3B,cAAQ,MAAM,GAAG,IAAI,aAAa,MAAM,KAAK,EAAE;AAC/C;AAAA,IACF;AAEA,QAAI,MAAM,SAAS;AACjB,YAAM,IAAI,MAAM;AAChB,cAAQ;AAAA,QACN,GAAG,IAAI,WAAW,EAAE,IAAI,SAAS,EAAE,UAAU,YAAY,EAAE,YAAY,aAAa,EAAE,iBAAiB;AAAA,MACzG;AAAA,IACF,OAAO;AACL,cAAQ,IAAI,IAAI;AAAA,IAClB;AAAA,EACF;AACF;AAEA,IAAM,cAAc,CAAC,UAAuC;AAC1D,SACE,OAAO,UAAU,YACjB,UAAU,QACV,QAAQ,SACR,gBAAgB,SAChB,aAAa,SACb,cAAc;AAElB;AAIA,IAAM,mBAAmB,CAAC,QAAyC;AACjE,SACE,OAAO,QAAQ,YACf,QAAQ,QACR,UAAU,OACV,YAAa,IAAwB,IAAI;AAE7C;AAEA,IAAM,gBAAgB,CAAC,QAAsD;AAC3E,MAAI,OAAO,QAAQ,YAAY,QAAQ,KAAM,QAAO;AAEpD,QAAM,SAAS;AACf,QAAM,SAAkC,CAAC;AAEzC,MAAI,UAAU,OAAQ,QAAO,OAAO,OAAO;AAC3C,MAAI,YAAY,OAAQ,QAAO,SAAS,OAAO;AAC/C,MAAI,gBAAgB,OAAQ,QAAO,aAAa,OAAO;AACvD,MAAI,cAAc,OAAQ,QAAO,WAAW,OAAO;AACnD,MAAI,cAAc,OAAQ,QAAO,WAAW,OAAO;AACnD,MAAI,aAAa,OAAQ,QAAO,UAAU,OAAO;AACjD,MAAI,gBAAgB,OAAQ,QAAO,aAAa,OAAO;AAEvD,SAAO,OAAO,KAAK,MAAM,EAAE,SAAS,IAAI,SAAS;AACnD;AAIA,IAAM,aAAa,CACjB,QACA,IACA,QACA,UAC8B;AAC9B,SAAO,CAAC,QAAe;AACrB,UAAM,aAAY,oBAAI,KAAK,GAAE,YAAY;AAGzC,UAAM,gBACJ,UAAU,aAAa,iBAAiB,GAAG,IACvC,mBAAmB,IAAI,IAAI,IAC3B;AAEN,UAAM,cAA6B;AAAA,MACjC;AAAA,MACA;AAAA,MACA,OAAO;AAAA,MACP,SAAS;AAAA,MACT,QAAQ,UAAU,YAAY,cAAc,GAAG,IAAI;AAAA,IACrD;AAEA,WAAO,IAAI,WAAW;AAGtB,UAAM,QAAQ,YAAY,IAAI;AAC9B,QAAI;AACJ,QAAI;AACF,eAAS,GAAG,GAAG;AAAA,IACjB,SAASA,MAAK;AACZ,YAAMC,cAAa,KAAK,OAAO,YAAY,IAAI,IAAI,SAAS,GAAG,IAAI;AACnE,YAAM,aAA4B;AAAA,QAChC,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,QAClC;AAAA,QACA,OAAO;AAAA,QACP,SAAS;AAAA,QACT,OAAOD,gBAAe,QAAQA,KAAI,UAAU,OAAOA,IAAG;AAAA,QACtD,YAAAC;AAAA,MACF;AACA,aAAO,IAAI,UAAU;AACrB,YAAMD;AAAA,IACR;AAEA,UAAM,aAAa,KAAK,OAAO,YAAY,IAAI,IAAI,SAAS,GAAG,IAAI;AAGnE,UAAM,eACJ,UAAU,aAAa,YAAY,MAAM,IACrC,mBAAmB,MAAmB,IACtC;AAEN,UAAM,aAA4B;AAAA,MAChC,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClC;AAAA,MACA,OAAO;AAAA,MACP,SAAS;AAAA,MACT;AAAA,MACA,WACE,UAAU,aAAa,YAAY,MAAM,IACpC,SACD;AAAA,IACR;AAEA,WAAO,IAAI,UAAU;AAErB,WAAO;AAAA,EACT;AACF;AAkBO,IAAM,gBAAgB,CAC3B,QACA,YACe;AACf,QAAM,SAAS,SAAS,UAAU;AAClC,QAAM,QAAQ,SAAS,SAAS;AAEhC,SAAO;AAAA,IACL,UAAU,WAAW,YAAY,OAAO,UAAU,QAAQ,KAAK;AAAA,IAC/D,eAAe;AAAA,MACb;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,IACA,YAAY,WAAW,cAAc,OAAO,YAAY,QAAQ,KAAK;AAAA,IACrE,YAAY,WAAW,cAAc,OAAO,YAAY,QAAQ,KAAK;AAAA,IACrE,eAAe;AAAA,MACb;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,IACA,WAAW,WAAW,aAAa,OAAO,WAAW,QAAQ,KAAK;AAAA,IAClE,cAAc;AAAA,MACZ;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,IACA,aAAa,WAAW,eAAe,OAAO,aAAa,QAAQ,KAAK;AAAA,IACxE,eAAe;AAAA,MACb;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,IACA,YAAY,WAAW,cAAc,OAAO,YAAY,QAAQ,KAAK;AAAA,IACrE,gBAAgB;AAAA,MACd;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,IACA,oBAAoB;AAAA,MAClB;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,IACA,gBAAgB;AAAA,MACd;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,IACA,WAAW,WAAW,aAAa,OAAO,WAAW,QAAQ,KAAK;AAAA,IAClE,aAAa,WAAW,eAAe,OAAO,aAAa,QAAQ,KAAK;AAAA,IACxE,mBAAmB;AAAA,MACjB;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AC7OA,IAAM,cAAc,CAAC,SACnB,mBAAmB,IAAI,KAAK,KAAK,WAAW,SAAS;AAchD,IAAM,iBAAiB,CAC5B,QACA,eACgB;AAAA;AAAA,EAEhB,UAAU,CAAC,QAAQ,OAAO,SAAS,GAAG;AAAA,EACtC,eAAe,CAAC,QAAQ,OAAO,cAAc,GAAG;AAAA,EAChD,gBAAgB,CAAC,QAAQ,OAAO,eAAe,GAAG;AAAA,EAClD,oBAAoB,CAAC,QAAQ,OAAO,mBAAmB,GAAG;AAAA,EAC1D,gBAAgB,CAAC,QAAQ,OAAO,eAAe,GAAG;AAAA,EAClD,WAAW,CAAC,QAAQ,OAAO,UAAU,GAAG;AAAA,EACxC,aAAa,CAAC,QAAQ,OAAO,YAAY,GAAG;AAAA,EAC5C,YAAY,CAAC,QAAQ,OAAO,WAAW,GAAG;AAAA,EAC1C,mBAAmB,CAAC,QAAQ,OAAO,kBAAkB,GAAG;AAAA;AAAA,EAGxD,YAAY,CAAC,QAAQ;AACnB,UAAM,OAAO,OAAO,WAAW,GAAG;AAClC,cAAU,gBAAgB,EAAE,KAAK,CAAC;AAClC,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,CAAC,QAAQ;AACnB,UAAM,OAAO,OAAO,WAAW,GAAG;AAClC,cAAU,iBAAiB,EAAE,KAAK,CAAC;AACnC,WAAO;AAAA,EACT;AAAA,EAEA,eAAe,CAAC,QAAQ,OAAO,cAAc,GAAG;AAAA,EAEhD,WAAW,CAAC,QAAQ;AAClB,UAAM,OAAO,OAAO,UAAU,GAAG;AACjC,cAAU,gBAAgB,EAAE,KAAK,CAAC;AAClC,cAAU,cAAc,EAAE,MAAM,MAAM,KAAK,KAAK,CAAC;AACjD,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,CAAC,QAAQ;AACrB,UAAM,aAAa,IAAI,KAAK;AAC5B,UAAM,OAAO,OAAO,aAAa,GAAG;AACpC,cAAU,iBAAiB;AAAA,MACzB;AAAA,MACA,QAAQ,IAAI;AAAA,MACZ,cAAc,IAAI;AAAA,IACpB,CAAC;AAGD,QAAI,KAAK,SAAS,YAAY;AAC5B,gBAAU,YAAY,EAAE,MAAM,MAAM,WAAW,CAAC;AAChD,gBAAU,cAAc,EAAE,MAAM,MAAM,KAAK,KAAK,CAAC;AAAA,IACnD;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,aAAa,CAAC,QAAQ;AACpB,UAAM,OAAO,OAAO,YAAY,GAAG;AACnC,cAAU,iBAAiB,EAAE,MAAM,QAAQ,IAAI,OAAO,CAAC;AAEvD,QAAI,YAAY,IAAI,GAAG;AACrB,gBAAU,YAAY,EAAE,KAAK,CAAC;AAAA,IAChC;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,eAAe,CAAC,QAAQ;AACtB,UAAM,OAAO,OAAO,cAAc,GAAG;AACrC,cAAU,oBAAoB,EAAE,MAAM,QAAQ,IAAI,OAAO,CAAC;AAE1D,QAAI,YAAY,IAAI,GAAG;AACrB,gBAAU,YAAY,EAAE,KAAK,CAAC;AAAA,IAChC;AAEA,WAAO;AAAA,EACT;AACF;;;AC3IO,IAAM,gBAAgB,CAAC,qBAAsC;AAClE,QAAM,gBAAgB,CAAC,OAAe,YAA4B;AAChE,UAAM,aAAY,oBAAI,KAAK,GAAE,YAAY;AACzC,WAAO,GAAG,SAAS,qBAAqB,KAAK,KAAK,OAAO;AAAA,EAC3D;AAEA,SAAO;AAAA,IACL,MAAM,CAAC,YAAoB;AACzB,UAAI,kBAAkB;AACpB,gBAAQ,IAAI,cAAc,QAAQ,OAAO,CAAC;AAAA,MAC5C;AAAA,IACF;AAAA,IACA,OAAO,CAAC,YAAoB;AAC1B,UAAI,kBAAkB;AACpB,gBAAQ,MAAM,cAAc,SAAS,OAAO,CAAC;AAAA,MAC/C;AAAA,IACF;AAAA,EACF;AACF;AAMO,IAAM,eAAuB;AAAA,EAClC,MAAM,MAAM;AAAA,EAAC;AAAA,EACb,OAAO,MAAM;AAAA,EAAC;AAChB;;;ACnCA;AAAA,EACE,SAAW;AAAA,IACT;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,EACF;AACF;;;AC9gBA,IAAM,eAAe,MAA0B;AAC7C,QAAM,WAAqC,CAAC;AAE5C,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,gBAAY,GAAG;AACvD,UAAM,kBAA4B,CAAC;AACnC,UAAM,QAAQ,CAAC,WAAW;AACxB,sBAAgB,KAAK;AAAA,QACnB,MAAM;AAAA,UACJ,MAAc,OAAO,KAAK;AAAA,UAC1B,QAAQ,OAAO,KAAK;AAAA,QACtB;AAAA,QACA,OAAO;AAAA,UACL,MAAc,OAAO,MAAM;AAAA,UAC3B,QAAQ,OAAO,MAAM;AAAA,QACvB;AAAA,QACA,QAAQ,OAAO;AAAA,MACjB,CAAC;AAAA,IACH,CAAC;AAED,aAAS,GAAG,IAAI;AAAA,EAClB;AAEA,SAAO;AAAA,IACL,YAAY,CAAC,SAAmB;AAC9B,aAAO,SAAS,KAAK,IAAI,KAAK,CAAC;AAAA,IACjC;AAAA,EACF;AACF;AAEA,IAAO,uBAAQ;;;AClCf;AAAA,EACI;AAAA,IACI,MAAQ;AAAA,IACR,aAAe;AAAA,EACnB;AACJ;;;ACDA,IAAM,YAAY,MAAsB;AACtC,QAAM,QAAoB,CAAC;AAE3B,gBAAU,QAAQ,CAAC,SAAS;AAC1B,UAAM,KAAK;AAAA,MACT,MAAM,KAAK;AAAA,MACX,aAAa,KAAK;AAAA,IACpB,CAAC;AAAA,EACH,CAAC;AAED,SAAO;AAAA,IACL,eAAe,MAAM;AACnB,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,IAAO,oBAAQ;;;ACrBf;AAAA,EACE,QAAU;AAAA,IACR;AAAA,MACE,cAAgB;AAAA,MAChB,gBAAkB;AAAA,MAClB,aAAe;AAAA,MACf,iBAAmB;AAAA,MACnB,UAAY;AAAA,MACZ,gBAAkB;AAAA,IACpB;AAAA,IACA;AAAA,MACE,cAAgB;AAAA,MAChB,gBAAkB;AAAA,MAClB,aAAe;AAAA,MACf,iBAAmB;AAAA,MACnB,UAAY;AAAA,MACZ,gBAAkB;AAAA,IACpB;AAAA,IACA;AAAA,MACE,cAAgB;AAAA,MAChB,gBAAkB;AAAA,MAClB,aAAe;AAAA,MACf,iBAAmB;AAAA,MACnB,UAAY;AAAA,MACZ,gBAAkB;AAAA,IACpB;AAAA,IACA;AAAA,MACE,cAAgB;AAAA,MAChB,gBAAkB;AAAA,MAClB,aAAe;AAAA,MACf,iBAAmB;AAAA,MACnB,UAAY;AAAA,MACZ,gBAAkB;AAAA,IACpB;AAAA,EACF;AAAA,EACA,OAAS;AAAA,IACP;AAAA,MACE,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,MAAQ,CAAC,EAAE,MAAQ,WAAW,aAAe,2BAA2B,CAAC;AAAA,IAC3E;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,MAAQ,CAAC,EAAE,MAAQ,WAAW,aAAe,2BAA2B,CAAC;AAAA,IAC3E;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,MAAQ,CAAC,EAAE,MAAQ,WAAW,aAAe,2BAA2B,CAAC;AAAA,MACzE,cAAgB;AAAA,IAClB;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,MAAQ,CAAC,EAAE,MAAQ,WAAW,aAAe,2BAA2B,CAAC;AAAA,IAC3E;AAAA,EACF;AACF;;;ACtDA,IAAM,YAAY,MAAsB;AACtC,QAAM,QAAe;AAAA,IACnB,OAAO,CAAC;AAAA,IACR,YAAY,CAAC;AAAA,EACf;AAEA,QAAM,cAAc,cAAU;AAC9B,QAAM,aAAa,cAAU;AAE7B,cAAY,QAAQ,CAAC,SAAS;AAC5B,UAAM,MAAM,KAAK,YAAY,IAAI;AAAA,MAC/B,OAAO,KAAK;AAAA,MACZ,aAAa,KAAK;AAAA,MAClB,iBAAiB,KAAK;AAAA,MACtB,UAAU,KAAK;AAAA,MACf,gBAAgB,KAAK;AAAA,IACvB;AAAA,EACF,CAAC;AAED,aAAW,QAAQ,CAAC,SAAS;AAC3B,UAAM,WAAW,KAAK;AAAA,MACpB,MAAM,KAAK;AAAA,MACX,aAAa,KAAK;AAAA,MAClB,MAAM,KAAK;AAAA,MACX,GAAI,kBAAkB,QAAQ,EAAE,cAAc,KAAK,aAAa;AAAA,IAClE,CAAC;AAAA,EACH,CAAC;AAED,SAAO;AAAA,IACL,QAAQ,MAAM;AACZ,aAAO;AAAA,IACT;AAAA,IACA,aAAa,MAAM;AACjB,aAAO,MAAM;AAAA,IACf;AAAA,EACF;AACF;AAEA,IAAO,oBAAQ;;;ACxCR,IAAM,gBAA+B,CAAI,UAAe;AAC7D,WAAS,IAAI,MAAM,SAAS,GAAG,IAAI,GAAG,KAAK;AACzC,UAAM,IAAI,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI,EAAE;AAC5C,KAAC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAQ,MAAM,CAAC,CAAM;AAAA,EACtD;AACA,SAAO;AACT;;;ACNO,IAAM,aAAyB,MAAM;AAC1C,SAAO,WAAW,OAAO,WAAW;AACtC;;;ACAO,IAAM,YAAY;AAAA;AAAA,EAEvB,cAAc;AAAA,EACd,uBAAuB;AAAA,EACvB,yBAAyB;AAAA;AAAA,EAGzB,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,gBAAgB;AAAA;AAAA,EAGhB,sBAAsB;AAAA,EACtB,qBAAqB;AAAA,EACrB,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,wBAAwB;AAAA,EACxB,2BAA2B;AAAA,EAC3B,yBAAyB;AAAA,EACzB,gCAAgC;AAAA;AAAA,EAGhC,eAAe;AAAA,EACf,aAAa;AAAA,EACb,cAAc;AAAA,EACd,uBAAuB;AAAA;AAAA,EAGvB,kBAAkB;AAAA,EAClB,kBAAkB;AACpB;AAmBO,IAAM,oBAAoB,CAC/B,MACA,SACA,aACiB;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AACF;AAKO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EACzB;AAAA,EACA;AAAA,EAEhB,YAAY,OAAoB;AAC9B,UAAM,MAAM,OAAO;AACnB,SAAK,OAAO;AACZ,SAAK,OAAO,MAAM;AAClB,SAAK,UAAU,MAAM;AAAA,EACvB;AACF;AAKO,IAAM,mBAAN,cAA+B,gBAAgB;AAAA,EACpD,YAAY,SAAiB,SAAmC;AAC9D,UAAM;AAAA,MACJ,MAAM,UAAU;AAAA,MAChB;AAAA,MACA;AAAA,IACF,CAAC;AACD,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAM,qBAAN,cAAiC,gBAAgB;AAAA,EACtD,YACE,SACA,OAAsB,UAAU,uBAChC,SACA;AACA,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAM,uBAAN,cAAmC,gBAAgB;AAAA,EACxD,YACE,SACA,OAAsB,UAAU,yBAChC,SACA;AACA,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAM,gBAAN,cAA4B,gBAAgB;AAAA,EACjD,YACE,SACA,OAAsB,UAAU,gBAChC,SACA;AACA,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAM,kBAAN,cAA8B,gBAAgB;AAAA,EACnD,YACE,SACA,MACA,SACA;AACA,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAM,YAAN,cAAwB,gBAAgB;AAAA,EAC7C,YAAY,UAAU,oBAAoB,SAAmC;AAC3E,UAAM;AAAA,MACJ,MAAM,UAAU;AAAA,MAChB;AAAA,MACA;AAAA,IACF,CAAC;AACD,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAM,YAAN,cAAwB,gBAAgB;AAAA,EAC7C,YAAY,UAAU,oBAAoB,SAAmC;AAC3E,UAAM;AAAA,MACJ,MAAM,UAAU;AAAA,MAChB;AAAA,MACA;AAAA,IACF,CAAC;AACD,SAAK,OAAO;AAAA,EACd;AACF;;;ACtLO,IAAM,iBAAiB;AAAA;AAAA,EAE5B,oBAAoB;AAAA,EACpB,6BAA6B;AAAA,EAC7B,+BAA+B;AAAA,EAC/B,sBAAsB;AAAA,EACtB,wBAAwB;AAAA,EACxB,wBAAwB;AAAA,EACxB,sBAAsB;AAAA,EACtB,yBAAyB;AAAA,EACzB,2BAA2B;AAAA,EAC3B,8BAA8B;AAAA,EAC9B,iCAAiC;AAAA,EACjC,+BAA+B;AAAA,EAC/B,sCAAsC;AAAA,EACtC,qBAAqB;AAAA,EACrB,mBAAmB;AAAA,EACnB,oBAAoB;AAAA,EACpB,6BAA6B;AAAA,EAC7B,4BAA4B;AAAA,EAC5B,2BAA2B;AAAA,EAC3B,wBAAwB;AAAA,EACxB,wBAAwB;AAAA;AAAA,EAGxB,cAAc;AAAA;AAAA,EAGd,qBAAqB;AAAA,EACrB,cAAc;AAAA;AAAA,EAGd,eAAe;AAAA,EACf,cAAc;AAAA,EACd,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,cAAc;AAAA,EACd,aAAa;AAAA;AAAA,EAGb,mBAAmB;AAAA,EACnB,eAAe;AAAA,EACf,aAAa;AAAA,EACb,cAAc;AAAA;AAAA,EAGd,oBAAoB;AAAA,EACpB,qBAAqB;AAAA,EACrB,aAAa;AACf;AAQO,IAAM,sBAA0D;AAAA;AAAA,EAErE,CAAC,eAAe,kBAAkB,GAAG;AAAA,EACrC,CAAC,eAAe,2BAA2B,GAAG;AAAA,EAC9C,CAAC,eAAe,6BAA6B,GAAG;AAAA,EAChD,CAAC,eAAe,oBAAoB,GAAG;AAAA,EACvC,CAAC,eAAe,sBAAsB,GAAG;AAAA,EACzC,CAAC,eAAe,sBAAsB,GAAG;AAAA,EACzC,CAAC,eAAe,oBAAoB,GAAG;AAAA,EACvC,CAAC,eAAe,uBAAuB,GAAG;AAAA,EAC1C,CAAC,eAAe,yBAAyB,GAAG;AAAA,EAC5C,CAAC,eAAe,4BAA4B,GAC1C;AAAA,EACF,CAAC,eAAe,+BAA+B,GAC7C;AAAA,EACF,CAAC,eAAe,6BAA6B,GAAG;AAAA,EAChD,CAAC,eAAe,oCAAoC,GAClD;AAAA,EACF,CAAC,eAAe,mBAAmB,GAAG;AAAA,EACtC,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,kBAAkB,GAAG;AAAA,EACrC,CAAC,eAAe,2BAA2B,GACzC;AAAA,EACF,CAAC,eAAe,0BAA0B,GACxC;AAAA,EACF,CAAC,eAAe,yBAAyB,GACvC;AAAA,EACF,CAAC,eAAe,sBAAsB,GAAG;AAAA,EACzC,CAAC,eAAe,sBAAsB,GAAG;AAAA;AAAA,EAGzC,CAAC,eAAe,YAAY,GAAG;AAAA;AAAA,EAG/B,CAAC,eAAe,mBAAmB,GAAG;AAAA,EACtC,CAAC,eAAe,YAAY,GAAG;AAAA;AAAA,EAG/B,CAAC,eAAe,aAAa,GAAG;AAAA,EAChC,CAAC,eAAe,YAAY,GAAG;AAAA,EAC/B,CAAC,eAAe,aAAa,GAAG;AAAA,EAChC,CAAC,eAAe,UAAU,GAAG;AAAA,EAC7B,CAAC,eAAe,YAAY,GAAG;AAAA,EAC/B,CAAC,eAAe,YAAY,GAAG;AAAA,EAC/B,CAAC,eAAe,WAAW,GAAG;AAAA;AAAA,EAG9B,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,aAAa,GAAG;AAAA,EAChC,CAAC,eAAe,WAAW,GAAG;AAAA,EAC9B,CAAC,eAAe,YAAY,GAAG;AAAA;AAAA,EAG/B,CAAC,eAAe,kBAAkB,GAAG;AAAA,EACrC,CAAC,eAAe,mBAAmB,GAAG;AAAA,EACtC,CAAC,eAAe,WAAW,GAAG;AAChC;AAMO,IAAM,4BAGT;AAAA,EACF,CAAC,UAAU,YAAY,GAAG,eAAe;AAAA,EACzC,CAAC,UAAU,qBAAqB,GAAG,eAAe;AAAA,EAClD,CAAC,UAAU,uBAAuB,GAChC,eAAe;AAAA,EACjB,CAAC,UAAU,cAAc,GAAG,eAAe;AAAA,EAC3C,CAAC,UAAU,gBAAgB,GAAG,eAAe;AAAA,EAC7C,CAAC,UAAU,gBAAgB,GAAG,eAAe;AAAA,EAC7C,CAAC,UAAU,cAAc,GAAG,eAAe;AAAA,EAC3C,CAAC,UAAU,oBAAoB,GAAG,eAAe;AAAA,EACjD,CAAC,UAAU,mBAAmB,GAAG,eAAe;AAAA,EAChD,CAAC,UAAU,iBAAiB,GAAG,eAAe;AAAA,EAC9C,CAAC,UAAU,mBAAmB,GAAG,eAAe;AAAA,EAChD,CAAC,UAAU,sBAAsB,GAC/B,eAAe;AAAA,EACjB,CAAC,UAAU,yBAAyB,GAClC,eAAe;AAAA,EACjB,CAAC,UAAU,uBAAuB,GAChC,eAAe;AAAA,EACjB,CAAC,UAAU,8BAA8B,GACvC,eAAe;AAAA,EACjB,CAAC,UAAU,aAAa,GAAG,eAAe;AAAA,EAC1C,CAAC,UAAU,WAAW,GAAG,eAAe;AAAA,EACxC,CAAC,UAAU,YAAY,GAAG,eAAe;AAAA,EACzC,CAAC,UAAU,qBAAqB,GAAG,eAAe;AAAA,EAClD,CAAC,UAAU,gBAAgB,GAAG,eAAe;AAAA,EAC7C,CAAC,UAAU,gBAAgB,GAAG,eAAe;AAC/C;AAMO,IAAM,qBAAqB,CAChC,YACA,MACA,WACW;AACX,QAAM,MAAM,0BAA0B,IAAI;AAC1C,SAAO,WAAW,EAAE,KAAK,MAAM;AACjC;AAsBO,IAAM,mBAAmB,CAC9B,eAA4D,CAAC,MAC9C;AACf,QAAM,qBAAqB,EAAE,GAAG,qBAAqB,GAAG,aAAa;AAErE,SAAO;AAAA,IACL,EACE,KACA,QACQ;AACR,UAAI,OAAO,mBAAmB,GAAG,KAAK;AAGtC,UAAI,QAAQ;AACV,mBAAW,CAAC,UAAU,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACtD,iBAAO,KAAK;AAAA,YACV,IAAI,OAAO,SAAS,QAAQ,UAAU,GAAG;AAAA,YACzC,OAAO,KAAK;AAAA,UACd;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAKO,IAAM,oBAAgC,iBAAiB;;;ACpNvD,IAAM,KAAK,CAAI,WAAqB,EAAE,KAAK,MAAM,MAAM;AACvD,IAAM,MAAM,CAAC,WAAwB,EAAE,KAAK,OAAO,MAAM;AAEzD,IAAM,OAAO,CAAI,WACtB,OAAO,QAAQ;AACV,IAAM,QAAQ,CAAI,WACvB,OAAO,QAAQ;AAEV,IAAM,SAAS,CAAI,WAA2B;AACnD,MAAI,OAAO,QAAQ,OAAO;AACxB,UAAM,IAAI,MAAM,OAAO,KAAK;AAAA,EAC9B;AACA,SAAO,OAAO;AAChB;;;ACNO,IAAM,uBACX,CACE,QACA,YACA,YAEF,CAAC,YAAkC;AACjC,QAAM,EAAE,MAAM,WAAW,IAAI;AAC7B,SAAO,KAAK,+BAA+B,KAAK,EAAE,EAAE;AACpD,SAAO,KAAK,gBAAgB,UAAU,EAAE;AAExC,MAAI,CAAC,mBAAmB,IAAI,GAAG;AAC7B,WAAO;AAAA,MACL,2DAA2D,KAAK,WAAW,IAAI;AAAA,IACjF;AACA,UAAM,IAAI;AAAA,MACR,mBAAmB,YAAY,UAAU,YAAY;AAAA,MACrD,EAAE,UAAU,QAAQ,QAAQ,KAAK,WAAW,MAAM,QAAQ,KAAK,GAAG;AAAA,IACpE;AAAA,EACF;AAEA,MAAI,KAAK,WAAW,SAAS,WAAW;AACtC,WAAO;AAAA,MACL,4CAA4C,KAAK,WAAW,IAAI;AAAA,IAClE;AACA,UAAM,IAAI;AAAA,MACR,mBAAmB,YAAY,UAAU,YAAY;AAAA,MACrD,EAAE,UAAU,WAAW,QAAQ,KAAK,WAAW,MAAM,QAAQ,KAAK,GAAG;AAAA,IACvE;AAAA,EACF;AAEA,QAAM,SAAS,QAAQ,MAAM,UAAU;AAEvC,MAAI,MAAM,MAAM,GAAG;AACjB,WAAO,MAAM,6BAA6B,OAAO,KAAK,EAAE;AACxD,UAAM,OAAO,OAAO;AACpB,UAAM,IAAI,mBAAmB,mBAAmB,YAAY,IAAI,GAAG,MAAM;AAAA,MACvE,QAAQ,KAAK;AAAA,MACb,YAAY,QAAQ;AAAA,IACtB,CAAC;AAAA,EACH;AAEA,SAAO,KAAK,8BAA8B,KAAK,EAAE,EAAE;AACnD,SAAO,OAAO;AAChB;;;AC5CK,IAAM,oBACX,CACE,QACA,YACA,YAEF,CAAC,YAA+B;AAC9B,QAAM,EAAE,MAAM,QAAQ,IAAI;AAE1B,SAAO,KAAK,2BAA2B,KAAK,EAAE,EAAE;AAEhD,MAAI,CAAC,mBAAmB,IAAI,GAAG;AAC7B,WAAO;AAAA,MACL,2DAA2D,KAAK,WAAW,IAAI;AAAA,IACjF;AACA,UAAM,IAAI;AAAA,MACR,mBAAmB,YAAY,UAAU,YAAY;AAAA,MACrD,EAAE,UAAU,QAAQ,QAAQ,KAAK,WAAW,MAAM,QAAQ,KAAK,GAAG;AAAA,IACpE;AAAA,EACF;AAEA,MAAI,KAAK,WAAW,SAAS,cAAc;AACzC,WAAO;AAAA,MACL,+CAA+C,KAAK,WAAW,IAAI;AAAA,IACrE;AACA,UAAM,IAAI;AAAA,MACR,mBAAmB,YAAY,UAAU,YAAY;AAAA,MACrD;AAAA,QACE,UAAU;AAAA,QACV,QAAQ,KAAK,WAAW;AAAA,QACxB,QAAQ,KAAK;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,QAAQ,MAAM,OAAO;AAEpC,MAAI,MAAM,MAAM,GAAG;AACjB,WAAO,MAAM,yBAAyB,OAAO,KAAK,EAAE;AACpD,UAAM,OAAO,OAAO;AACpB,UAAM,IAAI,mBAAmB,mBAAmB,YAAY,IAAI,GAAG,MAAM;AAAA,MACvE,QAAQ,KAAK;AAAA,MACb,SAAS,QAAQ;AAAA,IACnB,CAAC;AAAA,EACH;AAEA,SAAO,KAAK,0BAA0B,KAAK,EAAE,EAAE;AAC/C,SAAO,OAAO;AAChB;;;AC1DK,IAAM,wBACX,CACE,QACA,YACA,YAEF,CAAC,YAAY;AACX,QAAM,EAAE,QAAQ,IAAI;AACpB,SAAO,KAAK,+BAA+B;AAC3C,QAAM,SAAS,QAAQ,OAAO;AAE9B,MAAI,MAAM,MAAM,GAAG;AACjB,WAAO,MAAM,4BAA4B,OAAO,KAAK,EAAE;AACvD,UAAM,IAAI,MAAM,OAAO,KAAK;AAAA,EAC9B;AAEA,SAAO,KAAK,qBAAqB,OAAO,KAAK,EAAE;AAC/C,SAAO,OAAO;AAChB;;;ACXK,IAAM,wBAAwB,CACnC,QACA,YACA,YAC0B;AAC1B,SAAO,CAAC,YAAY;AAClB,WAAO,KAAK,sBAAsB,QAAQ,OAAO,MAAM,gBAAgB;AACvE,UAAM,WAAW;AAAA,MACf,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AACA,WAAO,KAAK,qBAAqB,QAAQ,EAAE;AAC3C,WAAO;AAAA,EACT;AACF;;;ACZO,IAAM,sBACX,CACE,QACA,YACA,YAEF,CAAC,YAAiC;AAChC,QAAM,EAAE,MAAM,QAAQ,WAAW,IAAI;AACrC,SAAO;AAAA,IACL,oBAAoB,UAAU,cAAc,MAAM,aAAa,KAAK,EAAE;AAAA,EACxE;AAEA,MAAI,CAAC,qBAAqB,IAAI,GAAG;AAC/B,WAAO;AAAA,MACL,6DAA6D,KAAK,WAAW,IAAI;AAAA,IACnF;AACA,UAAM,IAAI;AAAA,MACR,mBAAmB,YAAY,UAAU,YAAY;AAAA,MACrD,EAAE,UAAU,UAAU,QAAQ,KAAK,WAAW,MAAM,QAAQ,KAAK,GAAG;AAAA,IACtE;AAAA,EACF;AAEA,MAAI,KAAK,WAAW,eAAe,cAAc;AAC/C,WAAO;AAAA,MACL,iDAAiD,KAAK,WAAW,UAAU;AAAA,IAC7E;AACA,UAAM,IAAI;AAAA,MACR,mBAAmB,YAAY,UAAU,YAAY;AAAA,MACrD;AAAA,QACE,UAAU;AAAA,QACV,QAAQ,KAAK,WAAW;AAAA,QACxB,QAAQ,KAAK;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,QAAQ,MAAM,QAAQ,UAAU;AAE/C,MAAI,MAAM,MAAM,GAAG;AACjB,WAAO,MAAM,0BAA0B,OAAO,KAAK,EAAE;AACrD,UAAM,OAAO,OAAO;AACpB,UAAM,IAAI;AAAA,MACR,mBAAmB,YAAY,IAAI;AAAA,MACnC;AAAA,MACA;AAAA,QACE,QAAQ,KAAK;AAAA,QACb,QAAQ,QAAQ;AAAA,QAChB,YAAY,QAAQ;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,kBAAkB,UAAU,cAAc,MAAM,aAAa,KAAK,EAAE;AAAA,EACtE;AACA,SAAO,OAAO;AAChB;;;AC7DK,IAAM,oBACX,CACE,QACA,YACA,YAEF,CAAC,YAA+B;AAC9B,SAAO,KAAK,4BAA4B,QAAQ,IAAI,EAAE;AACtD,QAAM,SAAS,QAAQ,QAAQ,MAAM,QAAQ,IAAI;AAEjD,MAAI,MAAM,MAAM,GAAG;AACjB,WAAO,MAAM,wBAAwB,OAAO,KAAK,EAAE;AACnD,UAAM,OAAO,OAAO;AACpB,UAAM,IAAI,mBAAmB,mBAAmB,YAAY,IAAI,GAAG,MAAM;AAAA,MACvE,MAAM,QAAQ;AAAA,IAChB,CAAC;AAAA,EACH;AAEA,SAAO,KAAK,iBAAiB,OAAO,MAAM,EAAE,EAAE;AAC9C,SAAO,OAAO;AAChB;;;ACfK,IAAM,uBACX,CACE,QACA,YACA,YAEF,CAAC,YAAkC;AACjC,QAAM,EAAE,MAAM,OAAO,IAAI;AACzB,SAAO,KAAK,+BAA+B,MAAM,aAAa,KAAK,EAAE,EAAE;AAEvE,MAAI,CAAC,qBAAqB,IAAI,GAAG;AAC/B,WAAO;AAAA,MACL,6DAA6D,KAAK,WAAW,IAAI;AAAA,IACnF;AACA,UAAM,IAAI;AAAA,MACR,mBAAmB,YAAY,UAAU,YAAY;AAAA,MACrD,EAAE,UAAU,UAAU,QAAQ,KAAK,WAAW,MAAM,QAAQ,KAAK,GAAG;AAAA,IACtE;AAAA,EACF;AAEA,MAAI,KAAK,WAAW,eAAe,eAAe;AAChD,WAAO;AAAA,MACL,kDAAkD,KAAK,WAAW,UAAU;AAAA,IAC9E;AACA,UAAM,IAAI;AAAA,MACR,mBAAmB,YAAY,UAAU,YAAY;AAAA,MACrD;AAAA,QACE,UAAU;AAAA,QACV,QAAQ,KAAK,WAAW;AAAA,QACxB,QAAQ,KAAK;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,QAAQ,MAAM,MAAM;AAEnC,MAAI,MAAM,MAAM,GAAG;AACjB,WAAO,MAAM,4BAA4B,OAAO,KAAK,EAAE;AACvD,UAAM,OAAO,OAAO;AACpB,UAAM,IAAI;AAAA,MACR,mBAAmB,YAAY,IAAI;AAAA,MACnC;AAAA,MACA,EAAE,QAAQ,KAAK,IAAI,QAAQ,QAAQ,OAAO;AAAA,IAC5C;AAAA,EACF;AAEA,MAAI,qBAAqB,OAAO,KAAK,GAAG;AACtC,WAAO,KAAK,qBAAqB,MAAM,aAAa,KAAK,EAAE,EAAE;AAC7D,WAAO,OAAO;AAAA,EAChB;AAEA,SAAO,KAAK,qBAAqB,MAAM,aAAa,KAAK,EAAE,EAAE;AAC7D,SAAO,OAAO;AAChB;;;AC5DK,IAAM,0BAA0B,CACrC,QACA,YACA,YAC4B;AAC5B,SAAO,CAAC,YAAY;AAClB,WAAO;AAAA,MACL,mCAAmC,QAAQ,MAAM,MAAM;AAAA,IACzD;AACA,UAAM,UAAU,QAAQ,QAAQ,KAAK;AACrC,WAAO,KAAK,4BAA4B;AACxC,WAAO;AAAA,EACT;AACF;;;ACVO,IAAM,uBACX,CACE,QACA,YACA,YAEF,CAAC,YAAkC;AACjC,QAAM,EAAE,MAAM,QAAQ,IAAI;AAC1B,SAAO;AAAA,IACL,iCAAiC,IAAI,iBAAiB,OAAO;AAAA,EAC/D;AACA,QAAM,SAAS,QAAQ,MAAM,OAAO;AAEpC,MAAI,MAAM,MAAM,GAAG;AACjB,WAAO,MAAM,8BAA8B,OAAO,KAAK,EAAE;AACzD,UAAM,OAAO,OAAO;AACpB,UAAM,IAAI,cAAc,mBAAmB,YAAY,IAAI,GAAG,MAAM;AAAA,MAClE,MAAM,QAAQ;AAAA,IAChB,CAAC;AAAA,EACH;AAEA,SAAO,KAAK,0BAA0B,OAAO,KAAK,EAAE;AACpD,SAAO,OAAO;AAChB;;;ACvBK,IAAM,kBACX,CACE,QACA,YACA,YAEF,CAAC,aAA8B;AAC7B,SAAO,KAAK,eAAe;AAC3B,QAAM,SAAS,QAAQ;AAEvB,MAAI,MAAM,MAAM,GAAG;AACjB,WAAO,MAAM,wBAAwB,OAAO,KAAK,EAAE;AACnD,UAAM,OAAO,OAAO;AACpB,UAAM,IAAI,cAAc,mBAAmB,YAAY,IAAI,GAAG,IAAI;AAAA,EACpE;AAEA,SAAO,KAAK,oBAAoB,OAAO,KAAK,EAAE;AAC9C,SAAO,OAAO;AAChB;;;ACXK,IAAM,mBACX,CACE,QACA,YACA,aAKF,CAAC,YAA8B;AAC7B,QAAM,EAAE,kBAAAE,mBAAkB,uBAAAC,uBAAsB,IAAI;AACpD,QAAM,EAAE,KAAK,IAAI;AACjB,SAAO,KAAK,4BAA4B,KAAK,EAAE,EAAE;AAEjD,MAAI,CAAC,mBAAmB,IAAI,GAAG;AAC7B,WAAO;AAAA,MACL,2DAA2D,KAAK,WAAW,IAAI;AAAA,IACjF;AACA,UAAM,IAAI;AAAA,MACR,mBAAmB,YAAY,UAAU,YAAY;AAAA,MACrD,EAAE,UAAU,QAAQ,QAAQ,KAAK,WAAW,MAAM,QAAQ,KAAK,GAAG;AAAA,IACpE;AAAA,EACF;AAEA,MAAI,KAAK,WAAW,SAAS,UAAU;AACrC,WAAO;AAAA,MACL,2CAA2C,KAAK,WAAW,IAAI;AAAA,IACjE;AACA,UAAM,IAAI;AAAA,MACR,mBAAmB,YAAY,UAAU,YAAY;AAAA,MACrD,EAAE,UAAU,UAAU,QAAQ,KAAK,WAAW,MAAM,QAAQ,KAAK,GAAG;AAAA,IACtE;AAAA,EACF;AAEA,QAAM,EAAE,QAAQ,IAAI;AAEpB,QAAM,cAA6B,QAAQ,IAAI,CAAC,WAAW;AACzD,UAAM,EAAE,QAAQ,IAAI;AACpB,UAAMC,UAASD,uBAAsB,OAAO;AAE5C,QAAI,MAAMC,OAAM,GAAG;AACjB,aAAO,MAAM,iCAAiCA,QAAO,KAAK,EAAE;AAC5D,YAAM,OAAOA,QAAO;AACpB,YAAM,IAAI;AAAA,QACR,mBAAmB,YAAY,IAAI;AAAA,QACnC;AAAA,QACA;AAAA,UACE,QAAQ,KAAK;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,UAAU,OAAO;AAAA,MACjB,YAAY,OAAO;AAAA,MACnB,SAAS;AAAA,QACP,GAAGA,QAAO;AAAA,MACZ;AAAA,IACF;AAAA,EACF,CAAC;AAED,QAAM,SAASF,kBAAiB,MAAM,WAAW;AAEjD,MAAI,MAAM,MAAM,GAAG;AACjB,WAAO,MAAM,yBAAyB,OAAO,KAAK,EAAE;AACpD,UAAM,OAAO,OAAO;AACpB,UAAM,IAAI,cAAc,mBAAmB,YAAY,IAAI,GAAG,MAAM;AAAA,MAClE,QAAQ,KAAK;AAAA,IACf,CAAC;AAAA,EACH;AAEA,SAAO,KAAK,8BAA8B,KAAK,EAAE,EAAE;AACnD,SAAO,OAAO;AAChB;;;AC5EK,IAAM,4BAA4B,CACvC,QACA,YACA,YAC8B;AAC9B,SAAO,CAAC,YAAY;AAClB,WAAO;AAAA,MACL,wCAAwC,QAAQ,OAAO,MAAM;AAAA,IAC/D;AACA,UAAM,aAAa;AAAA,MACjB,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AACA,WAAO,KAAK,SAAS,WAAW,MAAM,mBAAmB;AACzD,WAAO;AAAA,EACT;AACF;;;ACjBO,IAAM,qBACX,CACE,QACA,YACA,YAEF,CAAC,YAAgC;AAC/B,QAAM,EAAE,MAAM,QAAQ,UAAU,SAAS,IAAI;AAC7C,SAAO;AAAA,IACL,mBAAmB,MAAM,iBAAiB,KAAK;AAAA,MAC7C;AAAA,IACF,CAAC,mBAAmB,QAAQ,aAAa,KAAK,EAAE;AAAA,EAClD;AAEA,MAAI,CAAC,qBAAqB,IAAI,GAAG;AAC/B,WAAO;AAAA,MACL,6DAA6D,KAAK,WAAW,IAAI;AAAA,IACnF;AACA,UAAM,IAAI;AAAA,MACR,mBAAmB,YAAY,UAAU,YAAY;AAAA,MACrD,EAAE,UAAU,UAAU,QAAQ,KAAK,WAAW,MAAM,QAAQ,KAAK,GAAG;AAAA,IACtE;AAAA,EACF;AAEA,MAAI,KAAK,WAAW,eAAe,eAAe;AAChD,WAAO;AAAA,MACL,kDAAkD,KAAK,WAAW,UAAU;AAAA,IAC9E;AACA,UAAM,IAAI;AAAA,MACR,mBAAmB,YAAY,UAAU,YAAY;AAAA,MACrD;AAAA,QACE,UAAU;AAAA,QACV,QAAQ,KAAK,WAAW;AAAA,QACxB,QAAQ,KAAK;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,QAAQ,MAAM,QAAQ,UAAU,QAAQ;AAEvD,MAAI,MAAM,MAAM,GAAG;AACjB,WAAO,MAAM,yBAAyB,OAAO,KAAK,EAAE;AACpD,UAAM,OAAO,OAAO;AACpB,UAAM,IAAI;AAAA,MACR,mBAAmB,YAAY,IAAI;AAAA,MACnC;AAAA,MACA;AAAA,QACE,QAAQ,KAAK;AAAA,QACb,QAAQ,QAAQ;AAAA,QAChB,UAAU,QAAQ;AAAA,QAClB,UAAU,QAAQ;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,qBAAqB,OAAO,KAAK,GAAG;AACtC,WAAO;AAAA,MACL,kBAAkB,MAAM,iBAAiB,KAAK;AAAA,QAC5C;AAAA,MACF,CAAC,mBAAmB,QAAQ,aAAa,KAAK,EAAE;AAAA,IAClD;AACA,WAAO,OAAO;AAAA,EAChB;AAEA,SAAO;AAAA,IACL,kBAAkB,MAAM,iBAAiB,KAAK;AAAA,MAC5C;AAAA,IACF,CAAC,mBAAmB,QAAQ,aAAa,KAAK,EAAE;AAAA,EAClD;AACA,SAAO,OAAO;AAChB;;;ACnFF,IAAM,wBAAwB;AAkBvB,IAAM,gBAAgB,CAAC,SAA4B;AACxD,QAAM,aAA6B;AAAA,IACjC,SAAS;AAAA,IACT,MAAM;AAAA,IACN,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,EACpC;AACA,SAAO,KAAK,UAAU,UAAU;AAClC;AASO,IAAM,kBAAkB,CAAC,SAAoC;AAClE,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,IAAI;AAG9B,QAAI,CAAC,OAAO,WAAW,CAAC,OAAO,MAAM;AACnC,aAAO,IAAI,gCAAgC;AAAA,IAC7C;AAGA,QAAI,OAAO,UAAU,uBAAuB;AAC1C,aAAO;AAAA,QACL,sCAAsC,OAAO,OAAO,sBAAsB,qBAAqB;AAAA,MACjG;AAAA,IACF;AAGA,UAAM,OAAO,OAAO;AACpB,QAAI,CAAC,KAAK,MAAM,CAAC,KAAK,WAAW,CAAC,KAAK,SAAS,CAAC,KAAK,YAAY;AAChE,aAAO,IAAI,8BAA8B;AAAA,IAC3C;AAEA,WAAO,GAAG,IAAI;AAAA,EAChB,SAAS,OAAO;AACd,WAAO,IAAI,8BAA+B,MAAgB,OAAO,EAAE;AAAA,EACrE;AACF;AAuBO,IAAM,kBAAkB,CAAC,SAAmC;AACjE,SAAO;AAAA,IACL,YAAY,cAAc,IAAI;AAAA,IAC9B,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,QAAQ,KAAK;AAAA,IACb,MAAM,KAAK;AAAA,EACb;AACF;AAQO,IAAM,uBAAuB,CAClC,cACsB;AACtB,SAAO,gBAAgB,UAAU,UAAU;AAC7C;;;ACpFO,IAAM,uBAAuB,CAClC,QACA,gBACyB;AACzB,SAAO,CAAC,YAAY;AAClB,WAAO,KAAK,qBAAqB,QAAQ,KAAK,EAAE,EAAE;AAClD,UAAM,aAAa,cAAc,QAAQ,IAAI;AAC7C,WAAO,KAAK,8BAA8B;AAC1C,WAAO;AAAA,EACT;AACF;AAKO,IAAM,yBAAyB,CACpC,QACA,eAC2B;AAC3B,SAAO,CAAC,YAAY;AAClB,WAAO,KAAK,8BAA8B;AAC1C,UAAM,SAAS,gBAAgB,QAAQ,IAAI;AAE3C,QAAI,MAAM,MAAM,GAAG;AACjB,aAAO,MAAM,+BAA+B,OAAO,KAAK,EAAE;AAC1D,YAAM,OAAO,OAAO;AACpB,YAAM,IAAI,mBAAmB,mBAAmB,YAAY,IAAI,GAAG,IAAI;AAAA,IACzE;AAEA,UAAM,OAAO,OAAO,MAAM;AAC1B,WAAO,KAAK,mCAAmC,KAAK,EAAE,EAAE;AACxD,WAAO;AAAA,EACT;AACF;;;ACtCO,IAAM,mBACX,CACE,QACA,YACA,YAEF,CAAC,YAA8B;AAC7B,QAAM,EAAE,KAAK,IAAI;AACjB,SAAO,KAAK,kBAAkB,KAAK,EAAE,EAAE;AAEvC,MAAI,CAAC,mBAAmB,IAAI,GAAG;AAC7B,WAAO;AAAA,MACL,2DAA2D,KAAK,WAAW,IAAI;AAAA,IACjF;AACA,UAAM,IAAI;AAAA,MACR,mBAAmB,YAAY,UAAU,YAAY;AAAA,MACrD,EAAE,UAAU,QAAQ,QAAQ,KAAK,WAAW,MAAM,QAAQ,KAAK,GAAG;AAAA,IACpE;AAAA,EACF;AAEA,MACE,KAAK,WAAW,SAAS,WACzB,KAAK,WAAW,SAAS,WACzB;AACA,WAAO;AAAA,MACL,0DAA0D,KAAK,WAAW,IAAI;AAAA,IAChF;AACA,UAAM,IAAI;AAAA,MACR,mBAAmB,YAAY,UAAU,YAAY;AAAA,MACrD;AAAA,QACE,UAAU;AAAA,QACV,QAAQ,KAAK,WAAW;AAAA,QACxB,QAAQ,KAAK;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,QAAQ,IAAI;AAE3B,MAAI,MAAM,MAAM,GAAG;AACjB,WAAO,MAAM,wBAAwB,OAAO,KAAK,EAAE;AACnD,UAAM,OAAO,OAAO;AACpB,UAAM,IAAI,mBAAmB,mBAAmB,YAAY,IAAI,GAAG,MAAM;AAAA,MACvE,QAAQ,KAAK;AAAA,IACf,CAAC;AAAA,EACH;AAEA,SAAO,KAAK,iBAAiB,KAAK,EAAE,EAAE;AACtC,SAAO,OAAO;AAChB;;;ACnCK,IAAM,WAAW;AAKjB,IAAM,mBAAmB;;;AClCzB,IAAM,SAAS;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACsBO,IAAM,gBAAgB;AAAA;AAAA,EAE3B,aAAa;AAAA;AAAA,EAEb,YAAY;AAAA;AAAA,EAEZ,MAAM;AACR;;;ACrCO,IAAM,0BAA0B,CACrC,YACA,MACA,oBACwB;AACxB,QAAM,sBAAsB,WAAW,OAAO,CAAC,SAAS;AACtD,WACE,KAAK,KAAK,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI,EAAE,SAAS,MACjD,CAAC,KAAK,gBAAgB,KAAK,iBAAiB;AAAA,EAEjD,CAAC;AAED,MAAI,oBAAoB,WAAW,GAAG;AACpC,WAAO,IAAI,UAAU,qBAAqB;AAAA,EAC5C;AAEA,SAAO,GAAG,mBAAmB;AAC/B;AAEO,IAAM,cAAc,CACzB,MACA,eACsB;AACtB,QAAM,YAAY,WAAW,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AAExD,MAAI,CAAC,WAAW;AACd,WAAO,IAAI,UAAU,qBAAqB;AAAA,EAC5C;AAEA,SAAO,GAAG,SAAS;AACrB;;;AChCA,IAAM,WAAW,CAAC,QAAwB;AACxC,MAAI,OAAO;AACX,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,YAAQ,IAAI,WAAW,CAAC;AACxB,WAAO,KAAK,KAAK,MAAM,QAAQ;AAAA,EACjC;AACA,SAAO,SAAS;AAClB;AAEA,IAAM,aAAa,CAAC,SAAiC;AACnD,MAAI,QAAQ;AACZ,SAAO,MAAM;AACX,aAAS;AACT,YAAS,QAAQ,aAAc;AAC/B,QAAI,IAAI,KAAK,KAAK,QAAS,UAAU,IAAK,IAAI,KAAK;AACnD,QAAK,IAAI,KAAK,KAAK,IAAK,MAAM,GAAI,KAAK,CAAC,IAAK;AAC7C,aAAS,IAAK,MAAM,QAAS,KAAK;AAAA,EACpC;AACF;AAEO,IAAM,sBAAsB,CACjC,MACA,SACkB;AAClB,QAAM,cAAc,SAAS,GAAG,IAAI,IAAI,IAAI,EAAE;AAC9C,QAAM,SAAS,WAAW,WAAW;AAErC,SAAO,CAAI,UAAoB;AAC7B,UAAM,SAAS,CAAC,GAAG,KAAK;AACxB,aAAS,IAAI,OAAO,SAAS,GAAG,IAAI,GAAG,KAAK;AAC1C,YAAM,IAAI,KAAK,MAAM,OAAO,KAAK,IAAI,EAAE;AACvC,OAAC,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAQ,OAAO,CAAC,CAAM;AAAA,IAC1D;AACA,WAAO;AAAA,EACT;AACF;;;ACnBO,IAAM,uBACX,CAAC,SAKD,CAAC,MAAM,UAAU;AACf,QAAM,EAAE,gBAAgB,oBAAoB,eAAAG,eAAc,IAAI;AAC9D,QAAM,sBAAsB,eAAe,YAAY;AAEvD,QAAM,gBAA6B,CAAC;AAEpC,aAAW,QAAQ,OAAO;AACxB,UAAM,SAAS,YAAY,MAAM,mBAAmB;AAEpD,QAAI,MAAM,MAAM,GAAG;AACjB,aAAO;AAAA,IACT;AAEA,kBAAc,KAAK,OAAO,KAAK;AAAA,EACjC;AAGA,MAAI,eAAe,KAAK,MAAM;AAC9B,MAAI,kBAAkB,KAAK;AAC3B,QAAM,gBAAgB,cAAc,KAAK,CAAC,MAAM,EAAE,SAAS,iBAAiB;AAC5E,MAAI,eAAe;AACjB,mBAAe;AAAA,MACb,GAAG;AAAA,MACH,aAAa;AAAA,MACb,UAAU;AAAA,MACV,gBAAgB;AAAA,IAClB;AAEA,UAAM,cAAc,mBAAmB,WAAW,KAAK,IAAI;AAC3D,QAAI,aAAa;AACf,YAAM,UAAU,KAAK,OACjB,oBAAoB,KAAK,MAAM,aAAa,IAC5CA;AACJ,wBAAkB,QAAQ,WAAW;AAAA,IACvC;AAAA,EACF;AAEA,QAAM,eAAe;AAAA,IACnB,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAEA,QAAM,OAAiB;AAAA,IACrB,MAAM;AAAA,IACN,MAAM,UAAU;AAAA,EAClB;AAEA,QAAM,cAAgC;AAAA,IACpC,GAAG;AAAA,IACH,UAAU;AAAA,IACV,OAAO;AAAA,IACP,YAAY;AAAA,EACd;AAEA,SAAO,GAAG,WAAW;AACvB;;;ACtEF,IAAM,WAAW,CAAC,WAAkC;AAClD,SAAO,OAAO,SAAS,MAAM;AAC/B;AAEO,IAAM,aAAa,CACxB,QACA,SAAgB,MACK;AACrB,MAAI,SAAS,MAAM,GAAG;AACpB,WAAO,EAAE,MAAM,QAAQ,OAAO;AAAA,EAChC;AACA,SAAO,EAAE,MAAM,QAAQ,QAAQ,EAAE;AACnC;;;ACPO,IAAM,qBAAqB,MAAe;AAC/C,QAAM,YAAY,WAAW,OAAO;AACpC,SAAO,MAAM;AAAA,IAAK,EAAC,QAAQ,SAAQ;AAAA,IAAG,MAClC,MAAM,KAAK,EAAC,QAAQ,SAAQ,GAAG,MAAM,SAAS;AAAA,EAClD;AACF;AAEO,IAAM,cAAc,CAAC,YAA8B;AACxD,QAAM,SAAS,WAAW,QAAQ;AAClC,QAAM,aAAa,gBAAgB,OAAO;AAC1C,aAAW,CAAC,EAAG,CAAC,IAAI;AACpB,SAAO;AACT;AAEO,IAAM,YAAY,CACvB,SACA,UACA,SACY;AACZ,QAAM,aAAa,gBAAgB,OAAO;AAC1C,aAAW,SAAS,CAAC,EAAG,SAAS,CAAC,IAAI;AACtC,SAAO;AACT;AAEO,IAAM,UAAU,CACrB,SACA,aAC6B;AAC7B,QAAM,OAAO,QAAQ,SAAS,CAAC,IAAI,SAAS,CAAC;AAC7C,MAAI,CAAC,MAAM;AACT,WAAO,IAAI,UAAU,uBAAuB;AAAA,EAC9C;AACA,SAAO,GAAG,IAAI;AAChB;AAEO,IAAM,0BAA0B,CACrC,UACA,UACA,WAC6E;AAC7E,MAAI;AAIJ,MAAI;AAKJ,UAAQ,UAAU;AAAA,IAChB,KAAK;AACH,kBAAY;AAAA,QACV,MAAM,OAAO;AAAA,QACb,UAAU;AAAA,UACR,GAAG,SAAS;AAAA,UACZ,GAAG,SAAS;AAAA,QACd;AAAA,MACF;AACA,mBAAa;AAAA,QACX,MAAM,OAAO;AAAA,QACb,UAAU;AAAA,UACR,GAAG,SAAS,IAAI;AAAA,UAChB,GAAG,SAAS;AAAA,QACd;AAAA,MACF;AACA;AAAA,IACF,KAAK;AACH,kBAAY;AAAA,QACV,MAAM,OAAO;AAAA,QACb,UAAU;AAAA,UACR,GAAG,SAAS;AAAA,UACZ,GAAG,SAAS;AAAA,QACd;AAAA,MACF;AACA,mBAAa;AAAA,QACX,MAAM,OAAO;AAAA,QACb,UAAU;AAAA,UACR,GAAG,SAAS;AAAA,UACZ,GAAG,SAAS,IAAI;AAAA,QAClB;AAAA,MACF;AACA;AAAA,IACF,KAAK;AACH,kBAAY;AAAA,QACV,MAAM,OAAO;AAAA,QACb,UAAU;AAAA,UACR,GAAG,SAAS;AAAA,UACZ,GAAG,SAAS;AAAA,QACd;AAAA,MACF;AACA,mBAAa;AAAA,QACX,MAAM,OAAO;AAAA,QACb,UAAU;AAAA,UACR,GAAG,SAAS,IAAI;AAAA,UAChB,GAAG,SAAS;AAAA,QACd;AAAA,MACF;AACA;AAAA,IACF,KAAK;AACH,kBAAY;AAAA,QACV,MAAM,OAAO;AAAA,QACb,UAAU;AAAA,UACR,GAAG,SAAS;AAAA,UACZ,GAAG,SAAS;AAAA,QACd;AAAA,MACF;AACA,mBAAa;AAAA,QACX,MAAM,OAAO;AAAA,QACb,UAAU;AAAA,UACR,GAAG,SAAS;AAAA,UACZ,GAAG,SAAS,IAAI;AAAA,QAClB;AAAA,MACF;AACA;AAAA,EACJ;AAEA,SAAO,CAAC,WAAW,UAAU;AAC/B;AAEO,IAAM,cAAc,CACzB,SACA,UACA,UACA,QACA,iBAAyB,qBACL;AACpB,QAAM,CAAC,WAAW,UAAU,IAAI;AAAA,IAC9B;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,oBAAoB;AAAA,IACxB;AAAA,IACA,UAAU;AAAA,IACV,WAAW;AAAA,EACb;AACA,MAAI,MAAM,iBAAiB,GAAG;AAC5B,WAAO;AAAA,EACT;AAEA,MAAI,eAAe,SAAS,UAAU,UAAU,WAAW,UAAU,cAAc,GAAG;AACpF,WAAO,IAAI,UAAU,8BAA8B;AAAA,EACrD;AAEA,QAAM,gBAAgB;AAAA,IACpB;AAAA,IACA,UAAU;AAAA,IACV,WAAW;AAAA,EACb;AAEA,MAAI,cAAc,WAAW,GAAG;AAC9B,WAAO,IAAI,UAAU,sBAAsB;AAAA,EAC7C;AAEA,QAAM,wBAAwB,iBAAiB,eAAe;AAAA,IAC5D,UAAU;AAAA,IACV,WAAW;AAAA,EACb,CAAC;AAED,MAAI,CAAC,uBAAuB;AAC1B,WAAO,IAAI,UAAU,yBAAyB;AAAA,EAChD;AAEA,SAAO,GAAG,WAAW,SAAS,CAAC,WAAW,UAAU,CAAC,CAAC;AACxD;AAEA,IAAM,aAAa,CACjB,SACA,UACG;AACH,MAAI,aAAa,gBAAgB,OAAO;AACxC,aAAW,EAAE,MAAM,SAAS,KAAK,OAAO;AACtC,iBAAa,UAAU,YAAY,UAAU,IAAI;AAAA,EACnD;AACA,SAAO;AACT;AAEA,IAAM,cAAc,CAClB,SACA,eACA,mBACoB;AACpB,QAAM,YAAY,QAAQ,SAAS,aAAa;AAChD,QAAM,aAAa,QAAQ,SAAS,cAAc;AAElD,MAAI,MAAM,SAAS,GAAG;AACpB,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,UAAU,GAAG;AACrB,WAAO;AAAA,EACT;AAEA,MAAI,UAAU,MAAM,SAAS,WAAW,WAAW,MAAM,SAAS,SAAS;AACzE,WAAO,IAAI,UAAU,mBAAmB;AAAA,EAC1C;AAEA,SAAO,GAAG,IAAI;AAChB;AAEA,IAAM,aAAa,CACjB,SACA,eACA,mBACW;AACX,QAAM,UAAU;AAAA,IACd,EAAE,GAAG,IAAI,GAAG,EAAE;AAAA,IACd,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,IACb,EAAE,GAAG,GAAG,GAAG,GAAG;AAAA,IACd,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EACf;AAEA,QAAM,gBAAgB,CAAC,GAAW,MAC/B,MAAM,cAAc,KAAK,MAAM,cAAc,KAC7C,MAAM,eAAe,KAAK,MAAM,eAAe;AAElD,QAAM,gBAAwB,CAAC;AAE/B,aAAW,OAAO,CAAC,eAAe,cAAc,GAAG;AACjD,eAAW,UAAU,SAAS;AAC5B,YAAM,KAAK,IAAI,IAAI,OAAO;AAC1B,YAAM,KAAK,IAAI,IAAI,OAAO;AAC1B,UAAI,cAAc,IAAI,EAAE,EAAG;AAC3B,YAAM,OAAO,QAAQ,SAAS,EAAE,GAAG,IAAI,GAAG,GAAG,CAAC;AAC9C,UAAI,KAAK,IAAI,KAAK,KAAK,MAAM,SAAS,SAAS;AAC7C,sBAAc,KAAK,KAAK,KAAK;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,IAAM,mBAAmB,CACvB,eACA,UACY;AACZ,SAAO,cAAc,KAAK,CAAC,iBAAiB;AAC1C,WAAO,MAAM,KAAK,CAAC,SAAS;AAC1B,aAAO,KAAK,SAAS,aAAa,QAAQ,aAAa,SAAS;AAAA,IAClE,CAAC;AAAA,EACH,CAAC;AACH;AAEO,IAAM,wBAAwB,CAAC,YAA8B;AAElE,MAAI;AACJ,MAAI;AAEJ,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,IAAI,QAAQ,CAAC,EAAG,UAAU,CAAC,SAAS,KAAK,SAAS,QAAQ;AAChE,QAAI,MAAM,IAAI;AACZ,gBAAU;AACV,gBAAU;AACV;AAAA,IACF;AAAA,EACF;AAEA,MAAI,YAAY,UAAa,YAAY,QAAW;AAClD,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,eAAe,OAAO;AACnC,MAAI,CAAC,KAAM,QAAO;AAGlB,QAAM,WAAW,KAAK,OAAO,KAAK,QAAQ;AAC1C,QAAM,WAAW,KAAK,OAAO,KAAK,QAAQ;AAE1C,SAAO,YAAY,WAAW,YAAY;AAC5C;AAEO,IAAM,iBAAiB,CAC5B,YACsE;AACtE,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AAEX,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,aAAS,IAAI,GAAG,IAAI,QAAQ,CAAC,EAAG,QAAQ,KAAK;AAC3C,UAAI,QAAQ,CAAC,EAAG,CAAC,EAAG,SAAS,SAAS;AACpC,YAAI,IAAI,KAAM,QAAO;AACrB,YAAI,IAAI,KAAM,QAAO;AACrB,YAAI,IAAI,KAAM,QAAO;AACrB,YAAI,IAAI,KAAM,QAAO;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,SAAS,SAAU,QAAO;AAC9B,SAAO,EAAE,MAAM,MAAM,MAAM,KAAK;AAClC;AAEA,IAAM,iBAAiB,CACrB,SACA,eACA,gBACA,UAAkB,qBACN;AACZ,QAAM,OAAO,eAAe,OAAO;AAEnC,MAAI,OAAO,MAAM,QAAQ;AACzB,MAAI,OAAO,MAAM,QAAQ;AACzB,MAAI,OAAO,MAAM,QAAQ;AACzB,MAAI,OAAO,MAAM,QAAQ;AAEzB,aAAW,OAAO,CAAC,eAAe,cAAc,GAAG;AACjD,QAAI,IAAI,IAAI,KAAM,QAAO,IAAI;AAC7B,QAAI,IAAI,IAAI,KAAM,QAAO,IAAI;AAC7B,QAAI,IAAI,IAAI,KAAM,QAAO,IAAI;AAC7B,QAAI,IAAI,IAAI,KAAM,QAAO,IAAI;AAAA,EAC/B;AAEA,SAAQ,OAAO,OAAO,IAAK,WAAY,OAAO,OAAO,IAAK;AAC5D;AAEO,IAAM,gBAAgB,CAAC,YAA6B;AACzD,QAAM,aAAa,QAAQ,KAAK,EAAE,OAAO,CAAC,SAAS,KAAK,SAAS,OAAO;AAExE,UAAQ,WAAW,SAAS,KAAK;AACnC;AAEA,IAAM,kBAAkB,CAAC,YAA8B;AACrD,SAAO,QAAQ,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,UAAU,EAAE,GAAG,KAAK,EAAE,CAAC;AAChE;;;AChVA,IAAM,uBAAuB;AAEtB,IAAM,iBAAiB,CAAC,SAAiC;AAC9D,MAAI,CAAC,QAAQ,KAAK,KAAK,EAAE,SAAS,sBAAsB;AACtD,WAAO,IAAI,UAAU,mBAAmB;AAAA,EAC1C;AAEA,SAAO,GAAG,IAAI;AAChB;AAEO,IAAM,eAAe,CAC1B,YACA,IACA,SACA,QACmB;AACnB,QAAM,OAAO,eAAe,UAAU;AAEtC,MAAI,MAAM,IAAI,GAAG;AACf,WAAO;AAAA,EACT;AAEA,SAAO,GAAG;AAAA,IACR,MAAM,KAAK;AAAA,IACX;AAAA,IACA;AAAA,IACA,GAAI,OAAO,EAAE,IAAI;AAAA,EACnB,CAAC;AACH;;;ACVA,IAAM,uBAAuB,CAC3B,UACqD;AACrD,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,EAAE,MAAM,MAAM;AAAA,EACvB;AACA,SAAO,EAAE,MAAM,MAAM,MAAM,KAAK,MAAM,IAAI;AAC5C;AAEO,IAAM,oBACX,CAAC,SAKD,CAAC,MAAM,YAAY;AACjB,QAAM,EAAE,YAAAC,aAAY,eAAAC,gBAAe,eAAe,IAAI;AAEtD,MAAI,CAAC,WAAW,QAAQ,SAAS,KAAK,QAAQ,SAAS,GAAG;AACxD,WAAO,IAAI,UAAU,oBAAoB;AAAA,EAC3C;AAEA,QAAM,aAAsB,CAAC;AAE7B,aAAW,UAAU,SAAS;AAC5B,UAAM,EAAE,MAAM,IAAI,IAAI,qBAAqB,MAAM;AACjD,QAAI,UAAU,mBAAmB;AACjC,cAAU,YAAY,OAAO;AAC7B,QAAI,KAAKD,YAAW;AACpB,UAAM,YAAY,aAAa,MAAM,IAAI,SAAS,GAAG;AAErD,QAAI,MAAM,SAAS,GAAG;AACpB,aAAO;AAAA,IACT;AAEA,eAAW,KAAK,UAAU,KAAK;AAAA,EACjC;AAGA,QAAM,QAAQ,eAAe,OAAO;AACpC,QAAM,aAAa,MAAM,MAAM,WAAW,MAAM;AAEhD,MAAI,CAAC,YAAY;AACf,WAAO,IAAI,UAAU,qBAAqB;AAAA,EAC5C;AAGA,QAAM,WAAW,KAAK;AACtB,QAAM,EAAE,YAAY,IAAI;AACxB,QAAM,UAAU,KAAK,OACjB,oBAAoB,KAAK,MAAM,UAAU,IACzCC;AACJ,QAAM,mBAAmB,QAAQ,QAAQ;AACzC,QAAM,kBAAkB,iBAAiB,MAAM,GAAG,WAAW;AAC7D,QAAM,OAAiB;AAAA,IACrB,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAEA,QAAM,cAAgC;AAAA,IACpC,GAAG;AAAA,IACH,SAAS;AAAA,IACT,UAAU;AAAA,IACV,OAAO;AAAA,MACL,GAAG,KAAK;AAAA,MACR,OAAO;AAAA,IACT;AAAA,IACA,YAAY;AAAA,EACd;AAEA,SAAO,GAAG,WAAW;AACvB;;;ACpFK,IAAM,wBAA+C,CAAC,YAAY;AACvE,QAAM,OAAO,QAAQ;AACrB,QAAM,OAAO,QAAQ,CAAC,EAAG;AACzB,QAAM,UAAuB,QAAQ,IAAI,CAAC,QAAQ,IAAI,IAAI,MAAM,KAAK,CAAC;AACtE,QAAM,aAAyB,CAAC;AAEhC,QAAM,aAAa;AAAA,IACjB,CAAC,IAAI,CAAC;AAAA,IACN,CAAC,GAAG,CAAC;AAAA,IACL,CAAC,GAAG,EAAE;AAAA,IACN,CAAC,GAAG,CAAC;AAAA,EACP;AAEA,WAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC7B,aAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC7B,YAAM,OAAO,QAAQ,CAAC,EAAG,CAAC;AAC1B,UAAI,QAAQ,CAAC,EAAG,CAAC,KAAK,KAAK,SAAS,WAAW,KAAK,SAAS,UAAU;AACrE;AAAA,MACF;AAGA,YAAM,OAAO,KAAK;AAClB,UAAI,OAAO;AACX,UAAI,SAAS;AACb,YAAM,QAA4B,CAAC,CAAC,GAAG,CAAC,CAAC;AACzC,cAAQ,CAAC,EAAG,CAAC,IAAI;AAEjB,aAAO,MAAM,SAAS,GAAG;AACvB,cAAM,CAAC,IAAI,EAAE,IAAI,MAAM,IAAI;AAC3B,cAAM,UAAU,QAAQ,EAAE,EAAG,EAAE;AAC/B;AACA,kBAAU,QAAQ;AAElB,mBAAW,CAAC,IAAI,EAAE,KAAK,YAAY;AACjC,gBAAM,KAAK,KAAM;AACjB,gBAAM,KAAK,KAAM;AACjB,cACE,MAAM,KACN,MAAM,KACN,KAAK,QACL,KAAK,QACL,CAAC,QAAQ,EAAE,EAAG,EAAE,KAChB,QAAQ,EAAE,EAAG,EAAE,EAAG,SAAS,MAC3B;AACA,oBAAQ,EAAE,EAAG,EAAE,IAAI;AACnB,kBAAM,KAAK,CAAC,IAAI,EAAE,CAAC;AAAA,UACrB;AAAA,QACF;AAAA,MACF;AAEA,iBAAW,KAAK,EAAE,MAAM,OAAO,CAAC;AAAA,IAClC;AAAA,EACF;AAEA,MAAI,WAAW,WAAW,GAAG;AAC3B,WAAO,GAAG;AAAA,MACR,QAAQ;AAAA,MACR,mBAAmB;AAAA,MACnB,aAAa;AAAA,IACf,CAAC;AAAA,EACH;AAEA,MAAI,SAAS;AACb,MAAI,oBAAoB;AACxB,MAAI,cAAc;AAElB,aAAW,YAAY,YAAY;AACjC,cAAU,SAAS,OAAO,SAAS;AACnC,QAAI,SAAS,OAAO,mBAAmB;AACrC,0BAAoB,SAAS;AAAA,IAC/B;AACA,mBAAe,SAAS;AAAA,EAC1B;AAEA,SAAO,GAAG;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;;;ACrFO,IAAM,aAAa,CAAC,IAAY,aAA2B;AAChE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AACF;AAEA,IAAM,UAAU,CAAC,SAAwB,KAAK;AAC9C,IAAM,WAAW,CAAC,SAAwB,KAAK;AAC/C,IAAM,eAAe,CAAC,SAAwB,KAAK;AAE5C,IAAM,UAAU,CAAC,SAAwB;AAC9C,SAAO,CAAC,QAAQ,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,aAAa,IAAI;AAChE;AAEO,IAAM,UAAU,CAAC,SAAwB;AAC9C,SAAO,CAAC,QAAQ,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,aAAa,IAAI;AAC/D;AAEO,IAAM,mCAAmC,CAC9C,SACwD;AACxD,SACE,CAAC,QAAQ,IAAI,KACb,CAAC,SAAS,IAAI,KACd,CAAC,aAAa,IAAI,KAClB,KAAK,iBAAiB;AAE1B;AAEO,IAAM,kBAAkB,CAAC,UAA0B;AACxD,SAAO,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM;AAC/B,YAAQ,EAAE,cAAc,UAAU,MAAM,EAAE,cAAc,UAAU;AAAA,EACpE,CAAC;AACH;AAEO,IAAM,oBAAoB,CAAC,UAA0B;AAC1D,SAAO,MAAM,IAAI,CAAC,UAAU;AAAA,IAC1B,GAAG;AAAA,IACH,WAAW;AAAA,IACX,SAAS;AAAA,IACT,UAAU;AAAA,EACZ,EAAE;AACJ;AAEO,IAAM,qBAAqB,CAAC,UAA8B;AAC/D,QAAM,WAAW,aAAa,KAAK;AAEnC,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU,SAAS;AAAA,IACnB,YAAY,SAAS,QAAQ,IACzB,cAAc,aACd,cAAc;AAAA,EACpB;AACF;AAEA,IAAM,eAAe,CAAC,UAAwB;AAC5C,QAAM,OAAO,MAAM,KAAK,CAACC,UAAS,CAAC,aAAaA,KAAI,CAAC;AACrD,MAAI,CAAC,MAAM;AACT,WAAO,MAAM,CAAC;AAAA,EAChB;AACA,SAAO;AACT;AAEO,IAAM,qBAAqB,CAAC,UAA2B;AAC5D,SAAO,MAAM,MAAM,CAAC,SAAS,KAAK,SAAS;AAC7C;;;ACzDO,IAAM,sBAA2C,CACtD,MACA,QACA,eACG;AACH,QAAM,cAAc,KAAK,MAAM;AAAA,IAC7B,CAAC,SAAS,KAAK,OAAO,KAAK,WAAW;AAAA,EACxC;AAEA,MAAI,CAAC,aAAa;AAChB,WAAO,IAAI,UAAU,cAAc;AAAA,EACrC;AAEA,MAAI,YAAY,OAAO,QAAQ;AAC7B,WAAO,IAAI,UAAU,aAAa;AAAA,EACpC;AAEA,MAAI,CAAC,QAAQ,WAAW,GAAG;AACzB,WAAO,IAAI,UAAU,WAAW;AAAA,EAClC;AAGA,QAAM,iBAAiB,KAAK,gBAAgB;AAAA,IAC1C,CAAC,WAAW,OAAO,OAAO,WAAW;AAAA,EACvC;AAEA,MAAI,CAAC,gBAAgB;AACnB,WAAO,IAAI,UAAU,gBAAgB;AAAA,EACvC;AAEA,MAAI,eAAe,QAAQ;AACzB,WAAO,IAAI,UAAU,qBAAqB;AAAA,EAC5C;AAGA,QAAM,yBAAyB,KAAK,gBAAgB;AAAA,IAAI,CAAC,WACvD,OAAO,OAAO,WAAW,aACrB,EAAE,GAAG,QAAQ,QAAQ,MAAM,QAAQ,YAAY,GAAG,IAClD;AAAA,EACN;AAGA,QAAM,eAAe,KAAK,MAAM;AAAA,IAAI,CAAC,SACnC,KAAK,OAAO,YAAY,KACpB,EAAE,GAAG,MAAM,SAAS,MAAM,WAAW,MAAM,cAAc,eAAe,OAAO,IAC/E;AAAA,EACN;AAEA,QAAM,YAAY,mBAAmB,YAAY;AAEjD,MAAI,WAAW;AACb,UAAM,QAAQ,kBAAkB,gBAAgB,YAAY,CAAC;AAC7D,UAAM,cAAc,KAAK,OAAO;AAChC,UAAMC,QAAO,mBAAmB,KAAK;AACrC,UAAM,eAAe,CAAC,GAAG,KAAK,QAAQ;AACtC,UAAM,gBAAgB,aAAa;AAAA,MACjC;AAAA,MACA,KAAK,MAAM,MAAM;AAAA,IACnB;AACA,kBAAc,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAChD,UAAMC,0BAAyB,cAAc,IAAI,CAAC,QAAQ,UAAU;AAClE,aAAO;AAAA,QACL;AAAA,QACA,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,UAAU,QAAQ;AAAA,MACpB;AAAA,IACF,CAAC;AAED,WAAO,GAAG;AAAA,MACR,GAAG;AAAA,MACH,iBAAiBA;AAAA,MACjB,UAAU;AAAA,MACV;AAAA,MACA,MAAM;AAAA,MACN,YAAYD;AAAA,IACd,CAAC;AAAA,EACH;AAEA,QAAM,OAAO,mBAAmB,YAAY;AAG5C,QAAM,eAAe;AAAA,IACnB,GAAG;AAAA,IACH,iBAAiB;AAAA,IACjB,OAAO;AAAA,IACP,YAAY;AAAA,EACd;AAEA,SAAO,GAAG,YAAY;AACxB;;;ACpGO,IAAM,SAAS,CAAC,YAKC;AACtB,QAAM,EAAE,IAAI,MAAM,UAAU,KAAK,IAAI;AACrC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,iBAAiB,CAAC;AAAA,IAClB,SAAS,CAAC;AAAA,IACV,OAAO,CAAC;AAAA,IACR,MAAM;AAAA,IACN,YAAY;AAAA,MACV,MAAM;AAAA,MACN,MAAM,UAAU;AAAA,IAClB;AAAA,IACA,OAAO;AAAA,MACL,OAAO;AAAA,QACL,OAAO;AAAA,QACP,aAAa;AAAA,QACb,iBAAiB;AAAA,QACjB,UAAU;AAAA,QACV,gBAAgB;AAAA,MAClB;AAAA,MACA,OAAO,CAAC;AAAA,IACV;AAAA,IACA;AAAA,IACA,GAAI,SAAS,UAAa,EAAE,KAAK;AAAA,EACnC;AACF;;;AClCA,IAAM,WAAW,CACf,MACA,kBACyB;AACzB,SAAO,cAAc,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AAClD;AAEO,IAAM,aAAa,CACxB,MACA,kBACqB;AACrB,QAAM,YAAY,SAAS,MAAM,aAAa;AAC9C,MAAI,WAAW;AACb,WAAO,GAAG,SAAS;AAAA,EACrB;AAEA,SAAO,IAAI,UAAU,cAAc;AACrC;;;ACPO,IAAM,oBACX,CAAC,SAKD,CAAC,MAAM,SAAS;AACd,QAAM,EAAE,gBAAgB,oBAAoB,YAAAE,YAAW,IAAI;AAC3D,QAAM,KAAKA,YAAW;AACtB,QAAM,WAAW,QAAQA,YAAW;AACpC,QAAM,gBAAgB,eAAe,cAAc;AACnD,QAAM,UAAU,WAAW,MAAM,aAAa;AAE9C,MAAI,MAAM,OAAO,GAAG;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,mBAAmB,WAAW,QAAQ,KAAK;AAE5D,MAAI,CAAC,YAAY,SAAS,WAAW,GAAG;AACtC,WAAO,IAAI,UAAU,gBAAgB;AAAA,EACvC;AAEA,QAAM,UAAU;AAAA,IACd;AAAA,IACA,MAAM,QAAQ;AAAA,IACd;AAAA,IACA,MAAM;AAAA,EACR;AAEA,QAAM,UAAU,OAAO,OAAO;AAE9B,SAAO,GAAG,OAAO;AACnB;;;ACnBK,IAAM,4BAAuD,CAClE,SACA,QACA,iBAAiB,qBACd;AACH,QAAM,kBAAoC,CAAC;AAC3C,QAAM,YAAwB,CAAC,GAAG,IAAI,KAAK,GAAG;AAG9C,WAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AACjC,aAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AACjC,YAAM,WAAqB,EAAE,GAAG,EAAE;AAGlC,iBAAW,YAAY,WAAW;AAChC,cAAM,SAAS,YAAY,SAAS,UAAU,UAAU,QAAQ,cAAc;AAC9E,YAAI,KAAK,MAAM,GAAG;AAChB,0BAAgB,KAAK,EAAE,UAAU,SAAS,CAAC;AAAA,QAC7C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAUO,IAAM,wBAAwB,CACnC,SACA,QACA,iBAAyB,qBACb;AACZ,QAAM,YAAwB,CAAC,GAAG,IAAI,KAAK,GAAG;AAG9C,WAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AACjC,aAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AACjC,YAAM,WAAqB,EAAE,GAAG,EAAE;AAGlC,iBAAW,YAAY,WAAW;AAChC,cAAM,SAAS,YAAY,SAAS,UAAU,UAAU,QAAQ,cAAc;AAC9E,YAAI,KAAK,MAAM,GAAG;AAChB,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;AC/DO,IAAM,uBAA6C,CAAC,MAAM,WAAW;AAC1E,QAAM,aAAa,KAAK;AAExB,QAAM,cAAc,KAAK,MAAM;AAAA,IAC7B,CAAC,SAAS,KAAK,OAAO,WAAW;AAAA,EACnC;AAEA,MAAI,CAAC,aAAa;AAChB,WAAO,IAAI,UAAU,cAAc;AAAA,EACrC;AAEA,MAAI,YAAY,OAAO,QAAQ;AAC7B,WAAO,IAAI,UAAU,aAAa;AAAA,EACpC;AAEA,MAAI,CAAC,QAAQ,WAAW,GAAG;AACzB,WAAO,IAAI,UAAU,YAAY;AAAA,EACnC;AAEA,MAAI,YAAY,cAAc;AAC5B,UAAM,gBAAgB,KAAK,QAAQ;AAAA,MACjC,CAAC,WAAW,OAAO,OAAO,YAAY;AAAA,IACxC;AAEA,QAAI,iBAAiB,sBAAsB,cAAc,SAAS,YAAY,cAAc,KAAK,MAAM,MAAM,cAAc,GAAG;AAC5H,aAAO,IAAI,UAAU,YAAY;AAAA,IACnC;AAAA,EACF;AAEA,QAAM,WAAW,KAAK,MAAM,MAAM;AAClC,QAAM,cAAc,KAAK;AACzB,QAAM,aAAa,gBAAgB;AAEnC,QAAM,cAAc,KAAK,MAAM,IAAI,CAAC,SAAS;AAC3C,QAAI,KAAK,OAAO,YAAY,IAAI;AAC9B,UAAI,YAAY;AACd,eAAO;AAAA,UACL,GAAG;AAAA,UACH,WAAW;AAAA,UACX,UAAU;AAAA,QACZ;AAAA,MACF;AAEA,aAAO;AAAA,QACL,GAAG;AAAA,QACH,UAAU;AAAA,MACZ;AAAA,IACF;AACA,WAAO;AAAA,EACT,CAAC;AAED,MAAI;AAEJ,QAAM,aAAuB;AAAA,IAC3B,MAAM;AAAA,IACN,MAAM,UAAU;AAAA,EAClB;AAEA,MAAI,cAAc,mBAAmB,WAAW,GAAG;AACjD,kBAAc;AAAA,MACZ,GAAG;AAAA,MACH,OAAO;AAAA,MACP,YAAY;AAAA,IACd;AAAA,EACF,OAAO;AACL,kBAAc;AAAA,MACZ,GAAG;AAAA,MACH,OAAO;AAAA,MACP,YAAwB,mBAAmB,WAAW;AAAA,IACxD;AAAA,EACF;AAEA,SAAO,GAAG,WAAW;AACvB;;;ACjFO,IAAM,0BAAmD,CAAC,UAAU;AAEzE,QAAM,YAAY,oBAAI,IAAgD;AAEtE,aAAW,QAAQ,OAAO;AACxB,eAAW,UAAU,KAAK,QAAQ;AAChC,YAAM,WAAW,UAAU,IAAI,OAAO,QAAQ;AAC9C,UAAI,UAAU;AACZ,iBAAS,OAAO,KAAK,OAAO,QAAQ,MAAM;AAAA,MAC5C,OAAO;AACL,kBAAU,IAAI,OAAO,UAAU;AAAA,UAC7B,MAAM,OAAO;AAAA,UACb,QAAQ,CAAC,OAAO,QAAQ,MAAM;AAAA,QAChC,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAGA,QAAM,UAA6C,CAAC;AACpD,aAAW,CAAC,UAAU,IAAI,KAAK,WAAW;AACxC,YAAQ,KAAK;AAAA,MACX;AAAA,MACA,YAAY,KAAK;AAAA,MACjB,aAAa,KAAK,OAAO,OAAO,CAAC,KAAK,MAAM,MAAM,GAAG,CAAC;AAAA,MACtD,aAAa,KAAK;AAAA,IACpB,CAAC;AAAA,EACH;AAEA,UAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,EAAE,WAAW;AAGpD,QAAM,eAAgC,CAAC;AACvC,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,UAAU,QAAQ,CAAC;AACzB,UAAM,WAAW,IAAI,IAAI,aAAa,IAAI,CAAC,IAAK;AAChD,UAAM,WACJ,YAAY,QAAQ,gBAAgB,SAAS,cACzC,SAAS,WACT,IAAI;AACV,iBAAa,KAAK,EAAE,GAAG,SAAS,SAAS,CAAC;AAAA,EAC5C;AAEA,SAAO;AACT;;;AC9CO,IAAM,uBACX,CAAC,SACD,CAAC,MAAwB,YAAyC;AAChE,QAAM,EAAE,eAAe,IAAI;AAE3B,QAAM,gBAAgB,eAAe,YAAY;AAEjD,MAAI,CAAC,eAAe;AAClB,WAAO,IAAI,UAAU,qBAAqB;AAAA,EAC5C;AAEA,SAAO,wBAAwB,eAAe,MAAM,OAAO;AAC7D;;;AClBK,IAAM,kBACX,CAAC,SACD,MAA0B;AACxB,QAAM,EAAE,eAAe,IAAI;AAC3B,SAAO,GAAG,eAAe,cAAc,CAAC;AAC1C;;;ACMK,IAAM,mBAAqC,CAAC,MAAM,gBAAgB;AACvE,QAAM,EAAE,MAAM,IAAI;AAClB,QAAM,EAAE,OAAO,MAAM,IAAI;AAEzB,QAAM,mBAAmB,YAAY,IAAI,CAAC,UAAuB;AAC/D,QAAI,aAAa,MAAM,QAAQ;AAE/B,UAAM,SAAS,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,QAAQ;AAC/D,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,IACT;AAEA,UAAM,EAAE,QAAQ,IAAI;AAEpB,QAAI,MAAM,SAAS,GAAG;AACpB,YAAM,QAAQ,CAAC,cAAc;AAC3B,YAAI,UAAU,SAAS,sBAAsB;AAC3C,gBAAM,mBAAmB,sBAAsB,OAAO;AACtD,cAAI,kBAAkB;AACpB,0BAAc;AAAA,UAChB;AAAA,QACF;AAEA,YAAI,UAAU,SAAS,WAAW;AAChC,gBAAM,gBAAgB,cAAc,OAAO;AAC3C,gBAAM,cAAc,MAAM;AAC1B,gBAAM,eAAe,KAAK,QAAQ;AAClC,gBAAM,oBAAoB,cAAc;AACxC,cAAI,kBAAkB,mBAAmB;AACvC,0BAAc;AAAA,UAChB;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL,GAAG;AAAA,MACH,SAAS;AAAA,QACP,GAAG,MAAM;AAAA,QACT,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF,CAAC;AAGD,mBAAiB,KAAK,CAAC,GAAG,MAAM;AAC9B,QAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,QAAQ;AACzC,aAAO,EAAE,QAAQ,SAAS,EAAE,QAAQ;AAAA,IACtC;AACA,WAAO,EAAE,QAAQ,oBAAoB,EAAE,QAAQ;AAAA,EACjD,CAAC;AAED,QAAM,SAAwB,CAAC;AAE/B,MAAI,QAAQ;AACZ,SAAO,KAAK;AAAA,IACV,UAAU,iBAAiB,CAAC,EAAG;AAAA,IAC/B,YAAY,iBAAiB,CAAC,EAAG;AAAA,IACjC,SAAS,iBAAiB,CAAC,EAAG;AAAA,IAC9B,UAAU;AAAA,EACZ,CAAC;AAED,WAAS,IAAI,GAAG,IAAI,iBAAiB,QAAQ,KAAK;AAChD,UAAM,eAAe,iBAAiB,CAAC;AACvC,UAAM,gBAAgB,iBAAiB,IAAI,CAAC;AAC5C,QACE,iBACA,gBACA,aAAa,QAAQ,WAAW,cAAc,QAAQ,UACtD,aAAa,QAAQ,sBACnB,cAAc,QAAQ,mBACxB;AACA,cAAQ;AAAA,IACV;AAEA,QAAI,OAAO;AACT,aAAO,KAAK;AAAA,QACV,GAAG;AAAA,QACH,UAAU,OAAO,IAAI,CAAC,EAAG;AAAA,MAC3B,CAAC;AAAA,IACH,OAAO;AACL,aAAO,KAAK;AAAA,QACV,GAAG;AAAA,QACH,UAAU,IAAI;AAAA,MAChB,CAAC;AAAA,IACH;AAEA,YAAQ;AAAA,EACV;AAEA,SAAO,GAAG;AAAA,IACR,GAAG;AAAA,IACH;AAAA,EACF,CAAC;AACH;;;ACnFO,IAAM,qBAAyC,CACpD,MACA,QACA,UACA,aACG;AACH,QAAM,aAAa,KAAK;AAExB,QAAM,cAAc,KAAK,MAAM;AAAA,IAC7B,CAAC,SAAS,KAAK,OAAO,WAAW;AAAA,EACnC;AAEA,MAAI,CAAC,aAAa;AAChB,WAAO,IAAI,UAAU,cAAc;AAAA,EACrC;AAEA,MAAI,YAAY,OAAO,QAAQ;AAC7B,WAAO,IAAI,UAAU,aAAa;AAAA,EACpC;AAEA,MAAI,CAAC,iCAAiC,WAAW,GAAG;AAClD,WAAO,IAAI,UAAU,YAAY;AAAA,EACnC;AAEA,QAAM,SAAS,YAAY;AAE3B,QAAM,gBAAgB,KAAK,QAAQ;AAAA,IACjC,CAAC,WAAW,OAAO,OAAO,YAAY;AAAA,EACxC;AAEA,MAAI,CAAC,eAAe;AAClB,WAAO,IAAI,UAAU,gBAAgB;AAAA,EACvC;AAEA,QAAM,iBAAiB;AAAA,IACrB,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA,KAAK,MAAM,MAAM;AAAA,EACnB;AAEA,MAAI,MAAM,cAAc,GAAG;AACzB,WAAO;AAAA,EACT;AAEA,QAAM,iBAAiB,KAAK,QAAQ,IAAI,CAAC,WAAW;AAClD,QAAI,OAAO,OAAO,cAAc,IAAI;AAClC,aAAO,UAAU,eAAe;AAAA,IAClC;AACA,WAAO;AAAA,EACT,CAAC;AAED,QAAM,WAAW,KAAK,MAAM,MAAM;AAClC,QAAM,cAAc,KAAK;AACzB,QAAM,aAAa,gBAAgB;AAEnC,QAAM,eAAe,KAAK,MAAM,IAAI,CAAC,SAAS;AAC5C,QAAI,KAAK,OAAO,YAAY,IAAI;AAC9B,UAAI,YAAY;AACd,eAAO;AAAA,UACL,GAAG;AAAA,UACH,WAAW;AAAA,UACX,UAAU;AAAA,QACZ;AAAA,MACF;AACA,aAAO;AAAA,QACL,GAAG;AAAA,QACH,UAAU;AAAA,MACZ;AAAA,IACF;AACA,WAAO;AAAA,EACT,CAAC;AAED,MAAI;AAEJ,QAAM,aAAuB;AAAA,IAC3B,MAAM;AAAA,IACN,MAAM,UAAU;AAAA,EAClB;AAEA,MAAI,cAAc,mBAAmB,YAAY,GAAG;AAClD,kBAAc;AAAA,MACZ,GAAG;AAAA,MACH,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,SAAS;AAAA,IACX;AAAA,EACF,OAAO;AACL,kBAAc;AAAA,MACZ,GAAG;AAAA,MACH,OAAO;AAAA,MACP,YAAwB,mBAAmB,YAAY;AAAA,MACvD,SAAS;AAAA,IACX;AAAA,EACF;AAEA,SAAO,GAAG,WAAW;AACvB;;;AC7GO,IAAM,mBACX,CAAC,SAID,CAAC,SAAS;AACR,QAAM,EAAE,YAAAC,aAAY,eAAAC,eAAc,IAAI;AACtC,QAAM;AAAA,IACJ,OAAO;AAAA,MACL,OAAO,EAAE,OAAO,UAAU,gBAAgB;AAAA,IAC5C;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,kBAAkB,QAAQ;AAEhC,QAAM,WAAmB,CAAC;AAE1B,WAAS,IAAI,GAAG,IAAI,iBAAiB,KAAK;AACxC,aAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AACjC,YAAM,OAAO,WAAWD,YAAW,GAAG,QAAQ,CAAC,EAAG,EAAE;AACpD,eAAS,KAAK,IAAI;AAAA,IACpB;AAAA,EACF;AAEA,QAAM,UAAU,KAAK,OACjB,oBAAoB,KAAK,MAAM,OAAO,IACtCC;AACJ,QAAM,gBAAgB,QAAQ,QAAQ;AACtC,QAAM,eAAe,CAAC,GAAG,QAAQ;AACjC,QAAM,gBAAgB,aAAa,OAAO,GAAG,eAAe;AAC5D,gBAAc,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAChD,QAAM,aAAyB;AAAA,IAC7B,MAAM;AAAA,IACN,UAAU,cAAc,CAAC,EAAG;AAAA,IAC5B,YAAY,cAAc;AAAA,EAC5B;AAEA,QAAM,WAA+B;AAAA,IACnC,GAAG;AAAA,IACH,OAAO;AAAA,IACP;AAAA,IACA,UAAU;AAAA,IACV,iBAAiB,cAAc,IAAI,CAAC,QAAQ,UAAU;AACpD,aAAO;AAAA,QACL;AAAA,QACA,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,UAAU,QAAQ;AAAA,MACpB;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO,GAAG,QAAQ;AACpB;;;ACgBK,IAAM,kBAAkB,CAAC,WAAsD;AACpF,QAAM,iBAAiB,kBAAU;AACjC,QAAM,qBAAqB,qBAAa;AACxC,QAAM,iBAAiB,kBAAU;AACjC,QAAM,OAAO,OAAO,cAAc;AAClC,QAAM,UAAU,OAAO,iBAAiB;AACxC,QAAM,aAAa,OAAO,cAAc;AAGxC,QAAM,SAAS,OAAO,SAClB,OAAO,SACP,OAAO,UACL,cAAc,IAAI,IAClB;AAEN,SAAO;AAAA,IACL,mBAAmB;AAAA,MACjB;AAAA,MACA;AAAA,MACA,kBAAkB;AAAA,QAChB;AAAA,QACA;AAAA,QACA,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AAAA,IACA,iBAAiB;AAAA,MACf;AAAA,MACA;AAAA,MACA,gBAAgB,EAAE,eAAe,CAAC;AAAA,IACpC;AAAA,IACA,sBAAsB;AAAA,MACpB;AAAA,MACA;AAAA,MACA,qBAAqB,EAAE,eAAe,CAAC;AAAA,IACzC;AAAA,IACA,mBAAmB;AAAA,MACjB;AAAA,MACA;AAAA,MACA,kBAAkB;AAAA,QAChB,YAAY;AAAA,QACZ,eAAe;AAAA,QACf;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IACA,sBAAsB;AAAA,MACpB;AAAA,MACA;AAAA,MACA,qBAAqB;AAAA,QACnB;AAAA,QACA;AAAA,QACA,eAAe;AAAA,MACjB,CAAC;AAAA,IACH;AAAA,IACA,kBAAkB;AAAA,MAChB;AAAA,MACA;AAAA,MACA,iBAAiB,EAAE,YAAY,MAAM,eAAe,QAAQ,CAAC;AAAA,IAC/D;AAAA,IACA,qBAAqB;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,oBAAoB;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,sBAAsB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,kBAAkB,iBAAiB,QAAQ,YAAY;AAAA,MACrD;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IACD,uBAAuB;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,2BAA2B;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,uBAAuB;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,sBAAsB,qBAAqB,QAAQ,UAAU;AAAA,IAC7D,wBAAwB,uBAAuB,QAAQ,UAAU;AAAA,IACjE,yBAAyB;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;ACrLA,IAAM,QAAQ,CACZ,MACA,MACA,SACA,WAA+B,aACV,EAAE,MAAM,MAAM,SAAS,SAAS;AAEvD,IAAM,mBAAmB,CAAC,UACxB,OAAO,UAAU,YAAY,MAAM,SAAS;AAE9C,IAAM,uBAAuB,CAAC,UAC5B,OAAO,UAAU,YAAY,OAAO,UAAU,KAAK,KAAK,SAAS;AAEnE,IAAM,oBAAoB,CAAC,UACzB,OAAO,UAAU,YAAY,OAAO,UAAU,KAAK,KAAK,QAAQ;AAElE,IAAM,eAAe,oBAAI,IAAY,CAAC,GAAG,QAAQ,OAAO,CAAC;AACzD,IAAM,qBAAqB,IAAI,IAAY,OAAO,OAAO,aAAa,CAAC;AACvE,IAAM,iBAAiB,IAAI,IAAY,OAAO,OAAO,SAAS,CAAC;AAI/D,IAAM,wBAAwB,CAAC,SAAkC;AAC/D,QAAM,SAA4B,CAAC;AAEnC,MAAI,CAAC,iBAAiB,KAAK,EAAE,GAAG;AAC9B,WAAO,KAAK,MAAM,MAAM,cAAc,oCAAoC,CAAC;AAAA,EAC7E;AACA,MAAI,CAAC,qBAAqB,KAAK,IAAI,GAAG;AACpC,WAAO,KAAK,MAAM,QAAQ,gBAAgB,qCAAqC,CAAC;AAAA,EAClF;AACA,MAAI,CAAC,MAAM,QAAQ,KAAK,QAAQ,GAAG;AACjC,WAAO,KAAK,MAAM,YAAY,oBAAoB,2BAA2B,CAAC;AAAA,EAChF;AACA,MAAI,CAAC,MAAM,QAAQ,KAAK,eAAe,GAAG;AACxC,WAAO,KAAK,MAAM,mBAAmB,4BAA4B,kCAAkC,CAAC;AAAA,EACtG;AACA,MAAI,CAAC,MAAM,QAAQ,KAAK,OAAO,GAAG;AAChC,WAAO,KAAK,MAAM,WAAW,mBAAmB,0BAA0B,CAAC;AAAA,EAC7E;AACA,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,GAAG;AAC9B,WAAO,KAAK,MAAM,SAAS,iBAAiB,wBAAwB,CAAC;AAAA,EACvE;AACA,MAAI,CAAC,KAAK,SAAS,OAAO,KAAK,UAAU,UAAU;AACjD,WAAO,KAAK,MAAM,SAAS,iBAAiB,yBAAyB,CAAC;AAAA,EACxE,OAAO;AACL,QAAI,CAAC,KAAK,MAAM,SAAS,OAAO,KAAK,MAAM,UAAU,UAAU;AAC7D,aAAO,KAAK,MAAM,eAAe,uBAAuB,+BAA+B,CAAC;AAAA,IAC1F;AACA,QAAI,CAAC,MAAM,QAAQ,KAAK,MAAM,KAAK,GAAG;AACpC,aAAO,KAAK,MAAM,eAAe,uBAAuB,8BAA8B,CAAC;AAAA,IACzF;AAAA,EACF;AACA,MAAI,CAAC,KAAK,QAAQ,OAAO,KAAK,SAAS,UAAU;AAC/C,WAAO,KAAK,MAAM,QAAQ,gBAAgB,wBAAwB,CAAC;AAAA,EACrE,OAAO;AACL,QAAI,CAAC,iBAAiB,KAAK,KAAK,IAAI,GAAG;AACrC,aAAO,KAAK,MAAM,aAAa,qBAAqB,sCAAsC,CAAC;AAAA,IAC7F;AAAA,EACF;AACA,MAAI,CAAC,KAAK,cAAc,OAAO,KAAK,eAAe,UAAU;AAC3D,WAAO,KAAK,MAAM,cAAc,uBAAuB,8BAA8B,CAAC;AAAA,EACxF,WAAW,KAAK,WAAW,SAAS,YAAY,KAAK,WAAW,SAAS,QAAQ;AAC/E,WAAO,KAAK,MAAM,mBAAmB,4BAA4B,4CAA4C,CAAC;AAAA,EAChH;AAEA,SAAO;AACT;AAEA,IAAM,eAAe,CAAC,MAAe,SAAoC;AACvE,QAAM,SAA4B,CAAC;AACnC,MAAI,CAAC,QAAQ,OAAO,SAAS,UAAU;AACrC,WAAO,KAAK,MAAM,MAAM,gBAAgB,WAAW,IAAI,oBAAoB,CAAC;AAC5E,WAAO;AAAA,EACT;AACA,QAAM,IAAI;AACV,MAAI,OAAO,EAAE,SAAS,YAAY,CAAC,aAAa,IAAI,EAAE,IAAI,GAAG;AAC3D,WAAO,KAAK,MAAM,GAAG,IAAI,SAAS,qBAAqB,2BAA2B,IAAI,EAAE,CAAC;AAAA,EAC3F;AACA,MAAI,OAAO,EAAE,WAAW,YAAY,EAAE,SAAS,GAAG;AAChD,WAAO,KAAK,MAAM,GAAG,IAAI,WAAW,uBAAuB,qBAAqB,IAAI,EAAE,CAAC;AAAA,EACzF;AACA,SAAO;AACT;AAEA,IAAM,kBAAkB,CAAC,SAAkC;AACzD,QAAM,SAA4B,CAAC;AACnC,MAAI,CAAC,MAAM,QAAQ,KAAK,OAAO,EAAG,QAAO;AAEzC,QAAM,YAAY,oBAAI,IAAY;AAClC,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,QAAQ,KAAK;AAC5C,UAAM,SAAS,KAAK,QAAQ,CAAC;AAC7B,UAAM,OAAO,WAAW,CAAC;AAEzB,QAAI,CAAC,iBAAiB,OAAO,EAAE,GAAG;AAChC,aAAO,KAAK,MAAM,GAAG,IAAI,OAAO,qBAAqB,sCAAsC,CAAC;AAAA,IAC9F,WAAW,UAAU,IAAI,OAAO,EAAE,GAAG;AACnC,aAAO,KAAK,MAAM,GAAG,IAAI,OAAO,uBAAuB,wBAAwB,OAAO,EAAE,EAAE,CAAC;AAAA,IAC7F,OAAO;AACL,gBAAU,IAAI,OAAO,EAAE;AAAA,IACzB;AAEA,QAAI,OAAO,OAAO,SAAS,YAAY,OAAO,KAAK,SAAS,GAAG;AAC7D,aAAO,KAAK,MAAM,GAAG,IAAI,SAAS,uBAAuB,2CAA2C,CAAC;AAAA,IACvG;AAGA,QAAI,CAAC,MAAM,QAAQ,OAAO,OAAO,GAAG;AAClC,aAAO,KAAK,MAAM,GAAG,IAAI,YAAY,mBAAmB,4BAA4B,CAAC;AACrF;AAAA,IACF;AACA,QAAI,OAAO,QAAQ,WAAW,UAAU;AACtC,aAAO,KAAK,MAAM,GAAG,IAAI,YAAY,wBAAwB,qBAAqB,QAAQ,cAAc,OAAO,QAAQ,MAAM,EAAE,CAAC;AAChI;AAAA,IACF;AAEA,QAAI,cAAc;AAClB,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,QAAQ,KAAK;AAC9C,YAAM,MAAM,OAAO,QAAQ,CAAC;AAC5B,UAAI,CAAC,MAAM,QAAQ,GAAG,KAAK,IAAI,WAAW,UAAU;AAClD,eAAO,KAAK,MAAM,GAAG,IAAI,YAAY,CAAC,KAAK,uBAAuB,eAAe,CAAC,cAAc,QAAQ,UAAU,CAAC;AACnH;AAAA,MACF;AACA,eAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,cAAM,OAAO,IAAI,CAAC;AAClB,eAAO,KAAK,GAAG,aAAa,MAAM,GAAG,IAAI,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC;AAChE,YAAI,QAAQ,OAAO,SAAS,YAAa,KAAiC,SAAS,UAAU;AAC3F;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,QAAI,gBAAgB,GAAG;AACrB,aAAO,KAAK,MAAM,GAAG,IAAI,YAAY,kBAAkB,6CAA6C,SAAS,CAAC;AAAA,IAChH,WAAW,cAAc,GAAG;AAC1B,aAAO,KAAK,MAAM,GAAG,IAAI,YAAY,oBAAoB,eAAe,WAAW,2BAA2B,CAAC;AAAA,IACjH;AAAA,EACF;AAEA,SAAO;AACT;AAEA,IAAM,mBAAmB,CAAC,SAAkC;AAC1D,QAAM,SAA4B,CAAC;AACnC,QAAM,aAAa,oBAAI,IAAY;AAGnC,MAAI,MAAM,QAAQ,KAAK,QAAQ,GAAG;AAChC,aAAS,IAAI,GAAG,IAAI,KAAK,SAAS,QAAQ,KAAK;AAC7C,YAAM,SAAS,KAAK,SAAS,CAAC;AAC9B,YAAM,OAAO,YAAY,CAAC;AAE1B,UAAI,CAAC,kBAAkB,OAAO,MAAM,GAAG;AACrC,eAAO,KAAK,MAAM,GAAG,IAAI,WAAW,yBAAyB,0CAA0C,CAAC;AAAA,MAC1G,WAAW,WAAW,IAAI,OAAO,MAAM,GAAG;AACxC,eAAO,KAAK,MAAM,GAAG,IAAI,WAAW,2BAA2B,4BAA4B,OAAO,MAAM,EAAE,CAAC;AAAA,MAC7G,OAAO;AACL,mBAAW,IAAI,OAAO,MAAM;AAAA,MAC9B;AACA,aAAO,KAAK,GAAG,aAAa,OAAO,MAAM,GAAG,IAAI,OAAO,CAAC;AACxD,aAAO,KAAK,GAAG,aAAa,OAAO,OAAO,GAAG,IAAI,QAAQ,CAAC;AAAA,IAC5D;AAAA,EACF;AAGA,MAAI,MAAM,QAAQ,KAAK,eAAe,GAAG;AACvC,aAAS,IAAI,GAAG,IAAI,KAAK,gBAAgB,QAAQ,KAAK;AACpD,YAAM,WAAW,KAAK,gBAAgB,CAAC;AACvC,YAAM,OAAO,mBAAmB,CAAC;AAEjC,UAAI,CAAC,SAAS,UAAU,OAAO,SAAS,WAAW,UAAU;AAC3D,eAAO,KAAK,MAAM,GAAG,IAAI,WAAW,2BAA2B,mCAAmC,CAAC;AACnG;AAAA,MACF;AAEA,YAAM,SAAS,SAAS;AACxB,UAAI,CAAC,kBAAkB,OAAO,MAAM,GAAG;AACrC,eAAO,KAAK,MAAM,GAAG,IAAI,kBAAkB,yBAAyB,0CAA0C,CAAC;AAAA,MACjH,WAAW,WAAW,IAAI,OAAO,MAAM,GAAG;AACxC,eAAO,KAAK,MAAM,GAAG,IAAI,kBAAkB,2BAA2B,4BAA4B,OAAO,MAAM,EAAE,CAAC;AAAA,MACpH,OAAO;AACL,mBAAW,IAAI,OAAO,MAAM;AAAA,MAC9B;AACA,aAAO,KAAK,GAAG,aAAa,OAAO,MAAM,GAAG,IAAI,cAAc,CAAC;AAC/D,aAAO,KAAK,GAAG,aAAa,OAAO,OAAO,GAAG,IAAI,eAAe,CAAC;AAGjE,UAAI,SAAS,UAAU,SAAS,WAAW,MAAM;AAC/C,eAAO,KAAK,MAAM,GAAG,IAAI,IAAI,uBAAuB,8CAA8C,CAAC;AAAA,MACrG;AACA,UAAI,CAAC,SAAS,UAAU,SAAS,WAAW,MAAM;AAChD,eAAO,KAAK,MAAM,GAAG,IAAI,IAAI,sBAAsB,uCAAuC,CAAC;AAAA,MAC7F;AAAA,IACF;AAAA,EACF;AAKA,MAAI,MAAM,QAAQ,KAAK,KAAK,GAAG;AAC7B,UAAM,oBAAoB,oBAAI,IAAY;AAC1C,aAAS,IAAI,GAAG,IAAI,KAAK,MAAM,QAAQ,KAAK;AAC1C,YAAM,OAAO,KAAK,MAAM,CAAC;AACzB,UAAI,KAAK,cAAc;AACrB,cAAM,OAAO,SAAS,CAAC;AACvB,cAAM,SAAS,KAAK;AACpB,YAAI,CAAC,kBAAkB,OAAO,MAAM,GAAG;AACrC,iBAAO,KAAK,MAAM,GAAG,IAAI,WAAW,yBAAyB,0CAA0C,CAAC;AAAA,QAC1G,WAAW,kBAAkB,IAAI,OAAO,MAAM,GAAG;AAC/C,iBAAO,KAAK,MAAM,GAAG,IAAI,WAAW,2BAA2B,wCAAwC,OAAO,MAAM,EAAE,CAAC;AAAA,QACzH,OAAO;AACL,4BAAkB,IAAI,OAAO,MAAM;AAAA,QACrC;AACA,eAAO,KAAK,GAAG,aAAa,OAAO,MAAM,GAAG,IAAI,OAAO,CAAC;AACxD,eAAO,KAAK,GAAG,aAAa,OAAO,OAAO,GAAG,IAAI,QAAQ,CAAC;AAAA,MAC5D;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,IAAM,gBAAgB,CAAC,SAAkC;AACvD,QAAM,SAA4B,CAAC;AACnC,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,EAAG,QAAO;AAEvC,QAAM,YAAY,IAAI;AAAA,IACpB,MAAM,QAAQ,KAAK,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC;AAAA,EACjE;AACA,QAAM,UAAU,oBAAI,IAAY;AAEhC,WAAS,IAAI,GAAG,IAAI,KAAK,MAAM,QAAQ,KAAK;AAC1C,UAAM,OAAO,KAAK,MAAM,CAAC;AACzB,UAAM,OAAO,SAAS,CAAC;AAEvB,QAAI,CAAC,iBAAiB,KAAK,EAAE,GAAG;AAC9B,aAAO,KAAK,MAAM,GAAG,IAAI,OAAO,mBAAmB,oCAAoC,CAAC;AAAA,IAC1F,WAAW,QAAQ,IAAI,KAAK,EAAE,GAAG;AAC/B,aAAO,KAAK,MAAM,GAAG,IAAI,OAAO,qBAAqB,sBAAsB,KAAK,EAAE,EAAE,CAAC;AAAA,IACvF,OAAO;AACL,cAAQ,IAAI,KAAK,EAAE;AAAA,IACrB;AAEA,QAAI,CAAC,iBAAiB,KAAK,QAAQ,GAAG;AACpC,aAAO,KAAK,MAAM,GAAG,IAAI,aAAa,0BAA0B,0CAA0C,CAAC;AAAA,IAC7G,WAAW,UAAU,OAAO,KAAK,CAAC,UAAU,IAAI,KAAK,QAAQ,GAAG;AAC9D,aAAO,KAAK,MAAM,GAAG,IAAI,aAAa,yBAAyB,wCAAwC,KAAK,QAAQ,EAAE,CAAC;AAAA,IACzH;AAEA,QAAI,KAAK,cAAc,CAAC,KAAK,WAAW,CAAC,KAAK,WAAW;AACvD,aAAO,KAAK,MAAM,MAAM,2BAA2B,uCAAuC,KAAK,OAAO,cAAc,KAAK,QAAQ,IAAI,SAAS,CAAC;AAAA,IACjJ;AAAA,EACF;AAEA,SAAO;AACT;AAEA,IAAM,mBAAmB,CAAC,SAAkC;AAC1D,QAAM,SAA4B,CAAC;AACnC,MAAI,CAAC,KAAK,cAAc,OAAO,KAAK,eAAe,SAAU,QAAO;AAEpE,QAAM,aAAa,KAAK;AAExB,MAAI,WAAW,SAAS,UAAU;AAChC,UAAM,SAAS;AAEf,QAAI,CAAC,iBAAiB,OAAO,QAAQ,GAAG;AACtC,aAAO,KAAK,MAAM,uBAAuB,qBAAqB,qCAAqC,CAAC;AAAA,IACtG,WAAW,MAAM,QAAQ,KAAK,KAAK,KAAK,CAAC,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,OAAO,QAAQ,GAAG;AACzF,aAAO,KAAK,MAAM,uBAAuB,uBAAuB,0CAA0C,OAAO,QAAkB,EAAE,CAAC;AAAA,IACxI;AAEA,QAAI,OAAO,OAAO,eAAe,YAAY,CAAC,mBAAmB,IAAI,OAAO,UAAoB,GAAG;AACjG,aAAO,KAAK,MAAM,yBAAyB,yBAAyB,8BAA8B,CAAC,GAAG,kBAAkB,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;AAAA,IACzI;AAAA,EACF,WAAW,WAAW,SAAS,QAAQ;AACrC,UAAM,OAAO;AAEb,QAAI,OAAO,KAAK,SAAS,YAAY,CAAC,eAAe,IAAI,KAAK,IAAc,GAAG;AAC7E,aAAO,KAAK,MAAM,mBAAmB,qBAAqB,wBAAwB,CAAC,GAAG,cAAc,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;AAAA,IACrH;AAAA,EACF;AAEA,SAAO;AACT;AAEA,IAAM,eAAe,CAAC,SAAwB;AAC5C,MAAI,KAAK,YAAY,SAAS,OAAQ,QAAO;AAC7C,QAAM,OAAQ,KAAK,WAAgC;AACnD,SAAO,SAAS,gBAAgB,SAAS,aAAa,SAAS;AACjE;AAEA,IAAM,gBAAgB,CAAC,SAAkC;AACvD,QAAM,SAA4B,CAAC;AACnC,MAAI,CAAC,KAAK,SAAS,OAAO,KAAK,UAAU,SAAU,QAAO;AAG1D,QAAM,YAAY,aAAa,IAAI;AAEnC,QAAM,QAAQ,KAAK,MAAM;AACzB,MAAI,SAAS,OAAO,UAAU,UAAU;AACtC,UAAM,SAAS,CAAC,SAAS,eAAe,mBAAmB,YAAY,gBAAgB;AACvF,eAAW,SAAS,QAAQ;AAC1B,YAAM,QAAQ,YAAY,uBAAuB;AACjD,UAAI,CAAC,MAAM,MAAM,KAAK,CAAC,GAAG;AACxB,eAAO,KAAK,MAAM,eAAe,KAAK,IAAI,4BAA4B,eAAe,KAAK,6BAA6B,CAAC;AAAA,MAC1H;AAAA,IACF;AAAA,EACF;AAEA,MAAI,MAAM,QAAQ,KAAK,MAAM,KAAK,GAAG;AACnC,aAAS,IAAI,GAAG,IAAI,KAAK,MAAM,MAAM,QAAQ,KAAK;AAChD,YAAM,OAAO,KAAK,MAAM,MAAM,CAAC;AAC/B,UAAI,CAAC,iBAAiB,KAAK,IAAI,GAAG;AAChC,eAAO,KAAK,MAAM,eAAe,CAAC,UAAU,2BAA2B,4CAA4C,CAAC;AAAA,MACtH;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAmBO,IAAM,oBAAoB,CAAC,SAAkC;AAClE,QAAM,SAA4B,CAAC;AAEnC,SAAO,KAAK,GAAG,sBAAsB,IAAI,CAAC;AAC1C,SAAO,KAAK,GAAG,gBAAgB,IAAI,CAAC;AACpC,SAAO,KAAK,GAAG,iBAAiB,IAAI,CAAC;AACrC,SAAO,KAAK,GAAG,cAAc,IAAI,CAAC;AAClC,SAAO,KAAK,GAAG,iBAAiB,IAAI,CAAC;AACrC,SAAO,KAAK,GAAG,cAAc,IAAI,CAAC;AAElC,SAAO;AACT;;;ACvVA,IAAM,oBAAiD;AAAA,EACrD,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,QAAQ;AACV;AAMO,IAAM,cAAc,CACzB,MACA,WAC4B;AAC5B,SAAO,SAAS,IAAI,KAAK,kBAAkB,IAAI;AACjD;AAKO,IAAM,mBAAmB,MAAgB,OAAO,KAAK,iBAAiB;;;ACgB7E,IAAM,eAAe,CAAC,YAA6B;AACjD,QAAM,SAAS,sBAAsB,OAAO;AAC5C,SAAO,KAAK,MAAM,IAAI,OAAO,MAAM,SAAS;AAC9C;AAEA,IAAM,oBAAoB,CACxB,SACA,QACA,WACA,mBACmB;AACnB,QAAM,SAAS;AAAA,IACb;AAAA,IACA,UAAU;AAAA,IACV,UAAU;AAAA,IACV;AAAA,IACA;AAAA,EACF;AACA,SAAO,KAAK,MAAM,IAAI,OAAO,QAAQ;AACvC;AAEA,IAAM,qBAAqB,CACzB,SACA,QACA,YACA,mBAC0E;AAC1E,MAAI,OAA8E;AAElF,aAAW,aAAa,YAAY;AAClC,UAAM,aAAa,kBAAkB,SAAS,QAAQ,WAAW,cAAc;AAC/E,QAAI,CAAC,WAAY;AACjB,UAAM,QAAQ,aAAa,UAAU;AACrC,QAAI,CAAC,QAAQ,QAAQ,KAAK,OAAO;AAC/B,aAAO,EAAE,WAAW,OAAO,SAAS,WAAW;AAAA,IACjD;AAAA,EACF;AAEA,SAAO;AACT;AAEA,IAAM,oBAAoB,CAAC,SACzB,KAAK,MAAM,MAAM;AAEnB,IAAM,mBAAmB,CAAC,MAA0B,WAAmB;AACrE,QAAM,OAAO,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM;AACnD,QAAM,SAAS,OACX,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK,QAAQ,IAC/C;AACJ,SAAO,EAAE,MAAM,OAAO;AACxB;AAEA,IAAM,uBAAuB,CAAC,SAAuC;AACnE,QAAM,UAAU,KAAK,MAAM,MAAM;AACjC,SAAO,CAAC,GAAG,KAAK,QAAQ,EACrB,MAAM,GAAG,OAAO,EAChB,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AACvC;AAQO,IAAM,iBAA8B;AAAA,EACzC,cAAc,CAAC,YAAY;AACzB,UAAM,EAAE,kBAAkB,IAAI;AAC9B,UAAM,MAAM,KAAK,MAAM,KAAK,OAAO,IAAI,kBAAkB,MAAM;AAC/D,WAAO,kBAAkB,GAAG,EAAG,OAAO;AAAA,EACxC;AAAA,EAEA,iBAAiB,CAAC,YAAY;AAC5B,UAAM,EAAE,gBAAgB,IAAI;AAC5B,QAAI,gBAAgB,WAAW,EAAG,QAAO;AACzC,UAAM,MAAM,KAAK,MAAM,KAAK,OAAO,IAAI,gBAAgB,MAAM;AAC7D,WAAO,gBAAgB,GAAG;AAAA,EAC5B;AACF;AASO,IAAM,iBAA8B;AAAA,EACzC,cAAc,CAAC,YAAY;AACzB,UAAM,EAAE,MAAM,QAAQ,kBAAkB,IAAI;AAC5C,UAAM,EAAE,OAAO,IAAI,iBAAiB,MAAM,MAAM;AAChD,QAAI,CAAC,OAAQ,QAAO,kBAAkB,CAAC,EAAG,OAAO;AAEjD,UAAM,UAAU,kBAAkB,IAAI;AACtC,QAAI,YAAY;AAChB,QAAI,WAAW,kBAAkB,CAAC,EAAG,OAAO;AAE5C,eAAW,MAAM,mBAAmB;AAClC,YAAM,aAAa;AAAA,QACjB,OAAO;AAAA,QACP,GAAG;AAAA,QACH;AAAA,MACF;AACA,YAAM,SAAS;AAAA,QACb,OAAO;AAAA,QACP,GAAG;AAAA,QACH;AAAA,QACA;AAAA,MACF;AACA,YAAM,QAAQ,SAAS,OAAO,QAAQ;AACtC,UAAI,QAAQ,WAAW;AACrB,oBAAY;AACZ,mBAAW,GAAG,OAAO;AAAA,MACvB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,iBAAiB,CAAC,YAAY;AAC5B,UAAM,EAAE,MAAM,QAAQ,SAAS,gBAAgB,IAAI;AACnD,QAAI,gBAAgB,WAAW,EAAG,QAAO;AAEzC,UAAM,UAAU,kBAAkB,IAAI;AACtC,UAAM,SAAS,mBAAmB,SAAS,QAAQ,iBAAiB,OAAO;AAC3E,WAAO,SAAS,OAAO,YAAY,gBAAgB,CAAC;AAAA,EACtD;AACF;AAIA,IAAM,wBAAwB,CAC5B,SACA,SACA,iBACW;AACX,MAAI,aAAa,WAAW,EAAG,QAAO;AAEtC,MAAI,gBAAgB;AACpB,aAAW,cAAc,cAAc;AACrC,UAAM,iBAAiB,0BAA0B,SAAS,YAAY,OAAO;AAC7E,UAAM,SAAS,mBAAmB,SAAS,YAAY,gBAAgB,OAAO;AAC9E,QAAI,UAAU,OAAO,QAAQ,eAAe;AAC1C,sBAAgB,OAAO;AAAA,IACzB;AAAA,EACF;AAEA,SAAO;AACT;AAQO,IAAM,mBAAgC;AAAA,EAC3C,cAAc,CAAC,YAAY;AACzB,UAAM,EAAE,MAAM,QAAQ,kBAAkB,IAAI;AAC5C,UAAM,EAAE,OAAO,IAAI,iBAAiB,MAAM,MAAM;AAChD,QAAI,CAAC,OAAQ,QAAO,kBAAkB,CAAC,EAAG,OAAO;AAEjD,UAAM,UAAU,kBAAkB,IAAI;AACtC,UAAM,YAAY,qBAAqB,IAAI;AAE3C,QAAI,oBAAoB;AACxB,QAAI,WAAW,kBAAkB,CAAC,EAAG,OAAO;AAE5C,eAAW,MAAM,mBAAmB;AAClC,YAAM,aAAa;AAAA,QACjB,OAAO;AAAA,QACP,GAAG;AAAA,QACH;AAAA,MACF;AACA,YAAM,SAAS;AAAA,QACb,OAAO;AAAA,QACP,GAAG;AAAA,QACH;AAAA,QACA;AAAA,MACF;AAEA,YAAM,iBAAiB,SAAS,OAAO,QAAQ,aAAa,OAAO,OAAO;AAC1E,YAAM,eAAe,SAAS,OAAO,UAAU,OAAO;AACtD,YAAM,cAAc,sBAAsB,cAAc,SAAS,SAAS;AAC1E,YAAM,WAAW,iBAAiB,cAAc;AAEhD,UAAI,WAAW,mBAAmB;AAChC,4BAAoB;AACpB,mBAAW,GAAG,OAAO;AAAA,MACvB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,iBAAiB,CAAC,YAAY;AAC5B,UAAM,EAAE,MAAM,QAAQ,SAAS,gBAAgB,IAAI;AACnD,QAAI,gBAAgB,WAAW,EAAG,QAAO;AAEzC,UAAM,UAAU,kBAAkB,IAAI;AACtC,UAAM,YAAY,qBAAqB,IAAI;AAE3C,QAAI,oBAAoB;AACxB,QAAI,gBAAgC,gBAAgB,CAAC;AAErD,eAAW,aAAa,iBAAiB;AACvC,YAAM,aAAa,kBAAkB,SAAS,QAAQ,WAAW,OAAO;AACxE,UAAI,CAAC,WAAY;AAEjB,YAAM,iBAAiB,aAAa,UAAU;AAC9C,YAAM,cAAc,sBAAsB,YAAY,SAAS,SAAS;AACxE,YAAM,WAAW,iBAAiB,cAAc;AAEhD,UAAI,WAAW,mBAAmB;AAChC,4BAAoB;AACpB,wBAAgB;AAAA,MAClB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;AAKA,IAAM,oBAAoB;AAG1B,IAAM,mBAAmB;AAMzB,IAAM,gBAAgB,CACpB,SACA,QACA,YACA,SACA,UACqB;AACrB,MAAI,WAAW,UAAU,MAAO,QAAO;AAEvC,QAAM,SAAS,WACZ,IAAI,CAAC,MAAM;AACV,UAAM,IAAI,kBAAkB,SAAS,QAAQ,GAAG,OAAO;AACvD,WAAO,EAAE,WAAW,GAAG,OAAO,IAAI,aAAa,CAAC,IAAI,EAAE;AAAA,EACxD,CAAC,EACA,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAEnC,SAAO,OAAO,MAAM,GAAG,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS;AACtD;AAEA,IAAM,iBAAiB,CACrB,SACA,mBACA,iBACA,SACA,UACW;AACX,MAAI,SAAS,KAAK,kBAAkB,WAAW,GAAG;AAChD,WAAO,aAAa,OAAO;AAAA,EAC7B;AAGA,QAAM,QAAQ,CAAC,GAAG,iBAAiB,EAChC,MAAM,GAAG,eAAe,EACxB,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AACrC,QAAM,aAAa,kBAAkB,MAAM,eAAe;AAE1D,MAAI,YAAY,aAAa,OAAO;AAEpC,aAAW,UAAU,OAAO;AAC1B,UAAM,gBAAgB,0BAA0B,SAAS,QAAQ,OAAO;AAExE,QAAI,cAAc,WAAW,GAAG;AAC9B,YAAM,QAAQ;AAAA,QACZ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,MACV;AACA,UAAI,QAAQ,UAAW,aAAY;AACnC;AAAA,IACF;AAGA,UAAM,aAAa;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,eAAW,aAAa,YAAY;AAClC,YAAM,aAAa,kBAAkB,SAAS,QAAQ,WAAW,OAAO;AACxE,UAAI,CAAC,WAAY;AAEjB,YAAM,QAAQ;AAAA,QACZ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,MACV;AACA,UAAI,QAAQ,UAAW,aAAY;AAAA,IACrC;AAAA,EACF;AAEA,SAAO;AACT;AAQO,IAAM,iBAA8B;AAAA,EACzC,cAAc,CAAC,YAAY;AACzB,UAAM,EAAE,MAAM,QAAQ,kBAAkB,IAAI;AAC5C,UAAM,EAAE,OAAO,IAAI,iBAAiB,MAAM,MAAM;AAChD,QAAI,CAAC,OAAQ,QAAO,kBAAkB,CAAC,EAAG,OAAO;AAEjD,UAAM,UAAU,kBAAkB,IAAI;AACtC,UAAM,UAAU,KAAK,MAAM,MAAM;AACjC,UAAM,YAAY,KAAK;AAAA,MACrB,KAAK,MAAM,MAAM,WAAW,KAAK;AAAA,MACjC;AAAA,IACF;AAEA,QAAI,YAAY;AAChB,QAAI,WAAW,kBAAkB,CAAC,EAAG,OAAO;AAE5C,eAAW,MAAM,mBAAmB;AAClC,YAAM,gBAAgB;AAAA,QACpB,OAAO;AAAA,QACP,GAAG;AAAA,QACH;AAAA,MACF;AAEA,UAAI,cAAc,WAAW,GAAG;AAC9B,cAAM,QAAQ;AAAA,UACZ,OAAO;AAAA,UACP,KAAK;AAAA,UACL;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,YAAI,QAAQ,WAAW;AACrB,sBAAY;AACZ,qBAAW,GAAG,OAAO;AAAA,QACvB;AACA;AAAA,MACF;AAEA,YAAM,aAAa;AAAA,QACjB,OAAO;AAAA,QACP,GAAG;AAAA,QACH;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,iBAAW,aAAa,YAAY;AAClC,cAAM,aAAa;AAAA,UACjB,OAAO;AAAA,UACP,GAAG;AAAA,UACH;AAAA,UACA;AAAA,QACF;AACA,YAAI,CAAC,WAAY;AAEjB,cAAM,QAAQ;AAAA,UACZ;AAAA,UACA,KAAK;AAAA,UACL;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,YAAI,QAAQ,WAAW;AACrB,sBAAY;AACZ,qBAAW,GAAG,OAAO;AAAA,QACvB;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,iBAAiB,CAAC,YAAY;AAC5B,UAAM,EAAE,MAAM,QAAQ,SAAS,gBAAgB,IAAI;AACnD,QAAI,gBAAgB,WAAW,EAAG,QAAO;AAEzC,UAAM,UAAU,kBAAkB,IAAI;AACtC,UAAM,UAAU,KAAK,MAAM,MAAM;AACjC,UAAM,YAAY,KAAK;AAAA,MACrB,KAAK,MAAM,MAAM,WAAW,KAAK;AAAA,MACjC;AAAA,IACF;AAEA,QAAI,YAAY;AAChB,QAAI,gBAAgC,gBAAgB,CAAC;AAErD,eAAW,aAAa,iBAAiB;AACvC,YAAM,aAAa,kBAAkB,SAAS,QAAQ,WAAW,OAAO;AACxE,UAAI,CAAC,WAAY;AAEjB,YAAM,QAAQ;AAAA,QACZ;AAAA,QACA,KAAK;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,UAAI,QAAQ,WAAW;AACrB,oBAAY;AACZ,wBAAgB;AAAA,MAClB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;AAcO,IAAM,cAAc,CACzB,QACA,MACA,aACc;AACd,QAAM,SAAS,KAAK,WAAW;AAC/B,QAAM,SAAS,KAAK,WAAW;AAE/B,MAAI,WAAW,cAAc;AAC3B,UAAM,oBAAoB,KAAK,gBAAgB,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM;AACtE,UAAM,aAAa,SAAS,aAAa;AAAA,MACvC;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,WAAO,OAAO,aAAa,EAAE,MAAM,QAAQ,WAAW,CAAC;AAAA,EACzD;AAEA,MAAI,WAAW,eAAe;AAC5B,UAAM,EAAE,MAAM,OAAO,IAAI,iBAAiB,MAAM,MAAM;AACtD,QAAI,CAAC,MAAM,gBAAgB,CAAC,QAAQ;AAClC,aAAO,OAAO,cAAc,EAAE,MAAM,OAAO,CAAC;AAAA,IAC9C;AAEA,UAAM,SAAS,KAAK;AACpB,UAAM,UAAU,OAAO;AACvB,UAAM,UAAU,kBAAkB,IAAI;AACtC,UAAM,kBAAkB,0BAA0B,SAAS,QAAQ,OAAO;AAE1E,UAAM,YAAY,SAAS,gBAAgB;AAAA,MACzC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,QAAI,CAAC,WAAW;AACd,aAAO,OAAO,cAAc,EAAE,MAAM,OAAO,CAAC;AAAA,IAC9C;AAEA,WAAO,OAAO,YAAY;AAAA,MACxB;AAAA,MACA;AAAA,MACA,UAAU,UAAU;AAAA,MACpB,UAAU,UAAU;AAAA,IACtB,CAAC;AAAA,EACH;AAGA,SAAO,OAAO,cAAc,EAAE,MAAM,OAAO,CAAC;AAC9C;AAOO,IAAM,YAAY,CAAC,SAAsC;AAC9D,QAAM,SAAS,KAAK,WAAW;AAC/B,QAAM,OAAO,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM;AACnD,QAAM,SAAS,OACX,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK,QAAQ,IAC/C;AACJ,SAAO,CAAC,CAAC,QAAQ;AACnB;AAYO,IAAM,eAAe,CAC1B,QACA,MACA,qBACc;AACd,MAAI,UAAU;AAEd,SAAO,qBAAqB,OAAO,KAAK,UAAU,OAAO,GAAG;AAC1D,UAAM,SAAS,QAAQ,WAAW;AAClC,UAAM,OAAO,QAAQ,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM;AACtD,UAAM,SAAS,OACX,QAAQ,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK,QAAQ,IAClD;AACJ,UAAM,eAAe,QAAQ,KAAK,gBAAgB;AAClD,UAAM,WACJ,YAAY,cAAc,gBAAgB,KAAK;AACjD,cAAU,YAAY,QAAQ,SAAS,QAAQ;AAAA,EACjD;AAEA,SAAO;AACT;;;AC7fO,IAAM,kBAAkB,CAAC,YAAmC;AAAA,EACjE;AAAA,EACA,SAAS,CAAC;AACZ;AAKO,IAAM,eAAe,CAC1B,KACA,WACmB;AAAA,EACnB,GAAG;AAAA,EACH,SAAS;AAAA,IACP,GAAG,IAAI;AAAA,IACP;AAAA,MACE,GAAG;AAAA,MACH,IAAI,IAAI,QAAQ;AAAA,MAChB,WAAW,KAAK,IAAI;AAAA,IACtB;AAAA,EACF;AACF;AAOO,IAAM,aAAa,CAAC,QACzB,IAAI;AAKC,IAAM,mBAAmB,CAC9B,KACA,SAC2B,IAAI,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,IAAI;AAKjE,IAAM,mBAAmB,CAC9B,KACA,SAC2B,IAAI,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI;AAmB/D,IAAM,oBAAoB,CAC/B,WACwD;AACxD,MAAI,MAAM,gBAAgB,EAAE;AAE5B,QAAM,SAAS,CACb,QACA,SACA,SACS;AACT,UAAM,aAAa,KAAK,EAAE,QAAQ,SAAS,KAAK,CAAC;AAAA,EACnD;AAEA,QAAM,gBAA4B;AAAA;AAAA,IAEhC,UAAU,CAAC,QAAQ,OAAO,SAAS,GAAG;AAAA,IACtC,eAAe,CAAC,QAAQ,OAAO,cAAc,GAAG;AAAA,IAChD,gBAAgB,CAAC,QAAQ,OAAO,eAAe,GAAG;AAAA,IAClD,oBAAoB,CAAC,QAAQ,OAAO,mBAAmB,GAAG;AAAA,IAC1D,gBAAgB,CAAC,QAAQ,OAAO,eAAe,GAAG;AAAA,IAClD,WAAW,CAAC,QAAQ,OAAO,UAAU,GAAG;AAAA,IACxC,aAAa,CAAC,QAAQ,OAAO,YAAY,GAAG;AAAA,IAC5C,YAAY,CAAC,QAAQ,OAAO,WAAW,GAAG;AAAA,IAC1C,mBAAmB,CAAC,QAAQ,OAAO,kBAAkB,GAAG;AAAA;AAAA,IAGxD,YAAY,CAAC,QAAQ;AACnB,YAAM,OAAO,OAAO,WAAW,GAAG;AAClC,YAAM,gBAAgB,KAAK,EAAE;AAC7B,aAAO,cAAc,EAAE,MAAM,IAAI,MAAM,MAAM,IAAI,KAAK,GAAG,KAAK,IAAI;AAClE,aAAO;AAAA,IACT;AAAA,IAEA,YAAY,CAAC,QAAQ;AACnB,YAAM,OAAO,OAAO,WAAW,GAAG;AAClC,aAAO,cAAc,EAAE,SAAS,IAAI,QAAQ,GAAG,KAAK,IAAI;AACxD,aAAO;AAAA,IACT;AAAA,IAEA,eAAe,CAAC,QAAQ;AACtB,YAAM,OAAO,OAAO,cAAc,GAAG;AACrC,aAAO,iBAAiB,EAAE,YAAY,IAAI,WAAW,GAAG,KAAK,IAAI;AACjE,aAAO;AAAA,IACT;AAAA,IAEA,WAAW,CAAC,QAAQ;AAClB,YAAM,OAAO,OAAO,UAAU,GAAG;AACjC,aAAO,aAAa,CAAC,GAAG,KAAK,IAAI;AACjC,aAAO;AAAA,IACT;AAAA,IAEA,cAAc,CAAC,QAAQ;AACrB,YAAM,OAAO,OAAO,aAAa,GAAG;AACpC;AAAA,QACE;AAAA,QACA,EAAE,QAAQ,IAAI,QAAQ,YAAY,IAAI,WAAW;AAAA,QACjD,KAAK;AAAA,MACP;AACA,aAAO;AAAA,IACT;AAAA,IAEA,aAAa,CAAC,QAAQ;AACpB,YAAM,OAAO,OAAO,YAAY,GAAG;AACnC;AAAA,QACE;AAAA,QACA;AAAA,UACE,QAAQ,IAAI;AAAA,UACZ,UAAU,IAAI;AAAA,UACd,UAAU,IAAI;AAAA,QAChB;AAAA,QACA,KAAK;AAAA,MACP;AACA,aAAO;AAAA,IACT;AAAA,IAEA,eAAe,CAAC,QAAQ;AACtB,YAAM,OAAO,OAAO,cAAc,GAAG;AACrC,aAAO,iBAAiB,EAAE,QAAQ,IAAI,OAAO,GAAG,KAAK,IAAI;AACzD,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,QAAQ,MAAM;AAAA,EAChB;AACF;AAaO,IAAM,gBAAgB,CAC3B,QACA,QACc;AACd,MAAI,IAAI,QAAQ,WAAW,GAAG;AAC5B,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AAEA,QAAM,aAAa,IAAI,QAAQ,CAAC;AAChC,MAAI,YAAY,WAAW,cAAc;AACvC,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAEA,QAAM,eAAe,WAAW;AAChC,MAAI,OAAkB,OAAO,WAAW;AAAA,IACtC,MAAM,aAAa;AAAA,IACnB,MAAM,aAAa;AAAA,EACrB,CAAC;AAED,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,QAAQ,KAAK;AAC3C,UAAM,QAAQ,IAAI,QAAQ,CAAC;AAC3B,QAAI,CAAC,MAAO;AAEZ,YAAQ,MAAM,QAAQ;AAAA,MACpB,KAAK,cAAc;AACjB,cAAM,UAAU,MAAM;AACtB,eAAO,OAAO,WAAW,EAAE,MAAM,QAAQ,MAAM,MAAM,QAAQ,KAAK,CAAC;AACnE;AAAA,MACF;AAAA,MACA,KAAK,cAAc;AACjB,cAAM,UAAU,MAAM;AACtB,eAAO,OAAO,WAAW,EAAE,MAAM,SAAS,QAAQ,QAAQ,CAAC;AAC3D;AAAA,MACF;AAAA,MACA,KAAK,iBAAiB;AACpB,cAAM,UAAU,MAAM;AACtB,eAAO,OAAO,cAAc;AAAA,UAC1B;AAAA,UACA,YAAY,QAAQ;AAAA,QACtB,CAAC;AACD;AAAA,MACF;AAAA,MACA,KAAK,aAAa;AAChB,eAAO,OAAO,UAAU,EAAE,KAAK,CAAC;AAChC;AAAA,MACF;AAAA,MACA,KAAK,gBAAgB;AACnB,cAAM,UAAU,MAAM;AACtB,eAAO,OAAO,aAAa;AAAA,UACzB;AAAA,UACA,QAAQ,QAAQ;AAAA,UAChB,YAAY,QAAQ;AAAA,QACtB,CAAC;AACD;AAAA,MACF;AAAA,MACA,KAAK,eAAe;AAClB,cAAM,UAAU,MAAM;AACtB,eAAO,OAAO,YAAY;AAAA,UACxB;AAAA,UACA,QAAQ,QAAQ;AAAA,UAChB,UAAU,QAAQ;AAAA,UAClB,UAAU,QAAQ;AAAA,QACpB,CAAC;AACD;AAAA,MACF;AAAA,MACA,KAAK,iBAAiB;AACpB,cAAM,UAAU,MAAM;AACtB,eAAO,OAAO,cAAc;AAAA,UAC1B;AAAA,UACA,QAAQ,QAAQ;AAAA,QAClB,CAAC;AACD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;AC/RO,IAAM,oBAAoB,CAAC,kBAA0C;AAAA,EAC1E,SAAS;AAAA,EACT,MAAM,CAAC;AAAA,EACP,QAAQ,CAAC;AACX;AAWO,IAAM,YAAY,CACvB,SACA,cACiB;AAAA,EACjB,SAAS;AAAA,EACT,MAAM,CAAC,GAAG,QAAQ,MAAM,QAAQ,OAAO;AAAA,EACvC,QAAQ,CAAC;AACX;AAUO,IAAM,OAAO,CAAC,YAAsC;AACzD,MAAI,QAAQ,KAAK,WAAW,GAAG;AAC7B,UAAM,IAAI,UAAU;AAAA,EACtB;AAEA,QAAM,WAAW,QAAQ,KAAK,QAAQ,KAAK,SAAS,CAAC;AACrD,SAAO;AAAA,IACL,SAAS;AAAA,IACT,MAAM,QAAQ,KAAK,MAAM,GAAG,EAAE;AAAA,IAC9B,QAAQ,CAAC,GAAG,QAAQ,QAAQ,QAAQ,OAAO;AAAA,EAC7C;AACF;AAUO,IAAM,OAAO,CAAC,YAAsC;AACzD,MAAI,QAAQ,OAAO,WAAW,GAAG;AAC/B,UAAM,IAAI,UAAU;AAAA,EACtB;AAEA,QAAM,OAAO,QAAQ,OAAO,QAAQ,OAAO,SAAS,CAAC;AACrD,SAAO;AAAA,IACL,SAAS;AAAA,IACT,MAAM,CAAC,GAAG,QAAQ,MAAM,QAAQ,OAAO;AAAA,IACvC,QAAQ,QAAQ,OAAO,MAAM,GAAG,EAAE;AAAA,EACpC;AACF;AAKO,IAAM,UAAU,CAAC,YACtB,QAAQ,KAAK,SAAS;AAKjB,IAAM,UAAU,CAAC,YACtB,QAAQ,OAAO,SAAS;AAQnB,IAAM,eAAe,CAAC,aAAuC;AAAA,EAClE,SAAS,QAAQ;AAAA,EACjB,MAAM,CAAC;AAAA,EACP,QAAQ,CAAC;AACX;AAKO,IAAM,iBAAiB,CAC5B,aACsC;AAAA,EACtC,MAAM,QAAQ,KAAK;AAAA,EACnB,QAAQ,QAAQ,OAAO;AACzB;;;AChBO,IAAM,mBAAmB,CAAC,WAA8C;AAC7E,QAAM;AAAA,IACJ,mBAAAC;AAAA,IACA,iBAAAC;AAAA,IACA,sBAAAC;AAAA,IACA,mBAAAC;AAAA,IACA,sBAAAC;AAAA,IACA,kBAAAC;AAAA,IACA,qBAAAC;AAAA,IACA,oBAAAC;AAAA,IACA,sBAAAC;AAAA,IACA,kBAAAC;AAAA,IACA,uBAAAC;AAAA,IACA,2BAAAC;AAAA,IACA,uBAAAC;AAAA,IACA,sBAAAC;AAAA,IACA,wBAAAC;AAAA,IACA,yBAAAC;AAAA,EACF,IAAI,gBAAgB,MAAM;AAE1B,MAAI,SAAqB;AAAA,IACvB,UAAU,CAAC,YAAYd,iBAAgB,OAAO;AAAA,IAC9C,eAAe,CAAC,YAAYC,sBAAqB,OAAO;AAAA,IACxD,YAAY,CAAC,YAAYF,mBAAkB,OAAO;AAAA,IAClD,YAAY,CAAC,YAAYG,mBAAkB,OAAO;AAAA,IAClD,eAAe,CAAC,YAAYC,sBAAqB,OAAO;AAAA,IACxD,WAAW,CAAC,YAAYC,kBAAiB,OAAO;AAAA,IAChD,cAAc,CAAC,YAAYC,qBAAoB,OAAO;AAAA,IACtD,aAAa,CAAC,YAAYC,oBAAmB,OAAO;AAAA,IACpD,eAAe,CAAC,YAAYC,sBAAqB,OAAO;AAAA,IACxD,YAAY,CAAC,YAAYC,kBAAiB,OAAO;AAAA,IACjD,gBAAgB,CAAC,YAAYC,uBAAsB,OAAO;AAAA,IAC1D,oBAAoB,CAAC,YAAYC,2BAA0B,OAAO;AAAA,IAClE,gBAAgB,CAAC,YAAYC,uBAAsB,OAAO;AAAA,IAC1D,WAAW,CAAC,YAAYC,sBAAqB,OAAO;AAAA,IACpD,aAAa,CAAC,YAAYC,wBAAuB,OAAO;AAAA,IACxD,mBAAmB,CAAC,YAAYC,yBAAwB,OAAO;AAAA,EACjE;AAEA,MAAI,OAAO,QAAQ;AACjB,aAAS,eAAe,QAAQ,OAAO,MAAM;AAAA,EAC/C;AAEA,MAAI,OAAO,OAAO;AAChB,UAAM,eACJ,OAAO,OAAO,UAAU,WAAW,OAAO,QAAQ;AACpD,aAAS,cAAc,QAAQ,YAAY;AAAA,EAC7C;AAEA,SAAO;AACT;","names":["err","durationMs","getResultUseCase","calculateScoreUseCase","result","shuffleMethod","uuidMethod","shuffleMethod","lord","next","updatedCurrentDominoes","uuidMethod","uuidMethod","shuffleMethod","createGameHandler","getModesHandler","getExtraRulesHandler","addPlayersHandler","addExtraRulesHandler","startGameHandler","chooseDominoHandler","placeDominoHandler","discardDominoHandler","getResultHandler","calculateScoreHandler","getValidPlacementsHandler","canPlaceDominoHandler","serializeGameHandler","deserializeGameHandler","getDynastyResultHandler"]}