@pompidup/kingdomino-engine 3.5.0 → 3.6.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/README.md +1 -1
- package/dist/index.d.ts +1376 -676
- package/dist/index.js +4038 -2393
- package/dist/index.js.map +1 -1
- package/dist/index.universal.js +4038 -2393
- package/dist/wasm-bridge.js +3769 -2200
- package/package.json +1 -9
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/buildings.json","../src/adapterServerside/jsonBuildings.ts","../src/datasources/cavemen.json","../src/adapterServerside/jsonCavemen.ts","../src/datasources/dominoes.json","../src/adapterServerside/jsonDominoes.ts","../src/datasources/modes.json","../src/adapterServerside/jsonModes.ts","../src/datasources/questTiles.json","../src/adapterServerside/jsonQuestTiles.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/constructBuildingHandler.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/application/handlers/placeFireTokenHandler.ts","../src/application/handlers/placeGiantHandler.ts","../src/application/handlers/placeKnightHandler.ts","../src/application/handlers/recruitCavemanHandler.ts","../src/application/handlers/sendGiantHandler.ts","../src/core/useCases/serialization.ts","../src/application/handlers/serializeGameHandler.ts","../src/application/handlers/skipOptionalActionHandler.ts","../src/application/handlers/startGameHandler.ts","../src/application/handlers/useDragonHandler.ts","../src/core/domain/entities/rule.ts","../src/core/domain/types/ageOfGiants.ts","../src/core/domain/types/domino.ts","../src/core/domain/types/kingdom.ts","../src/core/domain/types/origins.ts","../src/core/domain/types/player.ts","../src/utils/seededShuffle.ts","../src/core/useCases/addExtraRules.ts","../src/core/domain/entities/ageOfGiantsHelpers.ts","../src/core/domain/entities/economy.ts","../src/core/domain/entities/domino.ts","../src/core/domain/entities/kingdom.ts","../src/core/domain/entities/originsHelpers.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/building.ts","../src/core/domain/entities/queen.ts","../src/core/useCases/constructBuilding.ts","../src/core/domain/entities/fireToken.ts","../src/core/domain/entities/giant.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/domain/entities/caveman.ts","../src/core/domain/entities/originsScore.ts","../src/core/domain/entities/questScore.ts","../src/core/domain/entities/resource.ts","../src/core/domain/entities/totem.ts","../src/core/useCases/getResult.ts","../src/core/useCases/placeDomino.ts","../src/core/useCases/placeFireToken.ts","../src/core/useCases/placeGiant.ts","../src/core/domain/entities/knight.ts","../src/core/useCases/placeKnight.ts","../src/core/useCases/recruitCaveman.ts","../src/core/useCases/sendGiant.ts","../src/core/useCases/skipOptionalAction.ts","../src/core/useCases/startGame.ts","../src/core/useCases/useDragon.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 { AgeOfGiantsState } from \"./ageOfGiants.js\";\nimport type { Domino, RevealsDomino } from \"./domino.js\";\nimport type { Lord } from \"./lord.js\";\nimport type { GameMode } from \"./mode.js\";\nimport type { OriginsState } from \"./origins.js\";\nimport type { Player, PlayerActions } from \"./player.js\";\nimport type { QueenDominoState } from \"./queendomino.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 /** Queendomino-specific state (only present in QueenDomino mode) */\n queendomino?: QueenDominoState;\n /** Origins-specific state (only present in KingdominoOrigins modes) */\n origins?: OriginsState;\n /** Age of Giants-specific state (only present in AgeOfGiants modes) */\n ageOfGiants?: AgeOfGiantsState;\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 placeKnight: wrapMethod(\"placeKnight\", engine.placeKnight, logger, level),\n constructBuilding: wrapMethod(\n \"constructBuilding\",\n engine.constructBuilding,\n logger,\n level,\n ),\n useDragon: wrapMethod(\"useDragon\", engine.useDragon, logger, level),\n skipOptionalAction: wrapMethod(\n \"skipOptionalAction\",\n engine.skipOptionalAction,\n logger,\n level,\n ),\n placeFireToken: wrapMethod(\n \"placeFireToken\",\n engine.placeFireToken,\n logger,\n level,\n ),\n recruitCaveman: wrapMethod(\n \"recruitCaveman\",\n engine.recruitCaveman,\n logger,\n level,\n ),\n placeGiant: wrapMethod(\"placeGiant\", engine.placeGiant, logger, level),\n sendGiant: wrapMethod(\"sendGiant\", engine.sendGiant, logger, level),\n };\n};\n","import { isGameWithNextStep } from \"@core/domain/types/game.js\";\nimport type {\n GameState,\n GameWithNextAction,\n GameWithNextStep,\n} from \"@core/domain/types/index.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 /** Called after a lord places a knight on their kingdom (QueenDomino) */\n onKnightPlaced?: (event: { game: GameState; lordId: string }) => void;\n /** Called after a lord constructs a building (QueenDomino) */\n onBuildingConstructed?: (event: {\n game: GameState;\n lordId: string;\n buildingId: number;\n }) => void;\n /** Called after a lord uses the dragon to destroy a building (QueenDomino) */\n onDragonUsed?: (event: {\n game: GameState;\n lordId: string;\n buildingId: number;\n }) => void;\n /** Called after a lord places a fire token on their kingdom (Origins) */\n onFireTokenPlaced?: (event: { game: GameState; lordId: string }) => void;\n /** Called after a lord recruits a caveman from the cave board (Origins Tribe) */\n onCavemanRecruited?: (event: {\n game: GameState;\n lordId: string;\n cavemanId: number;\n }) => void;\n /** Called after a lord places a giant on a crown in their kingdom */\n onGiantPlaced?: (event: { game: GameState; lordId: string }) => void;\n /** Called after a lord sends a giant to an opponent's kingdom */\n onGiantSent?: (event: {\n game: GameState;\n lordId: string;\n targetPlayerId: string;\n }) => 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 // Queendomino methods — emit events after execution\n placeKnight: (cmd) => {\n const game = engine.placeKnight(cmd);\n callbacks.onKnightPlaced?.({ game, lordId: cmd.lordId });\n return game;\n },\n\n constructBuilding: (cmd) => {\n const game = engine.constructBuilding(cmd);\n callbacks.onBuildingConstructed?.({\n game,\n lordId: cmd.lordId,\n buildingId: cmd.buildingId,\n });\n return game;\n },\n\n useDragon: (cmd) => {\n const game = engine.useDragon(cmd);\n callbacks.onDragonUsed?.({\n game,\n lordId: cmd.lordId,\n buildingId: cmd.buildingId,\n });\n return game;\n },\n\n skipOptionalAction: (cmd) => engine.skipOptionalAction(cmd),\n\n // Origins methods — emit events after execution\n placeFireToken: (cmd) => {\n const game = engine.placeFireToken(cmd);\n callbacks.onFireTokenPlaced?.({ game, lordId: cmd.lordId });\n return game;\n },\n\n recruitCaveman: (cmd) => {\n const game = engine.recruitCaveman(cmd);\n callbacks.onCavemanRecruited?.({\n game,\n lordId: cmd.lordId,\n cavemanId: cmd.cavemanId,\n });\n return game;\n },\n\n // Age of Giants methods — emit events after execution\n placeGiant: (cmd) => {\n const game = engine.placeGiant(cmd);\n callbacks.onGiantPlaced?.({ game, lordId: cmd.lordId });\n return game;\n },\n\n sendGiant: (cmd) => {\n const game = engine.sendGiant(cmd);\n callbacks.onGiantSent?.({\n game,\n lordId: cmd.lordId,\n targetPlayerId: cmd.targetPlayerId,\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 { \"id\": 1, \"name\": \"The Bakery\", \"cost\": 1, \"immediateBonus\": { \"type\": \"coins\", \"amount\": 2 }, \"crowns\": 0, \"towers\": 0 },\n { \"id\": 2, \"name\": \"The Bakery\", \"cost\": 1, \"immediateBonus\": { \"type\": \"coins\", \"amount\": 2 }, \"crowns\": 0, \"towers\": 0 },\n { \"id\": 3, \"name\": \"The Sawmill\", \"cost\": 2, \"crowns\": 0, \"towers\": 0, \"endGameScoring\": { \"type\": \"perTerrain\", \"terrain\": \"forest\", \"points\": 1 } },\n { \"id\": 4, \"name\": \"The Fishmonger's\", \"cost\": 2, \"immediateBonus\": { \"type\": \"coins\", \"amount\": 1 }, \"crowns\": 0, \"towers\": 0, \"endGameScoring\": { \"type\": \"perTerrain\", \"terrain\": \"sea\", \"points\": 1 } },\n { \"id\": 5, \"name\": \"The Fishmonger's\", \"cost\": 2, \"immediateBonus\": { \"type\": \"coins\", \"amount\": 1 }, \"crowns\": 0, \"towers\": 0, \"endGameScoring\": { \"type\": \"perTerrain\", \"terrain\": \"sea\", \"points\": 1 } },\n { \"id\": 6, \"name\": \"The Weaving Shop\", \"cost\": 3, \"crowns\": 1, \"towers\": 0, \"endGameScoring\": { \"type\": \"perTerrain\", \"terrain\": \"wheat\", \"points\": 1 } },\n { \"id\": 7, \"name\": \"The Magic School\", \"cost\": 4, \"crowns\": 1, \"towers\": 0, \"endGameScoring\": { \"type\": \"perCrown\", \"points\": 1 } },\n { \"id\": 8, \"name\": \"The Fountain\", \"cost\": 3, \"crowns\": 0, \"towers\": 1, \"endGameScoring\": { \"type\": \"perTower\", \"points\": 2 } },\n { \"id\": 9, \"name\": \"The Church\", \"cost\": 4, \"crowns\": 1, \"towers\": 0, \"endGameScoring\": { \"type\": \"perBuilding\", \"points\": 2 } },\n { \"id\": 10, \"name\": \"The Bath\", \"cost\": 2, \"immediateBonus\": { \"type\": \"coins\", \"amount\": 1 }, \"crowns\": 0, \"towers\": 0, \"endGameScoring\": { \"type\": \"flat\", \"points\": 4 } },\n { \"id\": 11, \"name\": \"The Guard Tower\", \"cost\": 1, \"crowns\": 0, \"towers\": 1, \"endGameScoring\": { \"type\": \"flat\", \"points\": 2 } },\n { \"id\": 12, \"name\": \"The Guard Tower\", \"cost\": 1, \"crowns\": 0, \"towers\": 1, \"endGameScoring\": { \"type\": \"flat\", \"points\": 2 } },\n { \"id\": 13, \"name\": \"The Big Tower\", \"cost\": 3, \"crowns\": 0, \"towers\": 2, \"endGameScoring\": { \"type\": \"flat\", \"points\": 4 } },\n { \"id\": 14, \"name\": \"The Guardhouse\", \"cost\": 2, \"crowns\": 0, \"towers\": 1, \"endGameScoring\": { \"type\": \"perBuilding\", \"points\": 1 } },\n { \"id\": 15, \"name\": \"The Fortified Castle\", \"cost\": 5, \"crowns\": 2, \"towers\": 1, \"endGameScoring\": { \"type\": \"flat\", \"points\": 6 } },\n { \"id\": 16, \"name\": \"The Travelling Castle\", \"cost\": 3, \"crowns\": 1, \"towers\": 1, \"endGameScoring\": { \"type\": \"perTower\", \"points\": 1 } },\n { \"id\": 17, \"name\": \"The Travelling Group\", \"cost\": 2, \"immediateBonus\": { \"type\": \"coins\", \"amount\": 1 }, \"crowns\": 0, \"towers\": 0, \"endGameScoring\": { \"type\": \"perBuilding\", \"points\": 1 } },\n { \"id\": 18, \"name\": \"The Harbour\", \"cost\": 3, \"crowns\": 0, \"towers\": 0, \"endGameScoring\": { \"type\": \"perTerrain\", \"terrain\": \"sea\", \"points\": 2 } }\n]\n","import type {\n BuildingTile,\n EndGameScoring,\n EndGameScoringType,\n ImmediateBonus,\n ImmediateBonusType,\n} from \"@core/domain/types/building.js\";\nimport type { BuildingsRepository } from \"@core/portServerside/buildingsRepository.js\";\nimport buildingsJson from \"../datasources/buildings.json\" with { type: \"json\" };\n\nconst jsonBuildings = (): BuildingsRepository => {\n const buildings: BuildingTile[] = buildingsJson.map((b) => {\n const tile: BuildingTile = {\n id: b.id,\n name: b.name,\n cost: b.cost,\n crowns: b.crowns,\n towers: b.towers,\n };\n\n if (b.immediateBonus) {\n tile.immediateBonus = {\n type: b.immediateBonus.type as ImmediateBonusType,\n amount: b.immediateBonus.amount,\n } satisfies ImmediateBonus;\n }\n\n if (\"endGameScoring\" in b && b.endGameScoring) {\n tile.endGameScoring = {\n type: b.endGameScoring.type as EndGameScoringType,\n points: b.endGameScoring.points,\n ...(\"terrain\" in b.endGameScoring && {\n terrain: b.endGameScoring.terrain,\n }),\n } satisfies EndGameScoring;\n }\n\n return tile;\n });\n\n return {\n getAll: () => buildings,\n };\n};\n\nexport default jsonBuildings;\n","[\n { \"kind\": \"hunterGatherer\", \"id\": 1, \"hunterType\": \"mammothHunter\", \"pointsPerMatch\": 3 },\n { \"kind\": \"hunterGatherer\", \"id\": 2, \"hunterType\": \"mammothHunter\", \"pointsPerMatch\": 3 },\n { \"kind\": \"hunterGatherer\", \"id\": 3, \"hunterType\": \"fisherman\", \"pointsPerMatch\": 3 },\n { \"kind\": \"hunterGatherer\", \"id\": 4, \"hunterType\": \"fisherman\", \"pointsPerMatch\": 3 },\n { \"kind\": \"hunterGatherer\", \"id\": 5, \"hunterType\": \"mushroomPicker\", \"pointsPerMatch\": 3 },\n { \"kind\": \"hunterGatherer\", \"id\": 6, \"hunterType\": \"mushroomPicker\", \"pointsPerMatch\": 3 },\n { \"kind\": \"hunterGatherer\", \"id\": 7, \"hunterType\": \"flintCollector\", \"pointsPerMatch\": 3 },\n { \"kind\": \"hunterGatherer\", \"id\": 8, \"hunterType\": \"flintCollector\", \"pointsPerMatch\": 3 },\n { \"kind\": \"hunterGatherer\", \"id\": 9, \"hunterType\": \"trapper\", \"pointsPerMatch\": 2 },\n { \"kind\": \"hunterGatherer\", \"id\": 10, \"hunterType\": \"trapper\", \"pointsPerMatch\": 2 },\n { \"kind\": \"hunterGatherer\", \"id\": 11, \"hunterType\": \"gatherer\", \"pointsPerMatch\": 1 },\n { \"kind\": \"hunterGatherer\", \"id\": 12, \"hunterType\": \"gatherer\", \"pointsPerMatch\": 1 },\n { \"kind\": \"hunterGatherer\", \"id\": 13, \"hunterType\": \"fireLady\", \"pointsPerMatch\": 1 },\n { \"kind\": \"hunterGatherer\", \"id\": 14, \"hunterType\": \"fireLady\", \"pointsPerMatch\": 1 },\n { \"kind\": \"warrior\", \"id\": 15, \"warriorType\": \"small\", \"power\": 1 },\n { \"kind\": \"warrior\", \"id\": 16, \"warriorType\": \"small\", \"power\": 1 },\n { \"kind\": \"warrior\", \"id\": 17, \"warriorType\": \"small\", \"power\": 1 },\n { \"kind\": \"warrior\", \"id\": 18, \"warriorType\": \"small\", \"power\": 1 },\n { \"kind\": \"warrior\", \"id\": 19, \"warriorType\": \"amazon\", \"power\": 2 },\n { \"kind\": \"warrior\", \"id\": 20, \"warriorType\": \"amazon\", \"power\": 2 },\n { \"kind\": \"warrior\", \"id\": 21, \"warriorType\": \"amazon\", \"power\": 2 },\n { \"kind\": \"warrior\", \"id\": 22, \"warriorType\": \"oafish\", \"power\": 3 }\n]\n","import type {\n CavemanTile,\n HunterGathererKind,\n HunterGathererTile,\n WarriorTile,\n WarriorType,\n} from \"@core/domain/types/origins.js\";\nimport type { CavemenRepository } from \"@core/portServerside/cavemenRepository.js\";\nimport cavemenJson from \"../datasources/cavemen.json\" with { type: \"json\" };\n\nconst mapCaveman = (raw: {\n kind: string;\n id: number;\n hunterType?: string;\n pointsPerMatch?: number;\n warriorType?: string;\n power?: number;\n}): CavemanTile => {\n if (raw.kind === \"hunterGatherer\") {\n return {\n kind: \"hunterGatherer\",\n id: raw.id,\n hunterType: raw.hunterType as HunterGathererKind,\n pointsPerMatch: raw.pointsPerMatch!,\n } satisfies HunterGathererTile;\n }\n return {\n kind: \"warrior\",\n id: raw.id,\n warriorType: raw.warriorType as WarriorType,\n power: raw.power!,\n } satisfies WarriorTile;\n};\n\nconst jsonCavemen = (): CavemenRepository => {\n const cavemen: CavemanTile[] = cavemenJson.map(mapCaveman);\n\n return {\n getAll: () => [...cavemen],\n };\n};\n\nexport default jsonCavemen;\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 \"QueenDomino\": [\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\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 5\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 6\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 7\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 8\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"number\": 9\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"number\": 10\n },\n {\n \"left\": {\n \"type\": \"mine\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 0\n },\n \"number\": 11\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 12\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 13\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 14\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 15\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 16\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 17\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"number\": 18\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\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 \"hasConstructionSquare\": true\n },\n \"number\": 21\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 22\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 23\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 24\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 25\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 26\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 27\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 28\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 0\n },\n \"number\": 29\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 30\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 1\n },\n \"number\": 31\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"number\": 32\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 1\n },\n \"number\": 33\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 1\n },\n \"number\": 34\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 1\n },\n \"number\": 35\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 2,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 36\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 37\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 38\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 39\n },\n {\n \"left\": {\n \"type\": \"mine\",\n \"crowns\": 2,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 40\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 2\n },\n \"number\": 41\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"number\": 42\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 1\n },\n \"number\": 43\n },\n {\n \"left\": {\n \"type\": \"mine\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 1\n },\n \"number\": 44\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 2\n },\n \"number\": 45\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 2,\n \"hasConstructionSquare\": true\n },\n \"number\": 46\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 3\n },\n \"number\": 47\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 3\n },\n \"number\": 48\n }\n ],\n \"KingdominoOrigins\": [\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"number\": 1\n },\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"lake\",\n \"crowns\": 0\n },\n \"number\": 2\n },\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"number\": 3\n },\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"quarry\",\n \"crowns\": 0\n },\n \"number\": 4\n },\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"desert\",\n \"crowns\": 0\n },\n \"number\": 5\n },\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"number\": 6\n },\n {\n \"left\": {\n \"type\": \"lake\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"lake\",\n \"crowns\": 0\n },\n \"number\": 7\n },\n {\n \"left\": {\n \"type\": \"lake\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"number\": 8\n },\n {\n \"left\": {\n \"type\": \"lake\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"quarry\",\n \"crowns\": 0\n },\n \"number\": 9\n },\n {\n \"left\": {\n \"type\": \"lake\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"desert\",\n \"crowns\": 0\n },\n \"number\": 10\n },\n {\n \"left\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"number\": 11\n },\n {\n \"left\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"quarry\",\n \"crowns\": 0\n },\n \"number\": 12\n },\n {\n \"left\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"desert\",\n \"crowns\": 0\n },\n \"number\": 13\n },\n {\n \"left\": {\n \"type\": \"quarry\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"quarry\",\n \"crowns\": 0\n },\n \"number\": 14\n },\n {\n \"left\": {\n \"type\": \"quarry\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"desert\",\n \"crowns\": 0\n },\n \"number\": 15\n },\n {\n \"left\": {\n \"type\": \"desert\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"desert\",\n \"crowns\": 0\n },\n \"number\": 16\n },\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"number\": 17\n },\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"lake\",\n \"crowns\": 0\n },\n \"number\": 18\n },\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"number\": 19\n },\n {\n \"left\": {\n \"type\": \"volcano\",\n \"crowns\": 0,\n \"volcanoCraters\": 1\n },\n \"right\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"number\": 20\n },\n {\n \"left\": {\n \"type\": \"lake\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"number\": 21\n },\n {\n \"left\": {\n \"type\": \"lake\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"desert\",\n \"crowns\": 0\n },\n \"number\": 22\n },\n {\n \"left\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"quarry\",\n \"crowns\": 0\n },\n \"number\": 23\n },\n {\n \"left\": {\n \"type\": \"volcano\",\n \"crowns\": 0,\n \"volcanoCraters\": 1\n },\n \"right\": {\n \"type\": \"lake\",\n \"crowns\": 0\n },\n \"number\": 24\n },\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"number\": 25\n },\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"lake\",\n \"crowns\": 1\n },\n \"number\": 26\n },\n {\n \"left\": {\n \"type\": \"volcano\",\n \"crowns\": 0,\n \"volcanoCraters\": 1\n },\n \"right\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"number\": 27\n },\n {\n \"left\": {\n \"type\": \"lake\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"quarry\",\n \"crowns\": 0\n },\n \"number\": 28\n },\n {\n \"left\": {\n \"type\": \"jungle\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"desert\",\n \"crowns\": 0\n },\n \"number\": 29\n },\n {\n \"left\": {\n \"type\": \"volcano\",\n \"crowns\": 0,\n \"volcanoCraters\": 1\n },\n \"right\": {\n \"type\": \"quarry\",\n \"crowns\": 0\n },\n \"number\": 30\n },\n {\n \"left\": {\n \"type\": \"desert\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"number\": 31\n },\n {\n \"left\": {\n \"type\": \"quarry\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"lake\",\n \"crowns\": 0\n },\n \"number\": 32\n },\n {\n \"left\": {\n \"type\": \"volcano\",\n \"crowns\": 0,\n \"volcanoCraters\": 2\n },\n \"right\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"number\": 33\n },\n {\n \"left\": {\n \"type\": \"jungle\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"number\": 34\n },\n {\n \"left\": {\n \"type\": \"lake\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"desert\",\n \"crowns\": 0\n },\n \"number\": 35\n },\n {\n \"left\": {\n \"type\": \"volcano\",\n \"crowns\": 0,\n \"volcanoCraters\": 2\n },\n \"right\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"number\": 36\n },\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"quarry\",\n \"crowns\": 1\n },\n \"number\": 37\n },\n {\n \"left\": {\n \"type\": \"volcano\",\n \"crowns\": 0,\n \"volcanoCraters\": 1\n },\n \"right\": {\n \"type\": \"desert\",\n \"crowns\": 1\n },\n \"number\": 38\n },\n {\n \"left\": {\n \"type\": \"lake\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"jungle\",\n \"crowns\": 1\n },\n \"number\": 39\n },\n {\n \"left\": {\n \"type\": \"volcano\",\n \"crowns\": 0,\n \"volcanoCraters\": 2\n },\n \"right\": {\n \"type\": \"quarry\",\n \"crowns\": 1\n },\n \"number\": 40\n },\n {\n \"left\": {\n \"type\": \"desert\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"grassland\",\n \"crowns\": 1\n },\n \"number\": 41\n },\n {\n \"left\": {\n \"type\": \"quarry\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"number\": 42\n },\n {\n \"left\": {\n \"type\": \"volcano\",\n \"crowns\": 0,\n \"volcanoCraters\": 2\n },\n \"right\": {\n \"type\": \"lake\",\n \"crowns\": 1\n },\n \"number\": 43\n },\n {\n \"left\": {\n \"type\": \"jungle\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"desert\",\n \"crowns\": 0\n },\n \"number\": 44\n },\n {\n \"left\": {\n \"type\": \"lake\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"number\": 45\n },\n {\n \"left\": {\n \"type\": \"desert\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"quarry\",\n \"crowns\": 1\n },\n \"number\": 46\n },\n {\n \"left\": {\n \"type\": \"volcano\",\n \"crowns\": 0,\n \"volcanoCraters\": 3\n },\n \"right\": {\n \"type\": \"grassland\",\n \"crowns\": 2\n },\n \"number\": 47\n },\n {\n \"left\": {\n \"type\": \"jungle\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"quarry\",\n \"crowns\": 2\n },\n \"number\": 48\n }\n ],\n \"AgeOfGiants\": [\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 \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.01,\n \"letter\": \"A\"\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.02,\n \"letter\": \"B\"\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.03,\n \"letter\": \"C\"\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.04,\n \"letter\": \"D\"\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.05,\n \"letter\": \"E\"\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.06,\n \"letter\": \"F\"\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 49\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 50\n },\n {\n \"left\": {\n \"type\": \"mine\",\n \"crowns\": 1,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 51\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 52\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 1,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 53\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 2,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 54\n }\n ],\n \"AgeOfGiants-QueenDomino\": [\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\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 5\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 6\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 7\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 8\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"number\": 9\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"number\": 10\n },\n {\n \"left\": {\n \"type\": \"mine\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 0\n },\n \"number\": 11\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 12\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 13\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 14\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 15\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 16\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 17\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"number\": 18\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\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 \"hasConstructionSquare\": true\n },\n \"number\": 21\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 22\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 23\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 24\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 25\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 26\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 27\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 28\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 0\n },\n \"number\": 29\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 30\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 1\n },\n \"number\": 31\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"number\": 32\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 1\n },\n \"number\": 33\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 1\n },\n \"number\": 34\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 1\n },\n \"number\": 35\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 2,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 36\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 37\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 38\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 39\n },\n {\n \"left\": {\n \"type\": \"mine\",\n \"crowns\": 2,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 40\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 2\n },\n \"number\": 41\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"number\": 42\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 1\n },\n \"number\": 43\n },\n {\n \"left\": {\n \"type\": \"mine\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 1\n },\n \"number\": 44\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 2\n },\n \"number\": 45\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 2,\n \"hasConstructionSquare\": true\n },\n \"number\": 46\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 3\n },\n \"number\": 47\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 3\n },\n \"number\": 48\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.01,\n \"letter\": \"A\"\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.02,\n \"letter\": \"B\"\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.03,\n \"letter\": \"C\"\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.04,\n \"letter\": \"D\"\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.05,\n \"letter\": \"E\"\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.06,\n \"letter\": \"F\"\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 49\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 50\n },\n {\n \"left\": {\n \"type\": \"mine\",\n \"crowns\": 1,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 51\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 52\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 1,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 53\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 2,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 54\n }\n ]\n}","import type { Domino, Ground, Tile } 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 mapTile = (raw: {\n type: string;\n crowns: number;\n hasConstructionSquare?: boolean;\n volcanoCraters?: number;\n hasGiant?: boolean;\n hasFootprint?: boolean;\n}): Tile => {\n const tile: Tile = {\n type: raw.type as Ground,\n crowns: raw.crowns,\n };\n if (raw.hasConstructionSquare) {\n tile.hasConstructionSquare = true;\n }\n if (raw.volcanoCraters) {\n tile.volcanoCraters = raw.volcanoCraters;\n }\n if (raw.hasGiant) {\n tile.hasGiant = true;\n }\n if (raw.hasFootprint) {\n tile.hasFootprint = true;\n }\n return tile;\n};\n\n/** Maps Origins sub-mode names to the shared domino data key */\nconst ORIGINS_MODE_PREFIX = \"KingdominoOrigins\";\nconst resolveDataKey = (modeName: string): string => {\n if (modeName.startsWith(ORIGINS_MODE_PREFIX)) {\n return ORIGINS_MODE_PREFIX;\n }\n return modeName;\n};\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 const d: Domino = {\n left: mapTile(domino.left),\n right: mapTile(domino.right),\n number: domino.number,\n };\n if (\"letter\" in domino && typeof domino.letter === \"string\") {\n d.letter = domino.letter;\n }\n currentDominoes.push(d);\n });\n\n dominoes[key] = currentDominoes;\n }\n\n return {\n getForMode: (mode: GameMode) => {\n const key = resolveDataKey(mode.name);\n return dominoes[key] || [];\n },\n };\n};\n\nexport default jsonDominoes;\n","[\n {\n \"name\": \"Classic\",\n \"description\": \"Original KingDomino rules\"\n },\n {\n \"name\": \"QueenDomino\",\n \"description\": \"Queendomino expansion with buildings, knights, coins, the Queen and the Dragon\"\n },\n {\n \"name\": \"KingdominoOrigins-Discovery\",\n \"description\": \"Kingdomino Origins - Discovery mode with volcanoes, fire tokens and fire-based scoring\"\n },\n {\n \"name\": \"KingdominoOrigins-Totem\",\n \"description\": \"Kingdomino Origins - Totem mode with resources, totem majority and fire mechanics\"\n },\n {\n \"name\": \"KingdominoOrigins-Tribe\",\n \"description\": \"Kingdomino Origins - Tribe mode with resources, cave board, cavemen recruitment and fire mechanics\"\n },\n {\n \"name\": \"AgeOfGiants\",\n \"description\": \"Age of Giants extension with giants, quest tiles, 5-player support and 12 new dominos on top of Classic Kingdomino\"\n },\n {\n \"name\": \"AgeOfGiants-QueenDomino\",\n \"description\": \"Age of Giants extension combined with Queendomino, adding giants and quest tiles to the Queendomino experience\"\n }\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 {\n \"id\": 1,\n \"type\": \"localTrade\",\n \"name\": \"Local Trade - Wheat\",\n \"description\": \"Each wheat tile adjacent (orthogonal + diagonal) to your castle scores 5 bonus points.\",\n \"points\": 5,\n \"terrain\": \"wheat\"\n },\n {\n \"id\": 2,\n \"type\": \"localTrade\",\n \"name\": \"Local Trade - Forest\",\n \"description\": \"Each forest tile adjacent (orthogonal + diagonal) to your castle scores 5 bonus points.\",\n \"points\": 5,\n \"terrain\": \"forest\"\n },\n {\n \"id\": 3,\n \"type\": \"localTrade\",\n \"name\": \"Local Trade - Sea\",\n \"description\": \"Each sea tile adjacent (orthogonal + diagonal) to your castle scores 5 bonus points.\",\n \"points\": 5,\n \"terrain\": \"sea\"\n },\n {\n \"id\": 4,\n \"type\": \"localTrade\",\n \"name\": \"Local Trade - Plain\",\n \"description\": \"Each plain tile adjacent (orthogonal + diagonal) to your castle scores 5 bonus points.\",\n \"points\": 5,\n \"terrain\": \"plain\"\n },\n {\n \"id\": 5,\n \"type\": \"kingdomBorders\",\n \"name\": \"Kingdom Borders - Wheat\",\n \"description\": \"Each wheat tile in the 4 corners of your kingdom scores 5 bonus points.\",\n \"points\": 5,\n \"terrain\": \"wheat\"\n },\n {\n \"id\": 6,\n \"type\": \"kingdomBorders\",\n \"name\": \"Kingdom Borders - Forest\",\n \"description\": \"Each forest tile in the 4 corners of your kingdom scores 5 bonus points.\",\n \"points\": 5,\n \"terrain\": \"forest\"\n },\n {\n \"id\": 7,\n \"type\": \"kingdomBorders\",\n \"name\": \"Kingdom Borders - Sea\",\n \"description\": \"Each sea tile in the 4 corners of your kingdom scores 5 bonus points.\",\n \"points\": 5,\n \"terrain\": \"sea\"\n },\n {\n \"id\": 8,\n \"type\": \"kingdomBorders\",\n \"name\": \"Kingdom Borders - Plain\",\n \"description\": \"Each plain tile in the 4 corners of your kingdom scores 5 bonus points.\",\n \"points\": 5,\n \"terrain\": \"plain\"\n },\n {\n \"id\": 9,\n \"type\": \"harmony\",\n \"name\": \"Harmony\",\n \"description\": \"Score 5 bonus points if your kingdom is complete (no discarded dominos).\",\n \"points\": 5\n },\n {\n \"id\": 10,\n \"type\": \"middleKingdom\",\n \"name\": \"Middle Kingdom\",\n \"description\": \"Score 10 bonus points if your castle is in the center of your kingdom.\",\n \"points\": 10\n },\n {\n \"id\": 11,\n \"type\": \"lostCorner\",\n \"name\": \"Lost Corner\",\n \"description\": \"Score 20 bonus points if your castle is in one of the 4 corners of your kingdom.\",\n \"points\": 20\n },\n {\n \"id\": 12,\n \"type\": \"megalomania\",\n \"name\": \"Megalomania\",\n \"description\": \"Score 10 bonus points for each alignment of 3 or more tiles with crowns (horizontal, vertical, or diagonal).\",\n \"points\": 10\n },\n {\n \"id\": 13,\n \"type\": \"megalomania\",\n \"name\": \"Megalomania\",\n \"description\": \"Score 10 bonus points for each alignment of 3 or more tiles with crowns (horizontal, vertical, or diagonal).\",\n \"points\": 10\n },\n {\n \"id\": 14,\n \"type\": \"austereKing\",\n \"name\": \"Austere King\",\n \"description\": \"Score 10 bonus points for each property of 5+ wheat, forest, sea, or plain tiles with zero crowns.\",\n \"points\": 10\n },\n {\n \"id\": 15,\n \"type\": \"austereKing\",\n \"name\": \"Austere King\",\n \"description\": \"Score 10 bonus points for each property of 5+ wheat, forest, sea, or plain tiles with zero crowns.\",\n \"points\": 10\n },\n {\n \"id\": 16,\n \"type\": \"lostCorner\",\n \"name\": \"Lost Corner\",\n \"description\": \"Score 20 bonus points if your castle is in one of the 4 corners of your kingdom.\",\n \"points\": 20\n },\n {\n \"id\": 17,\n \"type\": \"harmony\",\n \"name\": \"Harmony\",\n \"description\": \"Score 5 bonus points if your kingdom is complete (no discarded dominos).\",\n \"points\": 5\n }\n]\n","import type { QuestTile, QuestType } from \"@core/domain/types/ageOfGiants.js\";\nimport type { Ground } from \"@core/domain/types/domino.js\";\nimport type { QuestTilesRepository } from \"@core/portServerside/questTilesRepository.js\";\nimport questTilesJson from \"../datasources/questTiles.json\" with {\n type: \"json\",\n};\n\nconst mapQuestTile = (raw: {\n id: number;\n type: string;\n name: string;\n description: string;\n points: number;\n terrain?: string;\n}): QuestTile => {\n const tile: QuestTile = {\n id: raw.id,\n type: raw.type as QuestType,\n name: raw.name,\n description: raw.description,\n points: raw.points,\n };\n if (raw.terrain) {\n tile.terrain = raw.terrain as Ground;\n }\n return tile;\n};\n\nconst jsonQuestTiles = (): QuestTilesRepository => {\n const questTiles: QuestTile[] = questTilesJson.map(mapQuestTile);\n\n return {\n getAll: () => [...questTiles],\n };\n};\n\nexport default jsonQuestTiles;\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 \"aog\": [\n {\n \"playersLimit\": 2,\n \"lordsPerPlayer\": 2,\n \"maxDominoes\": 30,\n \"dominoesPerTurn\": 5,\n \"maxTurns\": 6,\n \"maxKingdomSize\": 5,\n \"dominoesDiscardedPerTurn\": 1\n },\n {\n \"playersLimit\": 3,\n \"lordsPerPlayer\": 1,\n \"maxDominoes\": 60,\n \"dominoesPerTurn\": 5,\n \"maxTurns\": 12,\n \"maxKingdomSize\": 5,\n \"dominoesDiscardedPerTurn\": 2\n },\n {\n \"playersLimit\": 4,\n \"lordsPerPlayer\": 1,\n \"maxDominoes\": 60,\n \"dominoesPerTurn\": 5,\n \"maxTurns\": 12,\n \"maxKingdomSize\": 5,\n \"dominoesDiscardedPerTurn\": 1\n },\n {\n \"playersLimit\": 5,\n \"lordsPerPlayer\": 1,\n \"maxDominoes\": 60,\n \"dominoesPerTurn\": 5,\n \"maxTurns\": 12,\n \"maxKingdomSize\": 5,\n \"dominoesDiscardedPerTurn\": 0\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\": [\n { \"name\": \"Classic\", \"description\": \"King Domino classic mode\" },\n { \"name\": \"QueenDomino\", \"description\": \"Queendomino expansion with buildings, knights, coins, the Queen and the Dragon\" }\n ]\n },\n {\n \"name\": \"Harmony\",\n \"description\": \"Gain 5 additional points if your kingdom is complete (no discarded dominoes).\",\n \"mode\": [\n { \"name\": \"Classic\", \"description\": \"King Domino classic mode\" },\n { \"name\": \"QueenDomino\", \"description\": \"Queendomino expansion with buildings, knights, coins, the Queen and the Dragon\" }\n ]\n },\n {\n \"name\": \"The Mighty Duel\",\n \"description\": \"Use all 48 dominoes and build a 7x7 kingdom. For 2 players only.\",\n \"mode\": [\n { \"name\": \"Classic\", \"description\": \"King Domino classic mode\" },\n { \"name\": \"QueenDomino\", \"description\": \"Queendomino expansion with buildings, knights, coins, the Queen and the Dragon\" }\n ],\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\": [\n { \"name\": \"Classic\", \"description\": \"King Domino classic mode\" },\n { \"name\": \"QueenDomino\", \"description\": \"Queendomino expansion with buildings, knights, coins, the Queen and the Dragon\" }\n ]\n },\n {\n \"name\": \"Empire of Fire\",\n \"description\": \"Gain 10 additional points if your hut is in the center of your territory.\",\n \"mode\": [\n { \"name\": \"KingdominoOrigins-Discovery\", \"description\": \"Kingdomino Origins - Discovery mode\" },\n { \"name\": \"KingdominoOrigins-Totem\", \"description\": \"Kingdomino Origins - Totem mode\" },\n { \"name\": \"KingdominoOrigins-Tribe\", \"description\": \"Kingdomino Origins - Tribe mode\" }\n ]\n },\n {\n \"name\": \"Homo Habilis\",\n \"description\": \"Gain 5 additional points if your 5x5 territory is complete (no discarded dominoes).\",\n \"mode\": [\n { \"name\": \"KingdominoOrigins-Discovery\", \"description\": \"Kingdomino Origins - Discovery mode\" },\n { \"name\": \"KingdominoOrigins-Totem\", \"description\": \"Kingdomino Origins - Totem mode\" },\n { \"name\": \"KingdominoOrigins-Tribe\", \"description\": \"Kingdomino Origins - Tribe mode\" }\n ]\n },\n {\n \"name\": \"Neolithic\",\n \"description\": \"Use all 48 dominoes and build a 7x7 territory. For 2 players only.\",\n \"mode\": [\n { \"name\": \"KingdominoOrigins-Discovery\", \"description\": \"Kingdomino Origins - Discovery mode\" },\n { \"name\": \"KingdominoOrigins-Totem\", \"description\": \"Kingdomino Origins - Totem mode\" },\n { \"name\": \"KingdominoOrigins-Tribe\", \"description\": \"Kingdomino Origins - Tribe mode\" }\n ],\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\": [\n { \"name\": \"KingdominoOrigins-Discovery\", \"description\": \"Kingdomino Origins - Discovery mode\" },\n { \"name\": \"KingdominoOrigins-Totem\", \"description\": \"Kingdomino Origins - Totem mode\" },\n { \"name\": \"KingdominoOrigins-Tribe\", \"description\": \"Kingdomino Origins - Tribe mode\" }\n ]\n },\n {\n \"name\": \"Dynasty\",\n \"description\": \"Play 3 games in a row. The player with the highest total points wins.\",\n \"mode\": [\n { \"name\": \"AgeOfGiants\", \"description\": \"Age of Giants extension on Classic Kingdomino\" },\n { \"name\": \"AgeOfGiants-QueenDomino\", \"description\": \"Age of Giants extension on Queendomino\" }\n ]\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 aogRules = rulesJson.aog;\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 if (aogRules) {\n rules.aogBasic = {};\n aogRules.forEach((rule) => {\n rules.aogBasic![rule.playersLimit] = {\n lords: rule.lordsPerPlayer,\n maxDominoes: rule.maxDominoes,\n dominoesPerTurn: rule.dominoesPerTurn,\n maxTurns: rule.maxTurns,\n maxKingdomSize: rule.maxKingdomSize,\n dominoesDiscardedPerTurn: rule.dominoesDiscardedPerTurn,\n };\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\n // Queendomino errors\n CANNOT_PLACE_KNIGHT: \"CANNOT_PLACE_KNIGHT\",\n MAX_KNIGHTS_REACHED: \"MAX_KNIGHTS_REACHED\",\n KNIGHT_TERRITORY_OCCUPIED: \"KNIGHT_TERRITORY_OCCUPIED\",\n CANNOT_AFFORD_BUILDING: \"CANNOT_AFFORD_BUILDING\",\n NO_CONSTRUCTION_SQUARE: \"NO_CONSTRUCTION_SQUARE\",\n DRAGON_UNAVAILABLE: \"DRAGON_UNAVAILABLE\",\n QUEEN_HOLDER_CANNOT_USE_DRAGON: \"QUEEN_HOLDER_CANNOT_USE_DRAGON\",\n BUILDING_NOT_FOUND: \"BUILDING_NOT_FOUND\",\n INVALID_OPTIONAL_ACTION: \"INVALID_OPTIONAL_ACTION\",\n\n // Age of Giants errors\n GIANT_POOL_EMPTY: \"GIANT_POOL_EMPTY\",\n GIANT_NOT_FOUND: \"GIANT_NOT_FOUND\",\n INVALID_GIANT_PLACEMENT: \"INVALID_GIANT_PLACEMENT\",\n NOT_AOG_MODE: \"NOT_AOG_MODE\",\n\n // Origins errors\n FIRE_TOKEN_POOL_EMPTY: \"FIRE_TOKEN_POOL_EMPTY\",\n FIRE_TOKEN_INVALID_POSITION: \"FIRE_TOKEN_INVALID_POSITION\",\n NO_PENDING_FIRE_TOKEN: \"NO_PENDING_FIRE_TOKEN\",\n CANNOT_RECRUIT_CAVEMAN: \"CANNOT_RECRUIT_CAVEMAN\",\n INSUFFICIENT_RESOURCES: \"INSUFFICIENT_RESOURCES\",\n INVALID_CAVEMAN_PLACEMENT: \"INVALID_CAVEMAN_PLACEMENT\",\n CAVEMAN_NOT_FOUND: \"CAVEMAN_NOT_FOUND\",\n NOT_TRIBE_MODE: \"NOT_TRIBE_MODE\",\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\n // Queendomino errors\n ERROR_CANNOT_PLACE_KNIGHT: \"error.cannotPlaceKnight\",\n ERROR_MAX_KNIGHTS_REACHED: \"error.maxKnightsReached\",\n ERROR_KNIGHT_TERRITORY_OCCUPIED: \"error.knightTerritoryOccupied\",\n ERROR_CANNOT_AFFORD_BUILDING: \"error.cannotAffordBuilding\",\n ERROR_NO_CONSTRUCTION_SQUARE: \"error.noConstructionSquare\",\n ERROR_DRAGON_UNAVAILABLE: \"error.dragonUnavailable\",\n ERROR_QUEEN_HOLDER_CANNOT_USE_DRAGON: \"error.queenHolderCannotUseDragon\",\n ERROR_BUILDING_NOT_FOUND: \"error.buildingNotFound\",\n ERROR_INVALID_OPTIONAL_ACTION: \"error.invalidOptionalAction\",\n\n // Age of Giants errors\n ERROR_GIANT_POOL_EMPTY: \"error.giantPoolEmpty\",\n ERROR_GIANT_NOT_FOUND: \"error.giantNotFound\",\n ERROR_INVALID_GIANT_PLACEMENT: \"error.invalidGiantPlacement\",\n ERROR_NOT_AOG_MODE: \"error.notAogMode\",\n\n // Origins errors\n ERROR_FIRE_TOKEN_POOL_EMPTY: \"error.fireTokenPoolEmpty\",\n ERROR_FIRE_TOKEN_INVALID_POSITION: \"error.fireTokenInvalidPosition\",\n ERROR_NO_PENDING_FIRE_TOKEN: \"error.noPendingFireToken\",\n ERROR_CANNOT_RECRUIT_CAVEMAN: \"error.cannotRecruitCaveman\",\n ERROR_INSUFFICIENT_RESOURCES: \"error.insufficientResources\",\n ERROR_INVALID_CAVEMAN_PLACEMENT: \"error.invalidCavemanPlacement\",\n ERROR_CAVEMAN_NOT_FOUND: \"error.cavemanNotFound\",\n ERROR_NOT_TRIBE_MODE: \"error.notTribeMode\",\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 // Queendomino errors\n [TranslationKey.ERROR_CANNOT_PLACE_KNIGHT]: \"Cannot place knight here\",\n [TranslationKey.ERROR_MAX_KNIGHTS_REACHED]:\n \"Maximum number of knights reached (3)\",\n [TranslationKey.ERROR_KNIGHT_TERRITORY_OCCUPIED]:\n \"This territory already has a knight\",\n [TranslationKey.ERROR_CANNOT_AFFORD_BUILDING]:\n \"Not enough coins to purchase this building\",\n [TranslationKey.ERROR_NO_CONSTRUCTION_SQUARE]:\n \"No open construction square available\",\n [TranslationKey.ERROR_DRAGON_UNAVAILABLE]:\n \"The Dragon is not available this round\",\n [TranslationKey.ERROR_QUEEN_HOLDER_CANNOT_USE_DRAGON]:\n \"The Queen holder cannot use the Dragon\",\n [TranslationKey.ERROR_BUILDING_NOT_FOUND]:\n \"Building not found on the Builders Board\",\n [TranslationKey.ERROR_INVALID_OPTIONAL_ACTION]:\n \"Invalid optional action for this game state\",\n\n // Age of Giants errors\n [TranslationKey.ERROR_GIANT_POOL_EMPTY]: \"No giants remaining in the pool\",\n [TranslationKey.ERROR_GIANT_NOT_FOUND]: \"Giant not found on the kingdom\",\n [TranslationKey.ERROR_INVALID_GIANT_PLACEMENT]:\n \"Invalid position for giant placement — must be an uncovered crown\",\n [TranslationKey.ERROR_NOT_AOG_MODE]: \"Age of Giants mode is not enabled\",\n\n // Origins errors\n [TranslationKey.ERROR_FIRE_TOKEN_POOL_EMPTY]:\n \"No fire tokens remaining in the pool\",\n [TranslationKey.ERROR_FIRE_TOKEN_INVALID_POSITION]:\n \"Invalid position for fire token placement\",\n [TranslationKey.ERROR_NO_PENDING_FIRE_TOKEN]:\n \"No pending fire token to place\",\n [TranslationKey.ERROR_CANNOT_RECRUIT_CAVEMAN]: \"Cannot recruit a caveman\",\n [TranslationKey.ERROR_INSUFFICIENT_RESOURCES]:\n \"Insufficient resources for this action\",\n [TranslationKey.ERROR_INVALID_CAVEMAN_PLACEMENT]:\n \"Invalid position for caveman placement\",\n [TranslationKey.ERROR_CAVEMAN_NOT_FOUND]: \"Caveman not found\",\n [TranslationKey.ERROR_NOT_TRIBE_MODE]: \"Tribe mode is not enabled\",\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 [ErrorCode.CANNOT_PLACE_KNIGHT]: TranslationKey.ERROR_CANNOT_PLACE_KNIGHT,\n [ErrorCode.MAX_KNIGHTS_REACHED]: TranslationKey.ERROR_MAX_KNIGHTS_REACHED,\n [ErrorCode.KNIGHT_TERRITORY_OCCUPIED]:\n TranslationKey.ERROR_KNIGHT_TERRITORY_OCCUPIED,\n [ErrorCode.CANNOT_AFFORD_BUILDING]:\n TranslationKey.ERROR_CANNOT_AFFORD_BUILDING,\n [ErrorCode.NO_CONSTRUCTION_SQUARE]:\n TranslationKey.ERROR_NO_CONSTRUCTION_SQUARE,\n [ErrorCode.DRAGON_UNAVAILABLE]: TranslationKey.ERROR_DRAGON_UNAVAILABLE,\n [ErrorCode.QUEEN_HOLDER_CANNOT_USE_DRAGON]:\n TranslationKey.ERROR_QUEEN_HOLDER_CANNOT_USE_DRAGON,\n [ErrorCode.BUILDING_NOT_FOUND]: TranslationKey.ERROR_BUILDING_NOT_FOUND,\n [ErrorCode.INVALID_OPTIONAL_ACTION]:\n TranslationKey.ERROR_INVALID_OPTIONAL_ACTION,\n [ErrorCode.GIANT_POOL_EMPTY]: TranslationKey.ERROR_GIANT_POOL_EMPTY,\n [ErrorCode.GIANT_NOT_FOUND]: TranslationKey.ERROR_GIANT_NOT_FOUND,\n [ErrorCode.INVALID_GIANT_PLACEMENT]:\n TranslationKey.ERROR_INVALID_GIANT_PLACEMENT,\n [ErrorCode.NOT_AOG_MODE]: TranslationKey.ERROR_NOT_AOG_MODE,\n [ErrorCode.FIRE_TOKEN_POOL_EMPTY]: TranslationKey.ERROR_FIRE_TOKEN_POOL_EMPTY,\n [ErrorCode.FIRE_TOKEN_INVALID_POSITION]:\n TranslationKey.ERROR_FIRE_TOKEN_INVALID_POSITION,\n [ErrorCode.NO_PENDING_FIRE_TOKEN]: TranslationKey.ERROR_NO_PENDING_FIRE_TOKEN,\n [ErrorCode.CANNOT_RECRUIT_CAVEMAN]:\n TranslationKey.ERROR_CANNOT_RECRUIT_CAVEMAN,\n [ErrorCode.INSUFFICIENT_RESOURCES]:\n TranslationKey.ERROR_INSUFFICIENT_RESOURCES,\n [ErrorCode.INVALID_CAVEMAN_PLACEMENT]:\n TranslationKey.ERROR_INVALID_CAVEMAN_PLACEMENT,\n [ErrorCode.CAVEMAN_NOT_FOUND]: TranslationKey.ERROR_CAVEMAN_NOT_FOUND,\n [ErrorCode.NOT_TRIBE_MODE]: TranslationKey.ERROR_NOT_TRIBE_MODE,\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 { ConstructBuildingCommand } from \"@application/commands/constructBuildingCommand.js\";\nimport {\n ActionExecutionError,\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { GameState } 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 { ConstructBuildingUseCase } from \"@core/useCases/constructBuilding.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype ConstructBuildingHandler = (\n command: ConstructBuildingCommand,\n) => GameState;\n\nexport const constructBuildingHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: ConstructBuildingUseCase,\n ): ConstructBuildingHandler =>\n (command: ConstructBuildingCommand) => {\n const { game, lordId, buildingId, position } = command;\n logger.info(\n `Constructing building: ${buildingId} for lord: ${lordId} at position: ${JSON.stringify(\n position,\n )} in game: ${game.id}`,\n );\n\n if (game.nextAction.nextAction !== \"constructBuilding\") {\n logger.error(\n `Required game with constructBuilding action but got: ${game.nextAction.nextAction}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"constructBuilding\",\n actual: game.nextAction.nextAction,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(game, lordId, buildingId, position);\n\n if (isErr(result)) {\n logger.error(`Error constructing building: ${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 buildingId: command.buildingId,\n position: command.position,\n },\n );\n }\n\n logger.info(\n `Building constructed: ${buildingId} for lord: ${lordId} at position: ${JSON.stringify(\n position,\n )} 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 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 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 // Pass giant positions to reduce crowns covered by giants in scoring\n const giantPositions = player.giants?.map((g) => g.position);\n const result = calculateScoreUseCase(kingdom, giantPositions);\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 { PlaceFireTokenCommand } from \"@application/commands/placeFireTokenCommand.js\";\nimport {\n ActionExecutionError,\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { GameState } 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 { PlaceFireTokenUseCase } from \"@core/useCases/placeFireToken.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype PlaceFireTokenHandler = (command: PlaceFireTokenCommand) => GameState;\n\nexport const placeFireTokenHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: PlaceFireTokenUseCase,\n ): PlaceFireTokenHandler =>\n (command: PlaceFireTokenCommand) => {\n const { game, lordId, position } = command;\n logger.info(\n `Placing fire token for lord: ${lordId} at position: ${JSON.stringify(\n position,\n )} in game: ${game.id}`,\n );\n\n if (game.nextAction.nextAction !== \"placeFireToken\") {\n logger.error(\n `Required game with placeFireToken action but got: ${game.nextAction.nextAction}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"placeFireToken\",\n actual: game.nextAction.nextAction,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(game, lordId, position);\n\n if (isErr(result)) {\n logger.error(`Error placing fire token: ${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 },\n );\n }\n\n logger.info(\n `Fire token placed for lord: ${lordId} at position: ${JSON.stringify(\n position,\n )} in game: ${game.id}`,\n );\n return result.value;\n };\n","import type { PlaceGiantCommand } from \"@application/commands/placeGiantCommand.js\";\nimport {\n ActionExecutionError,\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { GameState } 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 { PlaceGiantUseCase } from \"@core/useCases/placeGiant.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype PlaceGiantHandler = (command: PlaceGiantCommand) => GameState;\n\nexport const placeGiantHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: PlaceGiantUseCase,\n ): PlaceGiantHandler =>\n (command: PlaceGiantCommand) => {\n const { game, lordId, position } = command;\n logger.info(\n `Placing giant for lord: ${lordId} at position: ${JSON.stringify(position)} in game: ${game.id}`,\n );\n\n if (game.nextAction.nextAction !== \"placeGiant\") {\n logger.error(\n `Required game with placeGiant action but got: ${game.nextAction.nextAction}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"placeGiant\",\n actual: game.nextAction.nextAction,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(game, lordId, position);\n\n if (isErr(result)) {\n logger.error(`Error placing giant: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new ActionExecutionError(\n translateErrorCode(translator, code),\n code,\n { gameId: game.id, lordId, position },\n );\n }\n\n logger.info(`Giant placed for lord: ${lordId} in game: ${game.id}`);\n return result.value;\n };\n","import type { PlaceKnightCommand } from \"@application/commands/placeKnightCommand.js\";\nimport {\n ActionExecutionError,\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { GameState } 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 { PlaceKnightUseCase } from \"@core/useCases/placeKnight.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype PlaceKnightHandler = (command: PlaceKnightCommand) => GameState;\n\nexport const placeKnightHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: PlaceKnightUseCase,\n ): PlaceKnightHandler =>\n (command: PlaceKnightCommand) => {\n const { game, lordId, position } = command;\n logger.info(\n `Placing knight for lord: ${lordId} at position: ${JSON.stringify(\n position,\n )} in game: ${game.id}`,\n );\n\n if (game.nextAction.nextAction !== \"placeKnight\") {\n logger.error(\n `Required game with placeKnight action but got: ${game.nextAction.nextAction}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"placeKnight\",\n actual: game.nextAction.nextAction,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(game, lordId, position);\n\n if (isErr(result)) {\n logger.error(`Error placing knight: ${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 },\n );\n }\n\n logger.info(\n `Knight placed for lord: ${lordId} at position: ${JSON.stringify(\n position,\n )} in game: ${game.id}`,\n );\n return result.value;\n };\n","import type { RecruitCavemanCommand } from \"@application/commands/recruitCavemanCommand.js\";\nimport {\n ActionExecutionError,\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { GameState } 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 { RecruitCavemanUseCase } from \"@core/useCases/recruitCaveman.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype RecruitCavemanHandler = (command: RecruitCavemanCommand) => GameState;\n\nexport const recruitCavemanHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: RecruitCavemanUseCase,\n ): RecruitCavemanHandler =>\n (command: RecruitCavemanCommand) => {\n const { game, lordId, cavemanId, position, resourcePositions } = command;\n logger.info(\n `Recruiting caveman ${cavemanId} for lord: ${lordId} in game: ${game.id}`,\n );\n\n if (game.nextAction.nextAction !== \"recruitCaveman\") {\n logger.error(\n `Required game with recruitCaveman action but got: ${game.nextAction.nextAction}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"recruitCaveman\",\n actual: game.nextAction.nextAction,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(\n game,\n lordId,\n cavemanId,\n position,\n resourcePositions,\n );\n\n if (isErr(result)) {\n logger.error(`Error recruiting caveman: ${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,\n cavemanId,\n position,\n },\n );\n }\n\n logger.info(\n `Caveman ${cavemanId} recruited for lord: ${lordId} in game: ${game.id}`,\n );\n return result.value;\n };\n","import type { SendGiantCommand } from \"@application/commands/sendGiantCommand.js\";\nimport {\n ActionExecutionError,\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { GameState } 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 { SendGiantUseCase } from \"@core/useCases/sendGiant.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype SendGiantHandler = (command: SendGiantCommand) => GameState;\n\nexport const sendGiantHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: SendGiantUseCase,\n ): SendGiantHandler =>\n (command: SendGiantCommand) => {\n const { game, lordId, giantIndex, targetPlayerId, targetCrownPosition } =\n command;\n logger.info(\n `Sending giant for lord: ${lordId} to player: ${targetPlayerId} in game: ${game.id}`,\n );\n\n if (game.nextAction.nextAction !== \"sendGiant\") {\n logger.error(\n `Required game with sendGiant action but got: ${game.nextAction.nextAction}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"sendGiant\",\n actual: game.nextAction.nextAction,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(\n game,\n lordId,\n giantIndex,\n targetPlayerId,\n targetCrownPosition,\n );\n\n if (isErr(result)) {\n logger.error(`Error sending giant: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new ActionExecutionError(\n translateErrorCode(translator, code),\n code,\n { gameId: game.id, lordId, targetPlayerId, targetCrownPosition },\n );\n }\n\n logger.info(\n `Giant sent from lord: ${lordId} to player: ${targetPlayerId} in game: ${game.id}`,\n );\n return result.value;\n };\n","import type { GameState } from \"@core/domain/types/index.js\";\nimport { err, ok, 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 { SkipOptionalActionCommand } from \"@application/commands/skipOptionalActionCommand.js\";\nimport {\n ActionExecutionError,\n type ErrorCodeType,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { GameState } 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 { SkipOptionalActionUseCase } from \"@core/useCases/skipOptionalAction.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype SkipOptionalActionHandler = (\n command: SkipOptionalActionCommand,\n) => GameState;\n\nexport const skipOptionalActionHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: SkipOptionalActionUseCase,\n ): SkipOptionalActionHandler =>\n (command: SkipOptionalActionCommand) => {\n const { game, lordId } = command;\n logger.info(\n `Skipping optional action for lord: ${lordId} in game: ${game.id}`,\n );\n\n const result = useCase(game, lordId);\n\n if (isErr(result)) {\n logger.error(`Error skipping optional action: ${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 logger.info(\n `Optional action skipped for lord: ${lordId} in game: ${game.id}`,\n );\n return result.value;\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 { UseDragonCommand } from \"@application/commands/useDragonCommand.js\";\nimport {\n ActionExecutionError,\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { GameState } 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 { UseDragonUseCase } from \"@core/useCases/useDragon.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype UseDragonHandler = (command: UseDragonCommand) => GameState;\n\nexport const useDragonHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: UseDragonUseCase,\n ): UseDragonHandler =>\n (command: UseDragonCommand) => {\n const { game, lordId, buildingId } = command;\n logger.info(\n `Using dragon on building: ${buildingId} for lord: ${lordId} in game: ${game.id}`,\n );\n\n if (game.nextAction.nextAction !== \"useDragon\") {\n logger.error(\n `Required game with useDragon action but got: ${game.nextAction.nextAction}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"useDragon\",\n actual: game.nextAction.nextAction,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(game, lordId, buildingId);\n\n if (isErr(result)) {\n logger.error(`Error using dragon: ${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 buildingId: command.buildingId,\n },\n );\n }\n\n logger.info(\n `Dragon used on building: ${buildingId} for lord: ${lordId} in game: ${game.id}`,\n );\n return result.value;\n };\n","import { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type { ExtraRule } from \"@core/domain/types/rule.js\";\nimport { err, ok, 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 { Ground } from \"./domino.js\";\nimport type { Position } from \"./kingdom.js\";\nimport type { ObjectValues } from \"./utils.js\";\n\n// ─── Giants ─────────────────────────────────────────────────────────\n\n/**\n * A giant placed on a player's kingdom, covering a crown.\n * The covered crown does not count for scoring.\n */\nexport type PlacedGiant = {\n /** Position on the kingdom grid where the giant covers a crown */\n position: Position;\n};\n\n// ─── Quest Tiles ────────────────────────────────────────────────────\n\n/**\n * All quest tile types available in Age of Giants.\n */\nexport const questTypes = {\n /** 5pts per matching terrain tile adjacent (8-dir) to castle */\n localTrade: \"localTrade\",\n /** 5pts per matching terrain tile in the 4 corners of the kingdom */\n kingdomBorders: \"kingdomBorders\",\n /** 5pts if kingdom is complete (no discarded dominos) */\n harmony: \"harmony\",\n /** 10pts if castle is in the center of the kingdom */\n middleKingdom: \"middleKingdom\",\n /** 20pts if castle is in one of the 4 corners of the kingdom */\n lostCorner: \"lostCorner\",\n /** 10pts per alignment of 3+ tiles with crowns (H/V/diagonal) */\n megalomania: \"megalomania\",\n /** 10pts per property of 5+ wheat/forest/sea/plain tiles with 0 crowns */\n austereKing: \"austereKing\",\n} as const;\n\nexport type QuestType = ObjectValues<typeof questTypes>;\n\n/**\n * A quest tile drawn at game start.\n * Provides a specific end-of-game bonus scoring condition.\n */\nexport type QuestTile = {\n /** Unique identifier for the quest tile */\n id: number;\n /** Type of quest determining the scoring rule */\n type: QuestType;\n /** Display name of the quest */\n name: string;\n /** Description of the scoring condition */\n description: string;\n /** Points awarded per match (e.g., 5 for localTrade, 10 for megalomania) */\n points: number;\n /** Target terrain type (only for localTrade and kingdomBorders quests) */\n terrain?: Ground;\n};\n\n// ─── Age of Giants Game State ───────────────────────────────────────\n\n/**\n * Complete Age of Giants-specific game state.\n * Stored as an optional field on Game and only present in AoG modes.\n */\nexport type AgeOfGiantsState = {\n /** Number of giant figurines remaining in the pool (starts at 6) */\n giantPool: number;\n /** The 2 quest tiles drawn for this game */\n questTiles: QuestTile[];\n};\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 \"grassland\",\n \"lake\",\n \"jungle\",\n \"quarry\",\n \"desert\",\n \"volcano\",\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. In Origins, represents fire symbols. */\n crowns: Crown;\n /** Whether this tile has a construction square for buildings (Queendomino) */\n hasConstructionSquare?: boolean;\n /** Number of volcanic craters on this tile (Origins, 1-3). Determines fire token type. */\n volcanoCraters?: number;\n /** Whether this tile has a giant icon (Age of Giants, letter dominos A-F) */\n hasGiant?: boolean;\n /** Whether this tile has footprint icons (Age of Giants, dominos 49-54) */\n hasFootprint?: boolean;\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). Letter dominos use fractional numbers (A=0.01...F=0.06). */\n number: number;\n /** Display letter for Age of Giants giant dominos (A-F). Undefined for numbered dominos. */\n letter?: string;\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 { 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","import type { Position } from \"./kingdom.js\";\nimport type { ObjectValues } from \"./utils.js\";\n\n// ─── Origins Sub-Modes ───────────────────────────────────────────────\n\n/**\n * The three gameplay modes within Kingdomino Origins.\n * Discovery is the base, Totem adds resources/totems, Tribe adds cavemen.\n */\nexport const originsSubModes = {\n discovery: \"Discovery\",\n totem: \"Totem\",\n tribe: \"Tribe\",\n} as const;\n\nexport type OriginsSubMode = ObjectValues<typeof originsSubModes>;\n\n// ─── Fire Tokens ─────────────────────────────────────────────────────\n\n/**\n * Represents the pool of available fire tokens.\n * Discovery Mode starts with: 5×1-fire, 4×2-fire, 1×3-fire = 10 total.\n */\nexport type FireTokenPool = {\n ones: number;\n twos: number;\n threes: number;\n};\n\n/**\n * A fire token that has been placed on a player's kingdom.\n */\nexport type PlacedFireToken = {\n /** Number of fires on this token (1, 2, or 3) */\n fires: 1 | 2 | 3;\n /** Position on the kingdom grid */\n position: Position;\n};\n\n/**\n * Tracks which volcano granted the current pending fire token,\n * so the placement validation knows the launch position.\n */\nexport type PendingFireToken = {\n /** Number of fires on the token to place */\n fires: 1 | 2 | 3;\n /** Position of the volcano that granted this token */\n volcanoPosition: Position;\n};\n\n// ─── Resources ───────────────────────────────────────────────────────\n\n/**\n * Types of wooden resources in Origins.\n * Each maps to a specific terrain type.\n */\nexport const resourceTypes = {\n mammoth: \"mammoth\",\n fish: \"fish\",\n mushroom: \"mushroom\",\n flint: \"flint\",\n} as const;\n\nexport type ResourceType = ObjectValues<typeof resourceTypes>;\n\n/**\n * A wooden resource placed on a player's kingdom tile.\n */\nexport type Resource = {\n /** Type of resource */\n type: ResourceType;\n /** Position on the kingdom grid */\n position: Position;\n};\n\n// ─── Totems ──────────────────────────────────────────────────────────\n\n/**\n * Tracks which player holds each totem tile.\n * null means no player currently holds that totem.\n */\nexport type TotemState = Record<ResourceType, string | null>;\n\n/**\n * Point values for each totem tile at end of game.\n */\nexport type TotemBonus = Record<ResourceType, number>;\n\n// ─── Cavemen ─────────────────────────────────────────────────────────\n\n/**\n * The 7 kinds of hunter-gatherers.\n * Each has a specific scoring rule based on surrounding resources.\n */\nexport const hunterGathererKinds = {\n /** Scores per mammoth adjacent */\n mammothHunter: \"mammothHunter\",\n /** Scores per fish adjacent */\n fisherman: \"fisherman\",\n /** Scores per mushroom adjacent */\n mushroomPicker: \"mushroomPicker\",\n /** Scores per flint adjacent */\n flintCollector: \"flintCollector\",\n /** Scores per unique resource type adjacent */\n trapper: \"trapper\",\n /** Scores per total resource adjacent (any type) */\n gatherer: \"gatherer\",\n /** Scores per fire symbol adjacent (Fire Lady) */\n fireLady: \"fireLady\",\n} as const;\n\nexport type HunterGathererKind = ObjectValues<typeof hunterGathererKinds>;\n\n/**\n * Warrior size categories with their power values.\n */\nexport const warriorTypes = {\n small: \"small\",\n amazon: \"amazon\",\n oafish: \"oafish\",\n} as const;\n\nexport type WarriorType = ObjectValues<typeof warriorTypes>;\n\n/**\n * Power values for each warrior type.\n */\nexport const WARRIOR_POWER: Record<WarriorType, number> = {\n small: 1,\n amazon: 2,\n oafish: 3,\n};\n\n/**\n * A hunter-gatherer caveman tile.\n */\nexport type HunterGathererTile = {\n kind: \"hunterGatherer\";\n id: number;\n /** Specific hunter-gatherer type determining scoring rule */\n hunterType: HunterGathererKind;\n /** Points per matching adjacent resource/symbol */\n pointsPerMatch: number;\n};\n\n/**\n * A warrior caveman tile.\n */\nexport type WarriorTile = {\n kind: \"warrior\";\n id: number;\n /** Warrior size category */\n warriorType: WarriorType;\n /** Combat power (1, 2, or 3) */\n power: number;\n};\n\n/** Discriminated union of all caveman tile types. */\nexport type CavemanTile = HunterGathererTile | WarriorTile;\n\n/**\n * A caveman tile placed on a player's kingdom.\n */\nexport type PlacedCaveman = {\n caveman: CavemanTile;\n position: Position;\n};\n\n/**\n * The Cave board used in Tribe mode.\n * Shows 4 visible caveman tiles and a face-down draw pile.\n */\nexport type CaveBoard = {\n /** Up to 4 visible caveman tiles available for recruitment */\n visible: CavemanTile[];\n /** Face-down draw pile */\n drawPile: CavemanTile[];\n};\n\n// ─── Origins Game State ──────────────────────────────────────────────\n\n/**\n * Complete Origins-specific game state.\n * Stored as an optional field on Game and only present in Origins modes.\n */\nexport type OriginsState = {\n /** Which Origins sub-mode is being played */\n subMode: OriginsSubMode;\n /** Available fire tokens pool */\n fireTokenPool: FireTokenPool;\n /** Pending fire token to place (set after placing a volcano domino) */\n pendingFireToken?: PendingFireToken;\n /** Totem holder state (Totem mode only) */\n totems?: TotemState;\n /** Cave board state (Tribe mode only) */\n caveBoard?: CaveBoard;\n};\n","import type { PlacedGiant } from \"./ageOfGiants.js\";\nimport type { PlacedBuilding } from \"./building.js\";\nimport type { Kingdom, Position } from \"./kingdom.js\";\nimport type { PlacedCaveman, PlacedFireToken, Resource } from \"./origins.js\";\nimport type { ObjectValues } from \"./utils.js\";\n\n/**\n * Represents a knight placed on a player's kingdom (Queendomino).\n */\nexport type Knight = {\n /** ID of the player who owns this knight */\n playerId: string;\n /** Position on the kingdom grid where the knight is placed */\n position: Position;\n};\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 /** Number of coins the player has (Queendomino) */\n coins?: number;\n /** Number of towers the player has (Queendomino) */\n towers?: number;\n /** Knights placed on the kingdom (Queendomino) */\n knights?: Knight[];\n /** Buildings placed on the kingdom (Queendomino) */\n buildings?: PlacedBuilding[];\n /** Fire tokens placed on the kingdom (Origins) */\n fireTokens?: PlacedFireToken[];\n /** Wooden resources on the kingdom (Origins Totem/Tribe) */\n resources?: Resource[];\n /** Cavemen placed on the kingdom (Origins Tribe) */\n cavemen?: PlacedCaveman[];\n /** Giants placed on the kingdom covering crowns (Age of Giants) */\n giants?: PlacedGiant[];\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 /** Place a knight on the just-placed domino (Queendomino, optional) */\n placeKnight: \"placeKnight\",\n /** Construct a building on a construction square (Queendomino, optional) */\n constructBuilding: \"constructBuilding\",\n /** Use the Dragon to burn a building tile (Queendomino, optional) */\n useDragon: \"useDragon\",\n /** Skip the current optional action (Queendomino/Origins/AoG) */\n skipOptionalAction: \"skipOptionalAction\",\n /** Place a giant on a crown after placing a giant domino (Age of Giants, mandatory) */\n placeGiant: \"placeGiant\",\n /** Send a giant to an opponent after placing a footprint domino (Age of Giants, optional) */\n sendGiant: \"sendGiant\",\n /** Place a fire token after placing a volcano domino (Origins, optional) */\n placeFireToken: \"placeFireToken\",\n /** Recruit a caveman from the cave board (Origins Tribe, optional) */\n recruitCaveman: \"recruitCaveman\",\n} as const;\n\n/** Union type of all player actions */\nexport type PlayerActions = ObjectValues<typeof playerActions>;\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 { toExtraRule } from \"@core/domain/entities/rule.js\";\nimport {\n type ExtraRule,\n type GameWithNextStep,\n gameSteps,\n type NextStep,\n} from \"@core/domain/types/index.js\";\nimport type { DominoesRepository } from \"@core/portServerside/dominoesRepository.js\";\nimport type { RuleRepository } from \"@core/portServerside/ruleRepository.js\";\nimport type { ShuffleMethod } from \"@core/portServerside/shuffleMethod.js\";\nimport { isErr, ok, type Result } from \"@utils/result.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(\n (r) => r.name === \"The Mighty Duel\",\n );\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 type { Domino } from \"@core/domain/types/domino.js\";\n\nconst AOG_MODE_PREFIX = \"AgeOfGiants\";\n\n/**\n * Checks whether the given mode name is an Age of Giants mode.\n */\nexport const isAgeOfGiantsMode = (modeName: string): boolean =>\n modeName.startsWith(AOG_MODE_PREFIX);\n\n/**\n * Checks whether the mode is Age of Giants combined with QueenDomino.\n */\nexport const isAgeOfGiantsQueenDominoMode = (modeName: string): boolean =>\n modeName === \"AgeOfGiants-QueenDomino\";\n\n/**\n * Checks whether a domino is a \"giant domino\" (has a giant icon on one of its tiles).\n * Giant dominos trigger the mandatory placeGiant action.\n */\nexport const isGiantDomino = (domino: Domino): boolean =>\n (domino.left.hasGiant ?? false) || (domino.right.hasGiant ?? false);\n\n/**\n * Checks whether a domino is a \"footprint domino\" (has footprint icons on one of its tiles).\n * Footprint dominos trigger the optional sendGiant action.\n */\nexport const isFootprintDomino = (domino: Domino): boolean =>\n (domino.left.hasFootprint ?? false) || (domino.right.hasFootprint ?? false);\n","import type { Player } from \"@core/domain/types/player.js\";\n\n/** Default starting coins for each player in Queendomino */\nexport const STARTING_COINS = 7;\n\n/** Maximum number of knights a player can place */\nexport const MAX_KNIGHTS = 3;\n\nexport const initializeCoins = (): number => STARTING_COINS;\n\nexport const addCoins = (player: Player, amount: number): Player => ({\n ...player,\n coins: (player.coins ?? 0) + amount,\n});\n\nexport const removeCoins = (player: Player, amount: number): Player => ({\n ...player,\n coins: (player.coins ?? 0) - amount,\n});\n\nexport const canAfford = (player: Player, cost: number): boolean =>\n (player.coins ?? 0) >= cost;\n\nexport const addTowers = (player: Player, amount: number): Player => ({\n ...player,\n towers: (player.towers ?? 0) + amount,\n});\n\nexport const getTowerCount = (player: Player): number => player.towers ?? 0;\n","import {\n type Crown,\n type EmptyGround,\n type EmptyTile,\n GROUND,\n type Ground,\n type Tile,\n} from \"@core/domain/types/domino.js\";\n\nconst isGround = (ground: unknown): ground is Ground => {\n return GROUND.includes(ground as 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 { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport {\n type Domino,\n type EmptyTile,\n GRIDSIZE,\n type Kingdom,\n MAX_KINGDOM_SIZE,\n type Position,\n type Rotation,\n type Tile,\n} from \"@core/domain/types/index.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 (\n exceedsMaxSize(\n kingdom,\n firstTile.position,\n secondTile.position,\n maxKingdomSize,\n )\n ) {\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 type { OriginsSubMode } from \"@core/domain/types/origins.js\";\n\nconst ORIGINS_MODE_PREFIX = \"KingdominoOrigins-\";\n\n/**\n * Checks whether the given mode name is an Origins mode.\n */\nexport const isOriginsMode = (modeName: string): boolean =>\n modeName.startsWith(ORIGINS_MODE_PREFIX);\n\n/**\n * Extracts the sub-mode from an Origins mode name.\n * Returns undefined if not an Origins mode.\n */\nexport const getOriginsSubMode = (\n modeName: string,\n): OriginsSubMode | undefined => {\n if (!isOriginsMode(modeName)) return undefined;\n return modeName.slice(ORIGINS_MODE_PREFIX.length) as OriginsSubMode;\n};\n\n/**\n * Checks whether the mode is a Totem or Tribe mode (modes that use resources).\n */\nexport const isResourceMode = (modeName: string): boolean => {\n const sub = getOriginsSubMode(modeName);\n return sub === \"Totem\" || sub === \"Tribe\";\n};\n\n/**\n * Checks whether the mode is the Tribe mode (has cave board + cavemen).\n */\nexport const isTribeMode = (modeName: string): boolean => {\n return getOriginsSubMode(modeName) === \"Tribe\";\n};\n\n/**\n * Checks whether the mode is the Totem mode (has totem majority tiles).\n */\nexport const isTotemMode = (modeName: string): boolean => {\n return getOriginsSubMode(modeName) === \"Totem\";\n};\n","import { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type { Kingdom } from \"@core/domain/types/kingdom.js\";\nimport type { Player } from \"@core/domain/types/player.js\";\nimport { err, isErr, ok, type Result } from \"@utils/result.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 type { PlayerInput } from \"@application/commands/addPlayersCommand.js\";\nimport {\n isAgeOfGiantsMode,\n isAgeOfGiantsQueenDominoMode,\n} from \"@core/domain/entities/ageOfGiantsHelpers.js\";\nimport { STARTING_COINS } from \"@core/domain/entities/economy.js\";\nimport {\n createEmptyKingdom,\n placeCastle,\n} from \"@core/domain/entities/kingdom.js\";\nimport {\n isOriginsMode,\n isResourceMode,\n isTribeMode,\n} from \"@core/domain/entities/originsHelpers.js\";\nimport { createPlayer } from \"@core/domain/entities/player.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.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 { err, isErr, ok, type Result } from \"@utils/result.js\";\nimport { createSeededShuffle } from \"@utils/seededShuffle.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 const isAoG = isAgeOfGiantsMode(game.mode.name);\n const maxPlayers = isAoG ? 5 : 4;\n const minPlayers = isAoG ? 2 : 1;\n\n if (\n !players ||\n players.length < minPlayers ||\n players.length > maxPlayers\n ) {\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 const id = uuidMethod();\n const newPlayer = createPlayer(name, id, kingdom, bot);\n\n if (isErr(newPlayer)) {\n return newPlayer;\n }\n\n // Initialize Queendomino-specific player state\n if (game.mode.name === \"QueenDomino\") {\n newPlayer.value.coins = STARTING_COINS;\n newPlayer.value.towers = 0;\n newPlayer.value.knights = [];\n newPlayer.value.buildings = [];\n }\n\n // Initialize Age of Giants-specific player state\n if (isAoG) {\n newPlayer.value.giants = [];\n // AoG-QueenDomino also needs Queendomino player state\n if (isAgeOfGiantsQueenDominoMode(game.mode.name)) {\n newPlayer.value.coins = STARTING_COINS;\n newPlayer.value.towers = 0;\n newPlayer.value.knights = [];\n newPlayer.value.buildings = [];\n }\n }\n\n // Initialize Origins-specific player state\n if (isOriginsMode(game.mode.name)) {\n newPlayer.value.fireTokens = [];\n if (isResourceMode(game.mode.name)) {\n newPlayer.value.resources = [];\n }\n if (isTribeMode(game.mode.name)) {\n newPlayer.value.cavemen = [];\n }\n }\n\n newPlayers.push(newPlayer.value);\n }\n\n // set rules\n const rules = ruleRepository.getAll();\n const basicRules =\n isAoG && rules.aogBasic\n ? rules.aogBasic[newPlayers.length]\n : 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, Position, Score } from \"@core/domain/types/index.js\";\nimport { ok, type Result } from \"@utils/result.js\";\n\nexport type CalculateScoreUseCase = (\n kingdom: Kingdom,\n giantPositions?: Position[],\n) => Result<Score>;\n\ntype Property = {\n size: number;\n crowns: number;\n};\n\nexport const calculateScoreUseCase: CalculateScoreUseCase = (\n kingdom,\n giantPositions,\n) => {\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 // Build a set for fast giant position lookup\n const giantSet = new Set<string>();\n if (giantPositions) {\n for (const pos of giantPositions) {\n giantSet.add(`${pos.x},${pos.y}`);\n }\n }\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\n // Count crowns, but subtract 1 for each giant covering this position\n let tileCrowns = current.crowns;\n if (giantSet.has(`${cx},${cy}`)) {\n tileCrowns = Math.max(0, tileCrowns - 1);\n }\n crowns += tileCrowns;\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 {\n type PlayerActions,\n playerActions,\n} 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\n/**\n * Queendomino optional action sequence after placeDomino:\n * placeKnight → constructBuilding → useDragon → pickDomino\n *\n * Given the current optional action, returns the next one in the sequence.\n */\nconst QUEENDOMINO_ACTION_SEQUENCE: PlayerActions[] = [\n playerActions.placeKnight,\n playerActions.constructBuilding,\n playerActions.useDragon,\n playerActions.pickDomino,\n];\n\nexport const nextQueenDominoAction = (\n currentAction: PlayerActions,\n): PlayerActions => {\n const index = QUEENDOMINO_ACTION_SEQUENCE.indexOf(currentAction);\n if (index === -1 || index >= QUEENDOMINO_ACTION_SEQUENCE.length - 1) {\n return playerActions.pickDomino;\n }\n return QUEENDOMINO_ACTION_SEQUENCE[index + 1]!;\n};\n\n/**\n * Age of Giants action sequence after placeDomino (when placeGiant/sendGiant is triggered):\n * placeGiant or sendGiant → pickDomino\n *\n * When combined with QueenDomino:\n * placeGiant or sendGiant → placeKnight → constructBuilding → useDragon → pickDomino\n */\nconst AOG_QD_ACTION_SEQUENCE: PlayerActions[] = [\n playerActions.placeGiant, // or sendGiant (handled dynamically)\n playerActions.placeKnight,\n playerActions.constructBuilding,\n playerActions.useDragon,\n playerActions.pickDomino,\n];\n\n/**\n * Returns the next action after an AoG action.\n * @param currentAction - The current AoG action being completed or skipped\n * @param isQueenDomino - Whether the game combines AoG with QueenDomino\n */\nexport const nextAgeOfGiantsAction = (\n currentAction: PlayerActions,\n isQueenDomino: boolean,\n): PlayerActions => {\n if (!isQueenDomino) {\n // Simple AoG: after giant action, go to pickDomino\n return playerActions.pickDomino;\n }\n\n // AoG + QueenDomino: use the combined sequence\n const sequence = AOG_QD_ACTION_SEQUENCE;\n // Map sendGiant to the same position as placeGiant in the sequence\n const normalizedAction =\n currentAction === playerActions.sendGiant\n ? playerActions.placeGiant\n : currentAction;\n\n const index = sequence.indexOf(normalizedAction);\n if (index === -1 || index >= sequence.length - 1) {\n return playerActions.pickDomino;\n }\n return sequence[index + 1]!;\n};\n\n/**\n * Origins Discovery/Totem action sequence after placeDomino:\n * placeFireToken → pickDomino\n *\n * In Origins, placing a fire token is optional (only after placing a volcano domino).\n */\nconst ORIGINS_DISCOVERY_SEQUENCE: PlayerActions[] = [\n playerActions.placeFireToken,\n playerActions.pickDomino,\n];\n\n/**\n * Origins Tribe action sequence after placeDomino:\n * placeFireToken → pickDomino → recruitCaveman\n *\n * recruitCaveman happens after picking a new domino (unique to Tribe mode).\n */\nconst ORIGINS_TRIBE_SEQUENCE: PlayerActions[] = [\n playerActions.placeFireToken,\n playerActions.pickDomino,\n playerActions.recruitCaveman,\n];\n\n/**\n * Returns the next Origins action in the sequence.\n * @param currentAction - The current action being completed or skipped\n * @param isTribe - Whether the game is in Tribe mode\n */\nexport const nextOriginsAction = (\n currentAction: PlayerActions,\n isTribe: boolean,\n): PlayerActions => {\n const sequence = isTribe\n ? ORIGINS_TRIBE_SEQUENCE\n : ORIGINS_DISCOVERY_SEQUENCE;\n const index = sequence.indexOf(currentAction);\n if (index === -1 || index >= sequence.length - 1) {\n // Fallback: if we're past the end, signal turn done\n return playerActions.pickDomino;\n }\n return sequence[index + 1]!;\n};\n","import {\n allLordsHavePlayed,\n canPick,\n nextLordWithAction,\n resetLordsActions,\n updateLordOrder,\n} from \"@core/domain/entities/lord.js\";\nimport { isTribeMode } from \"@core/domain/entities/originsHelpers.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type { GameWithNextAction } from \"@core/domain/types/game.js\";\nimport { playerActions } from \"@core/domain/types/player.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 const isTribe = isTribeMode(game.mode.name);\n\n // update lords - always mark turn ended\n const updatedLords = game.lords.map((lord) =>\n lord.id === currentLord.id\n ? {\n ...lord,\n hasPick: true,\n turnEnded: true,\n dominoPicked: selectedDomino.domino,\n }\n : lord,\n );\n\n const turnEnded = allLordsHavePlayed(updatedLords);\n\n if (turnEnded) {\n // All lords have picked - perform turn transition\n const lords = resetLordsActions(updateLordOrder(updatedLords));\n const updatedTurn = game.turn + 1;\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\n // Age of Giants: discard some dominos from the sorted line before selection\n const discardCount = game.rules.basic.dominoesDiscardedPerTurn ?? 0;\n if (discardCount > 0) {\n dominoesDrawn.splice(0, discardCount);\n }\n\n const newCurrentDominoes = dominoesDrawn.map((domino, index) => ({\n domino,\n picked: false,\n lordId: null,\n position: index + 1,\n }));\n\n if (isTribe) {\n // In Tribe mode, route to recruitCaveman before advancing to new turn\n return ok({\n ...game,\n currentDominoes: newCurrentDominoes,\n dominoes: dominoesCopy,\n lords,\n turn: updatedTurn,\n nextAction: {\n type: \"action\",\n nextLord: currentLord.id,\n nextAction: playerActions.recruitCaveman,\n },\n });\n }\n\n const next = nextLordWithAction(lords);\n return ok({\n ...game,\n currentDominoes: newCurrentDominoes,\n dominoes: dominoesCopy,\n lords,\n turn: updatedTurn,\n nextAction: next,\n });\n }\n\n if (isTribe) {\n // In Tribe mode, route to recruitCaveman before next lord picks\n return ok({\n ...game,\n currentDominoes: updatedCurrentDominoes,\n lords: updatedLords,\n nextAction: {\n type: \"action\",\n nextLord: currentLord.id,\n nextAction: playerActions.recruitCaveman,\n },\n });\n }\n\n const next = nextLordWithAction(updatedLords);\n\n return ok({\n ...game,\n currentDominoes: updatedCurrentDominoes,\n lords: updatedLords,\n nextAction: next,\n });\n};\n","import type {\n BuildersBoard,\n BuildingTile,\n PlacedBuilding,\n} from \"@core/domain/types/building.js\";\nimport type { Kingdom, Position } from \"@core/domain/types/kingdom.js\";\nimport type { Player } from \"@core/domain/types/player.js\";\nimport type { ShuffleMethod } from \"@core/portServerside/shuffleMethod.js\";\nimport { addCoins, addTowers, canAfford, removeCoins } from \"./economy.js\";\n\n/** Number of visible building slots on the Builders Board */\nconst BOARD_SLOTS = 4;\n\nexport const createBuildersBoard = (\n tiles: BuildingTile[],\n shuffle: ShuffleMethod,\n): BuildersBoard => {\n const shuffled = shuffle([...tiles]);\n const slots = shuffled.slice(0, BOARD_SLOTS);\n const drawPile = shuffled.slice(BOARD_SLOTS);\n\n return {\n slots,\n drawPile,\n };\n};\n\nexport const refillBuildersBoard = (board: BuildersBoard): BuildersBoard => {\n const newSlots = [...board.slots];\n const newDrawPile = [...board.drawPile];\n\n for (let i = 0; i < newSlots.length; i++) {\n if (newSlots[i] === null && newDrawPile.length > 0) {\n newSlots[i] = newDrawPile.shift()!;\n }\n }\n\n return { slots: newSlots, drawPile: newDrawPile };\n};\n\nexport const findBuildingOnBoard = (\n board: BuildersBoard,\n buildingId: number,\n): { building: BuildingTile; slotIndex: number } | null => {\n for (let i = 0; i < board.slots.length; i++) {\n const slot = board.slots[i];\n if (slot && slot.id === buildingId) {\n return { building: slot, slotIndex: i };\n }\n }\n return null;\n};\n\nexport const removeBuildingFromBoard = (\n board: BuildersBoard,\n slotIndex: number,\n): BuildersBoard => {\n const newSlots = [...board.slots];\n newSlots[slotIndex] = null;\n return { ...board, slots: newSlots };\n};\n\nexport const purchaseBuilding = (\n board: BuildersBoard,\n player: Player,\n buildingId: number,\n): {\n updatedBoard: BuildersBoard;\n updatedPlayer: Player;\n building: BuildingTile;\n} | null => {\n const found = findBuildingOnBoard(board, buildingId);\n if (!found) return null;\n\n const { building, slotIndex } = found;\n if (!canAfford(player, building.cost)) return null;\n\n let updatedPlayer = removeCoins(player, building.cost);\n\n // Apply immediate bonus\n if (building.immediateBonus) {\n switch (building.immediateBonus.type) {\n case \"coins\":\n updatedPlayer = addCoins(updatedPlayer, building.immediateBonus.amount);\n break;\n case \"tower\":\n updatedPlayer = addTowers(\n updatedPlayer,\n building.immediateBonus.amount,\n );\n break;\n }\n }\n\n // Add towers from the building itself\n if (building.towers > 0) {\n updatedPlayer = addTowers(updatedPlayer, building.towers);\n }\n\n const updatedBoard = removeBuildingFromBoard(board, slotIndex);\n\n return { updatedBoard, updatedPlayer, building };\n};\n\nexport const hasOpenConstructionSquare = (\n kingdom: Kingdom,\n placedBuildings: PlacedBuilding[],\n): boolean => {\n const occupiedPositions = new Set(\n placedBuildings.map((b) => `${b.position.x},${b.position.y}`),\n );\n\n for (let y = 0; y < kingdom.length; y++) {\n const row = kingdom[y]!;\n for (let x = 0; x < row.length; x++) {\n const tile = row[x]!;\n if (\n tile.type !== \"empty\" &&\n tile.type !== \"castle\" &&\n \"hasConstructionSquare\" in tile &&\n tile.hasConstructionSquare &&\n !occupiedPositions.has(`${x},${y}`)\n ) {\n return true;\n }\n }\n }\n return false;\n};\n\nexport const isValidConstructionPosition = (\n kingdom: Kingdom,\n placedBuildings: PlacedBuilding[],\n position: Position,\n): boolean => {\n const tile = kingdom[position.y]?.[position.x];\n if (!tile || tile.type === \"empty\" || tile.type === \"castle\") return false;\n if (!(\"hasConstructionSquare\" in tile) || !tile.hasConstructionSquare)\n return false;\n\n const occupied = placedBuildings.some(\n (b) => b.position.x === position.x && b.position.y === position.y,\n );\n return !occupied;\n};\n\nexport const placeBuildingOnKingdom = (\n kingdom: Kingdom,\n building: BuildingTile,\n position: Position,\n): Kingdom => {\n // Add building crowns to the tile\n const newKingdom = kingdom.map((row) => [...row]);\n const tile = newKingdom[position.y]![position.x]!;\n\n if (tile.type !== \"empty\" && tile.type !== \"castle\") {\n newKingdom[position.y]![position.x] = {\n ...tile,\n crowns: tile.crowns + building.crowns,\n };\n }\n\n return newKingdom;\n};\n\nexport const destroyWithDragon = (\n board: BuildersBoard,\n buildingId: number,\n player: Player,\n): {\n updatedBoard: BuildersBoard;\n updatedPlayer: Player;\n} | null => {\n const found = findBuildingOnBoard(board, buildingId);\n if (!found) return null;\n\n const { building, slotIndex } = found;\n if (!canAfford(player, building.cost)) return null;\n\n const updatedPlayer = removeCoins(player, building.cost);\n const updatedBoard = removeBuildingFromBoard(board, slotIndex);\n\n return { updatedBoard, updatedPlayer };\n};\n","import type { Kingdom } from \"@core/domain/types/kingdom.js\";\nimport type { Player } from \"@core/domain/types/player.js\";\nimport { getTowerCount } from \"./economy.js\";\n\n/**\n * Determine which player should hold the Queen.\n * The player with the most towers gets the Queen.\n * If tied, the Queen doesn't move (returns current holder).\n */\nexport const determineQueenHolder = (\n players: Player[],\n currentHolderId: string | null,\n): string | null => {\n let maxTowers = 0;\n let leaderId: string | null = null;\n let isTied = false;\n\n for (const player of players) {\n const towers = getTowerCount(player);\n if (towers > maxTowers) {\n maxTowers = towers;\n leaderId = player.id;\n isTied = false;\n } else if (towers === maxTowers && towers > 0 && leaderId !== null) {\n isTied = true;\n }\n }\n\n if (isTied || maxTowers === 0) {\n return currentHolderId;\n }\n\n return leaderId;\n};\n\ntype Property = {\n size: number;\n crowns: number;\n};\n\n/**\n * Find all properties (contiguous territories) in a kingdom using BFS.\n * Returns array of { size, crowns } for each property.\n */\nconst findProperties = (kingdom: Kingdom): Property[] => {\n const rows = kingdom.length;\n const cols = kingdom[0]?.length ?? 0;\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 const terrainType = 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 === terrainType\n ) {\n visited[ny]![nx] = true;\n queue.push([nx, ny]);\n }\n }\n }\n\n properties.push({ size, crowns });\n }\n }\n\n return properties;\n};\n\n/**\n * Calculate the Queen bonus: +1 crown to the territory with the most crowns.\n * Returns the additional points the Queen grants.\n */\nexport const getQueenBonus = (kingdom: Kingdom): number => {\n const properties = findProperties(kingdom);\n if (properties.length === 0) return 0;\n\n // Find the property with the most crowns\n let maxCrowns = 0;\n let maxCrownProperty: Property | null = null;\n\n for (const prop of properties) {\n if (prop.crowns > maxCrowns) {\n maxCrowns = prop.crowns;\n maxCrownProperty = prop;\n }\n }\n\n if (!maxCrownProperty || maxCrownProperty.crowns === 0) return 0;\n\n // Queen adds +1 crown to this territory\n // Original score: size * crowns\n // New score: size * (crowns + 1)\n // Bonus = size * (crowns + 1) - size * crowns = size\n return maxCrownProperty.size;\n};\n\n/**\n * Calculate end-game building bonus points for a player.\n */\nexport const calculateBuildingEndGameBonus = (player: Player): number => {\n const buildings = player.buildings ?? [];\n let bonus = 0;\n\n for (const placed of buildings) {\n const scoring = placed.building.endGameScoring;\n if (!scoring) continue;\n\n switch (scoring.type) {\n case \"flat\":\n bonus += scoring.points;\n break;\n case \"perBuilding\":\n bonus += buildings.length * scoring.points;\n break;\n case \"perTower\":\n bonus += getTowerCount(player) * scoring.points;\n break;\n case \"perCrown\": {\n const totalCrowns = countKingdomCrowns(player.kingdom);\n bonus += totalCrowns * scoring.points;\n break;\n }\n case \"perTerrain\": {\n if (scoring.terrain) {\n const count = countTerrainTiles(player.kingdom, scoring.terrain);\n bonus += count * scoring.points;\n }\n break;\n }\n }\n }\n\n return bonus;\n};\n\nconst countKingdomCrowns = (kingdom: Kingdom): number => {\n let total = 0;\n for (const row of kingdom) {\n for (const tile of row) {\n if (tile.type !== \"empty\" && tile.type !== \"castle\") {\n total += tile.crowns;\n }\n }\n }\n return total;\n};\n\nconst countTerrainTiles = (kingdom: Kingdom, terrain: string): number => {\n let count = 0;\n for (const row of kingdom) {\n for (const tile of row) {\n if (tile.type === terrain) {\n count++;\n }\n }\n }\n return count;\n};\n","import {\n isValidConstructionPosition,\n placeBuildingOnKingdom,\n purchaseBuilding,\n} from \"@core/domain/entities/building.js\";\nimport { nextQueenDominoAction } from \"@core/domain/entities/lord.js\";\nimport { determineQueenHolder } from \"@core/domain/entities/queen.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type { PlacedBuilding } from \"@core/domain/types/building.js\";\nimport type {\n GameStateResult,\n GameWithNextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Position } from \"@core/domain/types/kingdom.js\";\nimport { playerActions } from \"@core/domain/types/player.js\";\nimport { err, ok } from \"@utils/result.js\";\n\nexport type ConstructBuildingUseCase = (\n game: GameWithNextAction,\n lordId: string,\n buildingId: number,\n position: Position,\n) => GameStateResult;\n\nexport const constructBuildingUseCase: ConstructBuildingUseCase = (\n game,\n lordId,\n buildingId,\n position,\n) => {\n const currentAction = game.nextAction;\n\n if (currentAction.nextLord !== lordId) {\n return err(ErrorCode.NOT_YOUR_TURN);\n }\n\n if (currentAction.nextAction !== playerActions.constructBuilding) {\n return err(ErrorCode.INVALID_OPTIONAL_ACTION);\n }\n\n if (!game.queendomino) {\n return err(ErrorCode.INVALID_OPTIONAL_ACTION);\n }\n\n const currentLord = game.lords.find((l) => l.id === lordId);\n if (!currentLord) return err(ErrorCode.LORD_NOT_FOUND);\n\n const currentPlayer = game.players.find((p) => p.id === currentLord.playerId);\n if (!currentPlayer) return err(ErrorCode.PLAYER_NOT_FOUND);\n\n // Validate construction position\n if (\n !isValidConstructionPosition(\n currentPlayer.kingdom,\n currentPlayer.buildings ?? [],\n position,\n )\n ) {\n return err(ErrorCode.NO_CONSTRUCTION_SQUARE);\n }\n\n // Purchase the building\n const purchaseResult = purchaseBuilding(\n game.queendomino.buildersBoard,\n currentPlayer,\n buildingId,\n );\n\n if (!purchaseResult) {\n return err(ErrorCode.CANNOT_AFFORD_BUILDING);\n }\n\n const { updatedBoard, updatedPlayer, building } = purchaseResult;\n\n // Place building on kingdom (adds crowns)\n const updatedKingdom = placeBuildingOnKingdom(\n updatedPlayer.kingdom,\n building,\n position,\n );\n\n const placedBuilding: PlacedBuilding = { building, position };\n const finalPlayer = {\n ...updatedPlayer,\n kingdom: updatedKingdom,\n buildings: [...(updatedPlayer.buildings ?? []), placedBuilding],\n };\n\n const updatedPlayers = game.players.map((p) =>\n p.id === currentPlayer.id ? finalPlayer : p,\n );\n\n // Recalculate Queen holder\n const newQueenHolder = determineQueenHolder(\n updatedPlayers,\n game.queendomino.queenHolderId,\n );\n\n const nextAction = nextQueenDominoAction(playerActions.constructBuilding);\n\n return ok({\n ...game,\n players: updatedPlayers,\n queendomino: {\n ...game.queendomino,\n buildersBoard: updatedBoard,\n queenHolderId: newQueenHolder,\n },\n nextAction: {\n type: \"action\",\n nextLord: lordId,\n nextAction: nextAction,\n },\n });\n};\n","import { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type { Kingdom, Position } from \"@core/domain/types/index.js\";\nimport type {\n FireTokenPool,\n PlacedFireToken,\n} from \"@core/domain/types/origins.js\";\nimport { err, ok, type Result } from \"@utils/result.js\";\n\n// ─── Fire Token Pool ─────────────────────────────────────────────────\n\n/**\n * Creates the initial fire token pool for an Origins game.\n * 10 tokens total: 5×1-fire, 4×2-fire, 1×3-fire.\n */\nexport const createFireTokenPool = (): FireTokenPool => ({\n ones: 5,\n twos: 4,\n threes: 1,\n});\n\n/**\n * Takes a fire token from the pool matching the given crater count.\n * Returns the updated pool, or an error if none available.\n */\nexport const takeFireToken = (\n pool: FireTokenPool,\n craters: number,\n): Result<{ fires: 1 | 2 | 3; updatedPool: FireTokenPool }> => {\n if (craters === 1 && pool.ones > 0) {\n return ok({ fires: 1, updatedPool: { ...pool, ones: pool.ones - 1 } });\n }\n if (craters === 2 && pool.twos > 0) {\n return ok({ fires: 2, updatedPool: { ...pool, twos: pool.twos - 1 } });\n }\n if (craters === 3 && pool.threes > 0) {\n return ok({ fires: 3, updatedPool: { ...pool, threes: pool.threes - 1 } });\n }\n return err(ErrorCode.FIRE_TOKEN_POOL_EMPTY);\n};\n\n/**\n * Checks whether a fire token of the given crater type is available.\n */\nexport const hasFireToken = (pool: FireTokenPool, craters: number): boolean => {\n if (craters === 1) return pool.ones > 0;\n if (craters === 2) return pool.twos > 0;\n if (craters === 3) return pool.threes > 0;\n return false;\n};\n\n// ─── Fire Token Placement ────────────────────────────────────────────\n\n/**\n * Computes all positions reachable in exactly N steps from a starting position,\n * using 8-directional movement (including diagonal) with direction changes allowed.\n */\nconst getReachablePositions = (\n from: Position,\n steps: number,\n gridSize: number,\n): Position[] => {\n if (steps === 0) return [from];\n\n // BFS: track positions reachable at each step count\n let current = new Set<string>();\n current.add(`${from.x},${from.y}`);\n\n for (let step = 0; step < steps; step++) {\n const next = new Set<string>();\n for (const key of current) {\n const [cx, cy] = key.split(\",\").map(Number) as [number, number];\n for (let dx = -1; dx <= 1; dx++) {\n for (let dy = -1; dy <= 1; dy++) {\n if (dx === 0 && dy === 0) continue;\n const nx = cx + dx;\n const ny = cy + dy;\n if (nx >= 0 && nx < gridSize && ny >= 0 && ny < gridSize) {\n next.add(`${nx},${ny}`);\n }\n }\n }\n }\n current = next;\n }\n\n return [...current].map((key) => {\n const [x, y] = key.split(\",\").map(Number) as [number, number];\n return { x, y };\n });\n};\n\n/**\n * Returns all valid positions where a fire token can be placed.\n * A fire token is launched from the volcano and travels exactly N squares\n * (8-directional, direction changes allowed).\n *\n * Landing position constraints:\n * - Must be on the grid and contain a placed tile (not empty)\n * - Must NOT be a volcano or castle tile\n * - Must NOT have a fire symbol (crowns > 0)\n * - Must NOT already have a fire token\n */\nexport const getValidFireTokenPositions = (\n kingdom: Kingdom,\n volcanoPosition: Position,\n fires: 1 | 2 | 3,\n existingFireTokens: PlacedFireToken[],\n): Position[] => {\n const gridSize = kingdom.length;\n const reachable = getReachablePositions(volcanoPosition, fires, gridSize);\n\n const fireTokenPositions = new Set(\n existingFireTokens.map((ft) => `${ft.position.x},${ft.position.y}`),\n );\n\n return reachable.filter((pos) => {\n const tile = kingdom[pos.y]?.[pos.x];\n if (!tile) return false;\n if (tile.type === \"empty\") return false;\n if (tile.type === \"volcano\") return false;\n if (tile.type === \"castle\") return false;\n if (tile.crowns > 0) return false;\n if (fireTokenPositions.has(`${pos.x},${pos.y}`)) return false;\n return true;\n });\n};\n\n/**\n * Checks whether a specific position is valid for fire token placement.\n */\nexport const isValidFireTokenPosition = (\n kingdom: Kingdom,\n position: Position,\n volcanoPosition: Position,\n fires: 1 | 2 | 3,\n existingFireTokens: PlacedFireToken[],\n): boolean => {\n const validPositions = getValidFireTokenPositions(\n kingdom,\n volcanoPosition,\n fires,\n existingFireTokens,\n );\n return validPositions.some((p) => p.x === position.x && p.y === position.y);\n};\n","import { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type { PlacedGiant } from \"@core/domain/types/ageOfGiants.js\";\nimport type { Kingdom, Position } from \"@core/domain/types/kingdom.js\";\nimport type { Player } from \"@core/domain/types/player.js\";\nimport { err, ok, type Result } from \"@utils/result.js\";\n\nconst INITIAL_GIANT_POOL = 6;\n\n/**\n * Creates the initial giant pool (6 giants).\n */\nexport const createGiantPool = (): number => INITIAL_GIANT_POOL;\n\n/**\n * Takes a giant from the pool.\n * Returns the updated pool count, or an error if pool is empty.\n */\nexport const takeFromGiantPool = (pool: number): Result<number> => {\n if (pool <= 0) {\n return err(ErrorCode.GIANT_POOL_EMPTY);\n }\n return ok(pool - 1);\n};\n\n/**\n * Finds all positions in a kingdom that have at least 1 crown.\n */\nexport const findCrownsInKingdom = (kingdom: Kingdom): Position[] => {\n const crowns: Position[] = [];\n for (let y = 0; y < kingdom.length; y++) {\n const row = kingdom[y]!;\n for (let x = 0; x < row.length; x++) {\n const tile = row[x]!;\n if (tile.type !== \"empty\" && tile.type !== \"castle\" && tile.crowns > 0) {\n crowns.push({ x, y });\n }\n }\n }\n return crowns;\n};\n\n/**\n * Finds all crown positions not already covered by a giant.\n */\nexport const findCrownsNotCoveredByGiants = (\n kingdom: Kingdom,\n giants: PlacedGiant[],\n): Position[] => {\n const allCrowns = findCrownsInKingdom(kingdom);\n return allCrowns.filter(\n (crown) =>\n !giants.some((g) => g.position.x === crown.x && g.position.y === crown.y),\n );\n};\n\n/**\n * Checks whether a player has at least one giant on their kingdom.\n */\nexport const playerHasGiant = (player: Player): boolean =>\n (player.giants?.length ?? 0) > 0;\n\n/**\n * Places a giant on a crown in the player's kingdom.\n * Validates that the position has an uncovered crown.\n */\nexport const placeGiantOnCrown = (\n player: Player,\n position: Position,\n): Result<Player> => {\n const kingdom = player.kingdom;\n const tile = kingdom[position.y]?.[position.x];\n\n if (!tile || tile.type === \"empty\" || tile.type === \"castle\") {\n return err(ErrorCode.INVALID_GIANT_PLACEMENT);\n }\n\n if (tile.crowns <= 0) {\n return err(ErrorCode.INVALID_GIANT_PLACEMENT);\n }\n\n const giants = player.giants ?? [];\n\n // Check crown isn't already covered\n const alreadyCovered = giants.some(\n (g) => g.position.x === position.x && g.position.y === position.y,\n );\n if (alreadyCovered) {\n return err(ErrorCode.INVALID_GIANT_PLACEMENT);\n }\n\n const newGiant: PlacedGiant = { position };\n return ok({\n ...player,\n giants: [...giants, newGiant],\n });\n};\n\n/**\n * Sends a giant from the source player to the target player.\n * Removes the giant from the source and places it on a crown of the target.\n */\nexport const sendGiantToOpponent = (\n sourcePlayer: Player,\n targetPlayer: Player,\n giantIndex: number,\n targetCrownPosition: Position,\n): Result<{ source: Player; target: Player }> => {\n const sourceGiants = sourcePlayer.giants ?? [];\n\n if (giantIndex < 0 || giantIndex >= sourceGiants.length) {\n return err(ErrorCode.GIANT_NOT_FOUND);\n }\n\n // Validate target position has a crown\n const targetTile =\n targetPlayer.kingdom[targetCrownPosition.y]?.[targetCrownPosition.x];\n if (\n !targetTile ||\n targetTile.type === \"empty\" ||\n targetTile.type === \"castle\" ||\n targetTile.crowns <= 0\n ) {\n return err(ErrorCode.INVALID_GIANT_PLACEMENT);\n }\n\n // Check target crown isn't already covered\n const targetGiants = targetPlayer.giants ?? [];\n const alreadyCovered = targetGiants.some(\n (g) =>\n g.position.x === targetCrownPosition.x &&\n g.position.y === targetCrownPosition.y,\n );\n if (alreadyCovered) {\n return err(ErrorCode.INVALID_GIANT_PLACEMENT);\n }\n\n // Remove giant from source\n const updatedSourceGiants = sourceGiants.filter((_, i) => i !== giantIndex);\n\n // Place giant on target\n const newGiant: PlacedGiant = { position: targetCrownPosition };\n\n return ok({\n source: { ...sourcePlayer, giants: updatedSourceGiants },\n target: { ...targetPlayer, giants: [...targetGiants, newGiant] },\n });\n};\n","import type {\n AgeOfGiantsState,\n QuestTile,\n} from \"@core/domain/types/ageOfGiants.js\";\nimport type { BuildingTile } from \"@core/domain/types/building.js\";\nimport {\n type Domino,\n type GameMode,\n type GameWithNextStep,\n gameSteps,\n} from \"@core/domain/types/index.js\";\nimport type { CavemanTile, OriginsState } from \"@core/domain/types/origins.js\";\nimport type { QueenDominoState } from \"@core/domain/types/queendomino.js\";\nimport { isAgeOfGiantsMode } from \"./ageOfGiantsHelpers.js\";\nimport { createFireTokenPool } from \"./fireToken.js\";\nimport { createGiantPool } from \"./giant.js\";\nimport {\n getOriginsSubMode,\n isOriginsMode,\n isTotemMode,\n isTribeMode,\n} from \"./originsHelpers.js\";\n\nexport const create = (payload: {\n id: string;\n mode: GameMode;\n dominoes: Domino[];\n seed?: string;\n buildings?: BuildingTile[];\n cavemen?: CavemanTile[];\n questTiles?: QuestTile[];\n}): GameWithNextStep => {\n const { id, mode, dominoes, seed, buildings, cavemen, questTiles } = payload;\n\n let queendomino: QueenDominoState | undefined;\n if (\n (mode.name === \"QueenDomino\" || mode.name === \"AgeOfGiants-QueenDomino\") &&\n buildings\n ) {\n queendomino = {\n buildersBoard: {\n slots: [],\n drawPile: buildings,\n },\n queenHolderId: null,\n dragonAvailable: true,\n dragonUsedThisRound: false,\n };\n }\n\n let origins: OriginsState | undefined;\n if (isOriginsMode(mode.name)) {\n const subMode = getOriginsSubMode(mode.name)!;\n origins = {\n subMode,\n fireTokenPool: createFireTokenPool(),\n ...(isTotemMode(mode.name) && {\n totems: {\n mammoth: null,\n fish: null,\n mushroom: null,\n flint: null,\n },\n }),\n ...(isTribeMode(mode.name) &&\n cavemen && {\n caveBoard: {\n visible: [],\n drawPile: cavemen,\n },\n }),\n };\n }\n\n let ageOfGiants: AgeOfGiantsState | undefined;\n if (isAgeOfGiantsMode(mode.name) && questTiles) {\n ageOfGiants = {\n giantPool: createGiantPool(),\n questTiles,\n };\n }\n\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 ...(queendomino !== undefined && { queendomino }),\n ...(origins !== undefined && { origins }),\n ...(ageOfGiants !== undefined && { ageOfGiants }),\n };\n};\n","import { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type { GameMode } from \"@core/domain/types/mode.js\";\nimport { err, ok, type Result } from \"@utils/result.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 {\n isAgeOfGiantsMode,\n isAgeOfGiantsQueenDominoMode,\n} from \"@core/domain/entities/ageOfGiantsHelpers.js\";\nimport { create } from \"@core/domain/entities/game.js\";\nimport { createMode } from \"@core/domain/entities/mode.js\";\nimport { isTribeMode } from \"@core/domain/entities/originsHelpers.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type { QuestTile } from \"@core/domain/types/ageOfGiants.js\";\nimport type { BuildingTile } from \"@core/domain/types/building.js\";\nimport type { GameWithNextStep } from \"@core/domain/types/game.js\";\nimport type { CavemanTile } from \"@core/domain/types/origins.js\";\nimport type { BuildingsRepository } from \"@core/portServerside/buildingsRepository.js\";\nimport type { CavemenRepository } from \"@core/portServerside/cavemenRepository.js\";\nimport type { DominoesRepository } from \"@core/portServerside/dominoesRepository.js\";\nimport type { ModeRepository } from \"@core/portServerside/modeRepository.js\";\nimport type { QuestTilesRepository } from \"@core/portServerside/questTilesRepository.js\";\nimport type { ShuffleMethod } from \"@core/portServerside/shuffleMethod.js\";\nimport type { UuidMethod } from \"@core/portServerside/uuidMethod.js\";\nimport { err, isErr, ok, type Result } from \"@utils/result.js\";\nimport { createSeededShuffle } from \"@utils/seededShuffle.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 shuffleMethod: ShuffleMethod;\n buildingsRepository?: BuildingsRepository;\n cavemenRepository?: CavemenRepository;\n questTilesRepository?: QuestTilesRepository;\n }): CreateGameUseCase =>\n (mode, seed) => {\n const {\n modeRepository,\n dominoesRepository,\n uuidMethod,\n shuffleMethod,\n buildingsRepository,\n cavemenRepository,\n questTilesRepository,\n } = 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 isQueenDomino =\n newMode.value.name === \"QueenDomino\" ||\n isAgeOfGiantsQueenDominoMode(newMode.value.name);\n let buildings: BuildingTile[] | undefined;\n\n if (isQueenDomino && buildingsRepository) {\n buildings = buildingsRepository.getAll();\n }\n\n let cavemen: CavemanTile[] | undefined;\n if (isTribeMode(newMode.value.name) && cavemenRepository) {\n cavemen = cavemenRepository.getAll();\n }\n\n let questTiles: QuestTile[] | undefined;\n if (isAgeOfGiantsMode(newMode.value.name) && questTilesRepository) {\n const allQuests = questTilesRepository.getAll();\n // Draw 2 random quest tiles\n const questShuffle = gameSeed\n ? createSeededShuffle(gameSeed, \"quests\")\n : shuffleMethod;\n const shuffledQuests = questShuffle(allQuests);\n questTiles = shuffledQuests.slice(0, 2);\n }\n\n const payload = {\n id,\n mode: newMode.value,\n dominoes,\n seed: gameSeed,\n buildings,\n cavemen,\n questTiles,\n };\n\n const newGame = create(payload);\n\n return ok(newGame);\n };\n","import { placeDomino } from \"@core/domain/entities/kingdom.js\";\nimport type {\n Domino,\n Kingdom,\n Position,\n Rotation,\n} from \"@core/domain/types/index.js\";\nimport { GRIDSIZE, MAX_KINGDOM_SIZE } from \"@core/domain/types/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(\n kingdom,\n position,\n rotation,\n domino,\n maxKingdomSize,\n );\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(\n kingdom,\n position,\n rotation,\n domino,\n maxKingdomSize,\n );\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 { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameState,\n type GameStateResult,\n type GameWithNextAction,\n gameSteps,\n type NextAction,\n type NextStep,\n} from \"@core/domain/types/game.js\";\nimport { err, ok } from \"@utils/result.js\";\nimport { canPlaceDominoUseCase } from \"./getValidPlacements.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 (\n currentPlayer &&\n canPlaceDominoUseCase(\n currentPlayer.kingdom,\n currentLord.dominoPicked,\n game.rules.basic.maxKingdomSize,\n )\n ) {\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 { 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 { ErrorCode } from \"@core/domain/errors/domainErrors.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 { 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 type { Kingdom, Position } from \"@core/domain/types/kingdom.js\";\nimport type {\n CaveBoard,\n CavemanTile,\n PlacedCaveman,\n PlacedFireToken,\n Resource,\n ResourceType,\n} from \"@core/domain/types/origins.js\";\nimport type { ShuffleMethod } from \"@core/portServerside/shuffleMethod.js\";\n\nconst CAVE_BOARD_VISIBLE = 4;\n\n// ─── Cave Board Management ──────────────────────────────────────────\n\n/**\n * Creates a cave board from a list of caveman tiles.\n * Shuffles the tiles, reveals 4, and puts the rest in the draw pile.\n */\nexport const createCaveBoard = (\n tiles: CavemanTile[],\n shuffle: ShuffleMethod,\n): CaveBoard => {\n const shuffled = shuffle(tiles);\n return {\n visible: shuffled.slice(0, CAVE_BOARD_VISIBLE),\n drawPile: shuffled.slice(CAVE_BOARD_VISIBLE),\n };\n};\n\n/**\n * Takes a caveman from the visible slots and refills from draw pile.\n */\nexport const takeCavemanFromVisible = (\n board: CaveBoard,\n cavemanId: number,\n): { caveman: CavemanTile; updatedBoard: CaveBoard } | undefined => {\n const index = board.visible.findIndex((c) => c.id === cavemanId);\n if (index === -1) return undefined;\n\n const caveman = board.visible[index]!;\n const newVisible = [...board.visible];\n newVisible.splice(index, 1);\n\n // Refill from draw pile\n const newDrawPile = [...board.drawPile];\n if (newDrawPile.length > 0) {\n newVisible.push(newDrawPile.shift()!);\n }\n\n return {\n caveman,\n updatedBoard: { visible: newVisible, drawPile: newDrawPile },\n };\n};\n\n/**\n * Takes a caveman from the draw pile (face-down, player's choice).\n */\nexport const takeCavemanFromDrawPile = (\n board: CaveBoard,\n cavemanId: number,\n): { caveman: CavemanTile; updatedBoard: CaveBoard } | undefined => {\n const index = board.drawPile.findIndex((c) => c.id === cavemanId);\n if (index === -1) return undefined;\n\n const caveman = board.drawPile[index]!;\n const newDrawPile = [...board.drawPile];\n newDrawPile.splice(index, 1);\n\n return {\n caveman,\n updatedBoard: { visible: [...board.visible], drawPile: newDrawPile },\n };\n};\n\n// ─── Caveman Placement ───────────────────────────────────────────────\n\n/**\n * Checks if a position is valid for placing a caveman.\n * Must be on a placed tile with: no fire symbol, no fire token, no resource.\n */\nexport const isValidCavemanPosition = (\n kingdom: Kingdom,\n position: Position,\n fireTokens: PlacedFireToken[],\n resources: Resource[],\n cavemen: PlacedCaveman[],\n): boolean => {\n const tile = kingdom[position.y]?.[position.x];\n if (!tile) return false;\n if (tile.type === \"empty\" || tile.type === \"castle\") return false;\n\n // No fire symbols on tile\n if (tile.crowns > 0) return false;\n\n // No fire token at position\n if (\n fireTokens.some(\n (ft) => ft.position.x === position.x && ft.position.y === position.y,\n )\n )\n return false;\n\n // No resource at position\n if (\n resources.some(\n (r) => r.position.x === position.x && r.position.y === position.y,\n )\n )\n return false;\n\n // No existing caveman at position\n if (\n cavemen.some(\n (c) => c.position.x === position.x && c.position.y === position.y,\n )\n )\n return false;\n\n return true;\n};\n\n// ─── Caveman Scoring ─────────────────────────────────────────────────\n\n/**\n * All 8 directions (including diagonals) for adjacent resource counting.\n */\nconst EIGHT_DIRECTIONS = [\n [-1, -1],\n [-1, 0],\n [-1, 1],\n [0, -1],\n [0, 1],\n [1, -1],\n [1, 0],\n [1, 1],\n];\n\n/**\n * Calculates the score for a single hunter-gatherer based on surrounding resources/fire.\n */\nexport const calculateHunterGathererScore = (\n caveman: PlacedCaveman,\n kingdom: Kingdom,\n resources: Resource[],\n fireTokens: PlacedFireToken[],\n): number => {\n if (caveman.caveman.kind !== \"hunterGatherer\") return 0;\n\n const { hunterType, pointsPerMatch } = caveman.caveman;\n const { x, y } = caveman.position;\n let matches = 0;\n\n for (const [dx, dy] of EIGHT_DIRECTIONS) {\n const nx = x + (dx as number);\n const ny = y + (dy as number);\n\n switch (hunterType) {\n case \"mammothHunter\":\n if (\n resources.some(\n (r) =>\n r.position.x === nx &&\n r.position.y === ny &&\n r.type === \"mammoth\",\n )\n )\n matches++;\n break;\n case \"fisherman\":\n if (\n resources.some(\n (r) =>\n r.position.x === nx && r.position.y === ny && r.type === \"fish\",\n )\n )\n matches++;\n break;\n case \"mushroomPicker\":\n if (\n resources.some(\n (r) =>\n r.position.x === nx &&\n r.position.y === ny &&\n r.type === \"mushroom\",\n )\n )\n matches++;\n break;\n case \"flintCollector\":\n if (\n resources.some(\n (r) =>\n r.position.x === nx && r.position.y === ny && r.type === \"flint\",\n )\n )\n matches++;\n break;\n case \"trapper\": {\n // Count unique resource types adjacent\n const adjacentTypes = new Set<ResourceType>();\n for (const r of resources) {\n if (r.position.x === nx && r.position.y === ny) {\n adjacentTypes.add(r.type);\n }\n }\n matches += adjacentTypes.size;\n break;\n }\n case \"gatherer\":\n // Count all resources adjacent (any type)\n if (resources.some((r) => r.position.x === nx && r.position.y === ny))\n matches++;\n break;\n case \"fireLady\": {\n // Count fire symbols (on tiles + fire tokens)\n const tile = kingdom[ny]?.[nx];\n if (tile && tile.type !== \"empty\") {\n matches += tile.crowns;\n }\n if (\n fireTokens.some((ft) => ft.position.x === nx && ft.position.y === ny)\n ) {\n const token = fireTokens.find(\n (ft) => ft.position.x === nx && ft.position.y === ny,\n );\n if (token) matches += token.fires;\n }\n break;\n }\n }\n }\n\n return matches * pointsPerMatch;\n};\n\n/**\n * Calculates warrior group scoring.\n * Groups are connected warrior tiles (perpendicular only).\n * Score per group = number_of_warriors × total_power.\n */\nexport const calculateWarriorGroupScore = (\n cavemen: PlacedCaveman[],\n): number => {\n const warriors = cavemen.filter((c) => c.caveman.kind === \"warrior\");\n if (warriors.length === 0) return 0;\n\n const visited = new Set<string>();\n let totalScore = 0;\n\n const directions = [\n [-1, 0],\n [1, 0],\n [0, -1],\n [0, 1],\n ];\n\n for (const warrior of warriors) {\n const key = `${warrior.position.x},${warrior.position.y}`;\n if (visited.has(key)) continue;\n\n // BFS to find connected group\n let groupSize = 0;\n let groupPower = 0;\n const queue: PlacedCaveman[] = [warrior];\n visited.add(key);\n\n while (queue.length > 0) {\n const current = queue.pop()!;\n groupSize++;\n if (current.caveman.kind === \"warrior\") {\n groupPower += current.caveman.power;\n }\n\n for (const [dx, dy] of directions) {\n const nx = current.position.x + (dx as number);\n const ny = current.position.y + (dy as number);\n const nKey = `${nx},${ny}`;\n\n if (!visited.has(nKey)) {\n const neighbor = warriors.find(\n (w) => w.position.x === nx && w.position.y === ny,\n );\n if (neighbor) {\n visited.add(nKey);\n queue.push(neighbor);\n }\n }\n }\n }\n\n totalScore += groupSize * groupPower;\n }\n\n return totalScore;\n};\n\n/**\n * Calculates the total caveman bonus score for Tribe mode.\n */\nexport const calculateTribeCavemanScore = (\n cavemen: PlacedCaveman[],\n kingdom: Kingdom,\n resources: Resource[],\n fireTokens: PlacedFireToken[],\n): number => {\n let totalScore = 0;\n\n // Hunter-gatherer scores\n for (const caveman of cavemen) {\n if (caveman.caveman.kind === \"hunterGatherer\") {\n totalScore += calculateHunterGathererScore(\n caveman,\n kingdom,\n resources,\n fireTokens,\n );\n }\n }\n\n // Warrior group scores\n totalScore += calculateWarriorGroupScore(cavemen);\n\n return totalScore;\n};\n","import type { Kingdom } from \"@core/domain/types/kingdom.js\";\nimport type { PlacedFireToken } from \"@core/domain/types/origins.js\";\n\n/**\n * Calculates the fire token bonus for Origins scoring.\n *\n * For each region in the kingdom, fire tokens placed within that region\n * contribute their fire value as additional multiplier.\n * The bonus is: for each region, fire_tokens_in_region × region_size.\n *\n * This is added on top of the base score (which already accounts for\n * fire symbols printed on tiles via the crowns field).\n */\nexport const calculateOriginsFireBonus = (\n kingdom: Kingdom,\n placedFireTokens: PlacedFireToken[],\n): number => {\n if (placedFireTokens.length === 0) return 0;\n\n const rows = kingdom.length;\n const cols = kingdom[0]!.length;\n const visited: boolean[][] = kingdom.map((row) => row.map(() => false));\n\n const directions = [\n [-1, 0],\n [1, 0],\n [0, -1],\n [0, 1],\n ];\n\n // Build a map of fire token positions to fire values\n const tokenMap = new Map<string, number>();\n for (const token of placedFireTokens) {\n const key = `${token.position.x},${token.position.y}`;\n tokenMap.set(key, (tokenMap.get(key) ?? 0) + token.fires);\n }\n\n let totalBonus = 0;\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 (\n visited[y]![x] ||\n tile.type === \"empty\" ||\n tile.type === \"castle\" ||\n tile.type === \"volcano\"\n ) {\n continue;\n }\n\n // BFS flood-fill for this region\n const type = tile.type;\n let size = 0;\n let fireTokenFires = 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 size++;\n\n // Check for fire token at this position\n const key = `${cx},${cy}`;\n if (tokenMap.has(key)) {\n fireTokenFires += tokenMap.get(key)!;\n }\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 // Fire token bonus for this region: size × fire_token_fires\n totalBonus += size * fireTokenFires;\n }\n }\n\n return totalBonus;\n};\n","import type { PlacedGiant, QuestTile } from \"@core/domain/types/ageOfGiants.js\";\nimport { questTypes } from \"@core/domain/types/ageOfGiants.js\";\nimport type { Ground } from \"@core/domain/types/domino.js\";\nimport type { Kingdom } from \"@core/domain/types/kingdom.js\";\nimport { checkCastleIsInMiddle, countDominoes } from \"./kingdom.js\";\n\n/**\n * Finds the castle position in the kingdom.\n */\nconst findCastlePosition = (\n kingdom: Kingdom,\n): { x: number; y: number } | undefined => {\n for (let y = 0; y < kingdom.length; y++) {\n const row = kingdom[y]!;\n for (let x = 0; x < row.length; x++) {\n if (row[x]!.type === \"castle\") {\n return { x, y };\n }\n }\n }\n return undefined;\n};\n\n/**\n * Gets the bounding box of non-empty tiles in the kingdom.\n */\nconst getBoundingBox = (\n kingdom: Kingdom,\n): { minX: number; minY: number; maxX: number; maxY: number } | undefined => {\n let minX = Number.MAX_SAFE_INTEGER;\n let minY = Number.MAX_SAFE_INTEGER;\n let maxX = -1;\n let maxY = -1;\n\n for (let y = 0; y < kingdom.length; y++) {\n const row = kingdom[y]!;\n for (let x = 0; x < row.length; x++) {\n if (row[x]!.type !== \"empty\") {\n minX = Math.min(minX, x);\n minY = Math.min(minY, y);\n maxX = Math.max(maxX, x);\n maxY = Math.max(maxY, y);\n }\n }\n }\n\n if (maxX === -1) return undefined;\n return { minX, minY, maxX, maxY };\n};\n\n/**\n * Local Trade: 5pts per matching terrain tile adjacent (8-dir) to castle.\n */\nexport const calculateLocalTradeBonus = (\n kingdom: Kingdom,\n terrain: Ground,\n pointsPerMatch: number,\n): number => {\n const castle = findCastlePosition(kingdom);\n if (!castle) return 0;\n\n const directions = [\n [-1, -1],\n [-1, 0],\n [-1, 1],\n [0, -1],\n [0, 1],\n [1, -1],\n [1, 0],\n [1, 1],\n ];\n\n let count = 0;\n for (const [dy, dx] of directions) {\n const ny = castle.y + (dy as number);\n const nx = castle.x + (dx as number);\n const tile = kingdom[ny]?.[nx];\n if (tile && tile.type === terrain) {\n count++;\n }\n }\n\n return count * pointsPerMatch;\n};\n\n/**\n * Kingdom Borders: 5pts per matching terrain tile in the 4 corners of the kingdom bounding box.\n */\nexport const calculateKingdomBordersBonus = (\n kingdom: Kingdom,\n terrain: Ground,\n pointsPerMatch: number,\n): number => {\n const box = getBoundingBox(kingdom);\n if (!box) return 0;\n\n const corners = [\n { x: box.minX, y: box.minY },\n { x: box.maxX, y: box.minY },\n { x: box.minX, y: box.maxY },\n { x: box.maxX, y: box.maxY },\n ];\n\n let count = 0;\n for (const corner of corners) {\n const tile = kingdom[corner.y]?.[corner.x];\n if (tile && tile.type === terrain) {\n count++;\n }\n }\n\n return count * pointsPerMatch;\n};\n\n/**\n * Lost Corner: 20pts if castle is in one of the 4 corners of the kingdom bounding box.\n */\nexport const calculateLostCornerBonus = (\n kingdom: Kingdom,\n points: number,\n): number => {\n const castle = findCastlePosition(kingdom);\n if (!castle) return 0;\n\n const box = getBoundingBox(kingdom);\n if (!box) return 0;\n\n const isCorner =\n (castle.x === box.minX && castle.y === box.minY) ||\n (castle.x === box.maxX && castle.y === box.minY) ||\n (castle.x === box.minX && castle.y === box.maxY) ||\n (castle.x === box.maxX && castle.y === box.maxY);\n\n return isCorner ? points : 0;\n};\n\n/**\n * Megalomania: 10pts per alignment of 3+ tiles with uncovered crowns (H/V/diagonal).\n * Giants cover crowns, so we skip positions covered by giants.\n */\nexport const calculateMegalomaniaBonus = (\n kingdom: Kingdom,\n giants: PlacedGiant[],\n points: number,\n): number => {\n const rows = kingdom.length;\n const cols = kingdom[0]!.length;\n\n // Build a boolean grid: true if tile has uncovered crown\n const hasCrown: boolean[][] = Array.from({ length: rows }, () =>\n Array.from({ length: cols }, () => false),\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 (tile.type !== \"empty\" && tile.type !== \"castle\" && tile.crowns > 0) {\n const coveredByGiant = giants.some(\n (g) => g.position.x === x && g.position.y === y,\n );\n if (!coveredByGiant) {\n hasCrown[y]![x] = true;\n }\n }\n }\n }\n\n let alignments = 0;\n\n // Directions: horizontal (1,0), vertical (0,1), diagonal (1,1), anti-diagonal (1,-1)\n const directions = [\n { dx: 1, dy: 0 }, // horizontal\n { dx: 0, dy: 1 }, // vertical\n { dx: 1, dy: 1 }, // diagonal\n { dx: 1, dy: -1 }, // anti-diagonal\n ];\n\n for (const { dx, dy } of directions) {\n // Track which cells have been counted in a run for this direction\n const counted: boolean[][] = Array.from({ length: rows }, () =>\n Array.from({ length: cols }, () => false),\n );\n\n for (let y = 0; y < rows; y++) {\n for (let x = 0; x < cols; x++) {\n if (counted[y]![x] || !hasCrown[y]![x]) continue;\n\n // Count consecutive crowns in this direction\n let length = 0;\n let cx = x;\n let cy = y;\n while (\n cx >= 0 &&\n cx < cols &&\n cy >= 0 &&\n cy < rows &&\n hasCrown[cy]![cx]\n ) {\n counted[cy]![cx] = true;\n length++;\n cx += dx;\n cy += dy;\n }\n\n if (length >= 3) {\n alignments++;\n }\n }\n }\n }\n\n return alignments * points;\n};\n\n/**\n * Austere King: 10pts per property of 5+ wheat/forest/sea/plain tiles with 0 crowns.\n */\nexport const calculateAustereKingBonus = (\n kingdom: Kingdom,\n points: number,\n): number => {\n const eligibleTerrains: Ground[] = [\"wheat\", \"forest\", \"sea\", \"plain\"];\n const rows = kingdom.length;\n const cols = kingdom[0]!.length;\n const visited: boolean[][] = Array.from({ length: rows }, () =>\n Array.from({ length: cols }, () => false),\n );\n\n const directions = [\n [-1, 0],\n [1, 0],\n [0, -1],\n [0, 1],\n ];\n\n let qualifyingProperties = 0;\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] || !eligibleTerrains.includes(tile.type as Ground))\n continue;\n if (tile.type === \"empty\" || tile.type === \"castle\") continue;\n\n // BFS for this property\n const type = tile.type;\n let size = 0;\n let hasAnyCrown = false;\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 if (current.crowns > 0) hasAnyCrown = true;\n\n for (const [dy, dx] 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 if (size >= 5 && !hasAnyCrown) {\n qualifyingProperties++;\n }\n }\n }\n\n return qualifyingProperties * points;\n};\n\n/**\n * Calculates the bonus for a single quest tile.\n */\nexport const calculateQuestBonus = (\n quest: QuestTile,\n kingdom: Kingdom,\n giants: PlacedGiant[],\n dominoLimit: number,\n playerCount: number,\n): number => {\n switch (quest.type) {\n case questTypes.localTrade:\n return calculateLocalTradeBonus(kingdom, quest.terrain!, quest.points);\n\n case questTypes.kingdomBorders:\n return calculateKingdomBordersBonus(\n kingdom,\n quest.terrain!,\n quest.points,\n );\n\n case questTypes.harmony: {\n const totalDominoes = countDominoes(kingdom);\n const dominoesPerPlayer = dominoLimit / playerCount;\n return totalDominoes === dominoesPerPlayer ? quest.points : 0;\n }\n\n case questTypes.middleKingdom:\n return checkCastleIsInMiddle(kingdom) ? quest.points : 0;\n\n case questTypes.lostCorner:\n return calculateLostCornerBonus(kingdom, quest.points);\n\n case questTypes.megalomania:\n return calculateMegalomaniaBonus(kingdom, giants, quest.points);\n\n case questTypes.austereKing:\n return calculateAustereKingBonus(kingdom, quest.points);\n\n default:\n return 0;\n }\n};\n","import type { Ground, Tile } from \"@core/domain/types/domino.js\";\nimport type { Position } from \"@core/domain/types/kingdom.js\";\nimport type { Resource, ResourceType } from \"@core/domain/types/origins.js\";\n\n/**\n * Maps terrain types to their corresponding resource type.\n * Returns null for terrains that don't produce resources.\n */\nexport const terrainToResource = (terrain: Ground): ResourceType | null => {\n switch (terrain) {\n case \"grassland\":\n return \"mammoth\";\n case \"lake\":\n return \"fish\";\n case \"jungle\":\n return \"mushroom\";\n case \"quarry\":\n return \"flint\";\n default:\n return null;\n }\n};\n\n/**\n * Checks whether a tile should receive a wooden resource.\n * A tile gets a resource if it has a resource-eligible terrain AND no fire symbols.\n */\nexport const shouldHaveResource = (tile: Tile): boolean => {\n const resourceType = terrainToResource(tile.type);\n return resourceType !== null && tile.crowns === 0;\n};\n\n/**\n * Creates a resource for a tile at the given position, if applicable.\n */\nexport const createResourceForTile = (\n tile: Tile,\n position: Position,\n): Resource | null => {\n const resourceType = terrainToResource(tile.type);\n if (resourceType === null || tile.crowns > 0) return null;\n return { type: resourceType, position };\n};\n\n/**\n * Destroys a resource at a given position (e.g., from fire token impact).\n * Returns the updated resources array.\n */\nexport const destroyResourceAtPosition = (\n resources: Resource[],\n position: Position,\n): Resource[] => {\n return resources.filter(\n (r) => !(r.position.x === position.x && r.position.y === position.y),\n );\n};\n\n/**\n * Counts resources by type for a player's resource list.\n */\nexport const countResourcesByType = (\n resources: Resource[],\n): Record<ResourceType, number> => {\n const counts: Record<ResourceType, number> = {\n mammoth: 0,\n fish: 0,\n mushroom: 0,\n flint: 0,\n };\n for (const r of resources) {\n counts[r.type]++;\n }\n return counts;\n};\n\n/**\n * Checks if a player has at least the required resources to spend.\n * @param resources - Player's current resources\n * @param positions - Positions of resources to spend\n * @param requiredDifferentTypes - How many different types are required\n */\nexport const canSpendResources = (\n resources: Resource[],\n positions: Position[],\n requiredDifferentTypes: number,\n): boolean => {\n const toSpend = positions.map((pos) =>\n resources.find((r) => r.position.x === pos.x && r.position.y === pos.y),\n );\n\n // All positions must have a resource\n if (toSpend.some((r) => r === undefined)) return false;\n\n // Must have the required number of different types\n const types = new Set(toSpend.map((r) => r!.type));\n return types.size >= requiredDifferentTypes;\n};\n\n/**\n * Removes resources at the given positions.\n */\nexport const spendResources = (\n resources: Resource[],\n positions: Position[],\n): Resource[] => {\n const posSet = new Set(positions.map((p) => `${p.x},${p.y}`));\n return resources.filter(\n (r) => !posSet.has(`${r.position.x},${r.position.y}`),\n );\n};\n","import type { ResourceType, TotemState } from \"@core/domain/types/origins.js\";\nimport type { Player } from \"@core/domain/types/player.js\";\nimport { countResourcesByType } from \"./resource.js\";\n\n/**\n * Bonus points for holding each totem at end of game.\n * Values from the Kingdomino Origins rules.\n */\nexport const TOTEM_BONUSES: Record<ResourceType, number> = {\n mammoth: 3,\n fish: 3,\n mushroom: 3,\n flint: 3,\n};\n\nconst RESOURCE_TYPES: ResourceType[] = [\"mammoth\", \"fish\", \"mushroom\", \"flint\"];\n\n/**\n * Determines which player holds each totem based on resource majority.\n * A player must have the strict majority (more than any other player).\n * In case of tie, the current holder keeps the totem. If no one holds it, it stays unclaimed.\n */\nexport const determineTotemHolders = (\n players: Player[],\n currentTotems: TotemState,\n): TotemState => {\n const result: TotemState = { ...currentTotems };\n\n for (const resourceType of RESOURCE_TYPES) {\n let maxCount = 0;\n let maxPlayerId: string | null = null;\n let isTied = false;\n\n for (const player of players) {\n const resources = player.resources ?? [];\n const counts = countResourcesByType(resources);\n const count = counts[resourceType];\n\n if (count > maxCount) {\n maxCount = count;\n maxPlayerId = player.id;\n isTied = false;\n } else if (count === maxCount && count > 0) {\n isTied = true;\n }\n }\n\n if (maxCount === 0) {\n // No one has this resource - totem stays unclaimed\n result[resourceType] = null;\n } else if (isTied) {\n // Tie: current holder keeps it, or stays with one of the tied players\n // Per rules: \"If there is a tie for the majority then you can choose which\n // of the players to give the totem to\" - we keep the current holder\n // If no current holder, give to first tied player\n if (\n result[resourceType] === null ||\n !players.some((p) => p.id === result[resourceType])\n ) {\n result[resourceType] = maxPlayerId;\n }\n } else {\n result[resourceType] = maxPlayerId;\n }\n }\n\n return result;\n};\n\n/**\n * Calculates totem scoring for a player in Totem mode:\n * - 1 point per remaining wooden resource\n * - Totem bonus for each totem the player holds\n */\nexport const calculateTotemScore = (\n player: Player,\n totemState: TotemState,\n): number => {\n let score = 0;\n\n // 1 point per remaining resource\n const resources = player.resources ?? [];\n score += resources.length;\n\n // Totem bonuses\n for (const resourceType of RESOURCE_TYPES) {\n if (totemState[resourceType] === player.id) {\n score += TOTEM_BONUSES[resourceType];\n }\n }\n\n return score;\n};\n","import { isAgeOfGiantsMode } from \"@core/domain/entities/ageOfGiantsHelpers.js\";\nimport { calculateTribeCavemanScore } from \"@core/domain/entities/caveman.js\";\nimport {\n checkCastleIsInMiddle,\n countDominoes,\n} from \"@core/domain/entities/kingdom.js\";\nimport {\n isOriginsMode,\n isTotemMode,\n isTribeMode,\n} from \"@core/domain/entities/originsHelpers.js\";\nimport { calculateOriginsFireBonus } from \"@core/domain/entities/originsScore.js\";\nimport { calculateQuestBonus } from \"@core/domain/entities/questScore.js\";\nimport { calculateTotemScore } from \"@core/domain/entities/totem.js\";\nimport type {\n FinalResult,\n GameWithNextStep,\n GameWithResults,\n ScoreResult,\n} from \"@core/domain/types/index.js\";\nimport { 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 // Origins fire token scoring bonus\n if (\n isOriginsMode(game.mode.name) &&\n player.fireTokens &&\n player.fireTokens.length > 0\n ) {\n finalScore += calculateOriginsFireBonus(kingdom, player.fireTokens);\n }\n\n // Totem mode: resource points + totem bonuses\n if (isTotemMode(game.mode.name) && game.origins?.totems) {\n finalScore += calculateTotemScore(player, game.origins.totems);\n }\n\n // Tribe mode: caveman bonuses (no resource points, no totems)\n if (\n isTribeMode(game.mode.name) &&\n player.cavemen &&\n player.cavemen.length > 0\n ) {\n finalScore += calculateTribeCavemanScore(\n player.cavemen,\n kingdom,\n player.resources ?? [],\n player.fireTokens ?? [],\n );\n }\n\n // Age of Giants: quest tile bonuses\n if (isAgeOfGiantsMode(game.mode.name) && game.ageOfGiants?.questTiles) {\n const giants = player.giants ?? [];\n for (const quest of game.ageOfGiants.questTiles) {\n finalScore += calculateQuestBonus(\n quest,\n kingdom,\n giants,\n basic.maxDominoes,\n game.players.length,\n );\n }\n }\n\n if (extra.length > 0) {\n extra.forEach((extraRule) => {\n // Castle in middle: \"The middle Kingdom\" (Classic/QD) or \"Empire of Fire\" (Origins)\n if (\n extraRule.name === \"The middle Kingdom\" ||\n extraRule.name === \"Empire of Fire\"\n ) {\n const castleIsInMiddle = checkCastleIsInMiddle(kingdom);\n if (castleIsInMiddle) {\n finalScore += 10;\n }\n }\n\n // Complete kingdom: \"Harmony\" (Classic/QD) or \"Homo Habilis\" (Origins)\n if (extraRule.name === \"Harmony\" || extraRule.name === \"Homo Habilis\") {\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 {\n isAgeOfGiantsMode,\n isAgeOfGiantsQueenDominoMode,\n isFootprintDomino,\n isGiantDomino,\n} from \"@core/domain/entities/ageOfGiantsHelpers.js\";\nimport { takeFireToken } from \"@core/domain/entities/fireToken.js\";\nimport {\n findCrownsNotCoveredByGiants,\n playerHasGiant,\n} from \"@core/domain/entities/giant.js\";\nimport {\n calculateDominoPosition,\n placeDomino,\n} from \"@core/domain/entities/kingdom.js\";\nimport {\n allLordsHavePlayed,\n canPlaceAndDominoPickedIsDefined,\n nextLordWithAction,\n} from \"@core/domain/entities/lord.js\";\nimport {\n isOriginsMode,\n isResourceMode,\n} from \"@core/domain/entities/originsHelpers.js\";\nimport { createResourceForTile } from \"@core/domain/entities/resource.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameState,\n type GameStateResult,\n type GameWithNextAction,\n gameSteps,\n type NextAction,\n type NextStep,\n} from \"@core/domain/types/game.js\";\nimport type { Position, Rotation } from \"@core/domain/types/kingdom.js\";\nimport type { PendingFireToken, Resource } from \"@core/domain/types/origins.js\";\nimport {\n type PlayerActions,\n playerActions,\n} from \"@core/domain/types/player.js\";\nimport { err, isErr, isOk, ok } from \"@utils/result.js\";\n\nexport type PlaceDominoUseCase = (\n game: GameWithNextAction,\n lordId: string,\n position: Position,\n rotation: Rotation,\n) => GameStateResult;\n\n/**\n * Finds the volcano tile position(s) in a just-placed domino.\n * Returns the first volcano tile with craters, or undefined.\n */\nconst findVolcanoInDomino = (\n game: GameWithNextAction,\n position: Position,\n rotation: Rotation,\n): { craters: number; volcanoPosition: Position } | undefined => {\n const lord = game.lords.find((l) => l.id === game.nextAction.nextLord);\n if (!lord?.dominoPicked) return undefined;\n\n const [first, second] = calculateDominoPosition(\n position,\n rotation,\n lord.dominoPicked,\n );\n\n for (const placed of [first, second]) {\n if (\n placed.tile.type === \"volcano\" &&\n placed.tile.volcanoCraters &&\n placed.tile.volcanoCraters > 0\n ) {\n return {\n craters: placed.tile.volcanoCraters,\n volcanoPosition: placed.position,\n };\n }\n }\n return undefined;\n};\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 // Collect resources from placed tiles (Totem/Tribe modes)\n const newResources: Resource[] = [];\n if (isResourceMode(game.mode.name)) {\n const [first, second] = calculateDominoPosition(position, rotation, domino);\n for (const placed of [first, second]) {\n const resource = createResourceForTile(placed.tile, placed.position);\n if (resource) {\n newResources.push(resource);\n }\n }\n }\n\n const updatedPlayers = game.players.map((player) => {\n if (player.id === currentPlayer.id) {\n const updated = { ...player, kingdom: updatedKingdom.value };\n if (newResources.length > 0 && updated.resources) {\n updated.resources = [...updated.resources, ...newResources];\n }\n return updated;\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 const isQueenDomino = game.mode.name === \"QueenDomino\";\n const isOrigins = isOriginsMode(game.mode.name);\n const isAoG = isAgeOfGiantsMode(game.mode.name);\n const isAoGQD = isAgeOfGiantsQueenDominoMode(game.mode.name);\n\n if (\n isLastTurn &&\n allLordsHavePlayed(updatedLords) &&\n !isQueenDomino &&\n !isOrigins &&\n !isAoG\n ) {\n updatedGame = {\n ...game,\n lords: updatedLords,\n nextAction: resultStep,\n players: updatedPlayers,\n };\n } else if (isQueenDomino && !isLastTurn) {\n // In QueenDomino, after placing a domino, the same lord gets optional actions\n updatedGame = {\n ...game,\n lords: updatedLords,\n nextAction: {\n type: \"action\",\n nextLord: currentLord.id,\n nextAction: playerActions.placeKnight,\n },\n players: updatedPlayers,\n };\n } else if (isQueenDomino && isLastTurn) {\n // Last turn in QueenDomino: optional actions before checking if all lords done\n const queenDominoAction: NextAction = {\n type: \"action\",\n nextLord: currentLord.id,\n nextAction: playerActions.placeKnight,\n };\n updatedGame = {\n ...game,\n lords: updatedLords,\n nextAction: queenDominoAction,\n players: updatedPlayers,\n };\n } else if (isOrigins) {\n // Origins: check for volcano to grant fire token\n const volcano = findVolcanoInDomino(game, position, rotation);\n let updatedOrigins = game.origins;\n\n if (volcano && updatedOrigins) {\n const tokenResult = takeFireToken(\n updatedOrigins.fireTokenPool,\n volcano.craters,\n );\n if (isOk(tokenResult)) {\n // Grant fire token and set pending for placement\n const pendingFireToken: PendingFireToken = {\n fires: tokenResult.value.fires,\n volcanoPosition: volcano.volcanoPosition,\n };\n updatedOrigins = {\n ...updatedOrigins,\n fireTokenPool: tokenResult.value.updatedPool,\n pendingFireToken,\n };\n\n // Route to placeFireToken action\n updatedGame = {\n ...game,\n lords: updatedLords,\n players: updatedPlayers,\n origins: updatedOrigins,\n nextAction: {\n type: \"action\",\n nextLord: currentLord.id,\n nextAction: playerActions.placeFireToken,\n },\n };\n } else {\n // Pool empty for this crater type - skip fire token, go to pickDomino\n if (isLastTurn && allLordsHavePlayed(updatedLords)) {\n updatedGame = {\n ...game,\n lords: updatedLords,\n nextAction: resultStep,\n players: updatedPlayers,\n origins: updatedOrigins,\n };\n } else if (isLastTurn) {\n updatedGame = {\n ...game,\n lords: updatedLords,\n nextAction: resultStep,\n players: updatedPlayers,\n origins: updatedOrigins,\n };\n } else {\n updatedGame = {\n ...game,\n lords: updatedLords,\n nextAction: nextLordWithAction(updatedLords) as NextAction,\n players: updatedPlayers,\n origins: updatedOrigins,\n };\n }\n }\n } else {\n // No volcano placed - skip straight to next action\n if (isLastTurn && allLordsHavePlayed(updatedLords)) {\n updatedGame = {\n ...game,\n lords: updatedLords,\n nextAction: resultStep,\n players: updatedPlayers,\n };\n } else if (isLastTurn) {\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: nextLordWithAction(updatedLords) as NextAction,\n players: updatedPlayers,\n };\n }\n }\n } else if (isAoG) {\n // Age of Giants: check for giant/footprint domino effects\n const currentPlayer = updatedPlayers.find(\n (p) => p.id === currentLord.playerId,\n );\n const isGiant = isGiantDomino(domino);\n const isFootprint = isFootprintDomino(domino);\n\n let aogAction: PlayerActions | null = null;\n\n if (isGiant) {\n // Giant domino: must place giant on a crown (mandatory)\n // But auto-skip if player has no uncovered crowns or pool is empty\n const hasUncoveredCrowns =\n currentPlayer &&\n findCrownsNotCoveredByGiants(\n currentPlayer.kingdom,\n currentPlayer.giants ?? [],\n ).length > 0;\n const poolAvailable = (game.ageOfGiants?.giantPool ?? 0) > 0;\n\n if (hasUncoveredCrowns && poolAvailable) {\n aogAction = playerActions.placeGiant;\n }\n } else if (isFootprint) {\n // Footprint domino: may send a giant to opponent (optional)\n // But only if player has a giant in their kingdom\n if (currentPlayer && playerHasGiant(currentPlayer)) {\n aogAction = playerActions.sendGiant;\n }\n }\n\n if (aogAction) {\n updatedGame = {\n ...game,\n lords: updatedLords,\n players: updatedPlayers,\n nextAction: {\n type: \"action\",\n nextLord: currentLord.id,\n nextAction: aogAction,\n },\n };\n } else if (isAoGQD) {\n // No AoG action but still need QueenDomino actions\n updatedGame = {\n ...game,\n lords: updatedLords,\n players: updatedPlayers,\n nextAction: {\n type: \"action\",\n nextLord: currentLord.id,\n nextAction: playerActions.placeKnight,\n },\n };\n } else 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: nextLordWithAction(updatedLords) as NextAction,\n players: updatedPlayers,\n };\n }\n } else {\n updatedGame = {\n ...game,\n lords: updatedLords,\n nextAction: nextLordWithAction(updatedLords) as NextAction,\n players: updatedPlayers,\n };\n }\n\n return ok(updatedGame);\n};\n","import { isValidFireTokenPosition } from \"@core/domain/entities/fireToken.js\";\nimport {\n allLordsHavePlayed,\n nextLordWithAction,\n} from \"@core/domain/entities/lord.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameState,\n type GameStateResult,\n type GameWithNextAction,\n gameSteps,\n type NextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Position } from \"@core/domain/types/kingdom.js\";\nimport type { PlacedFireToken } from \"@core/domain/types/origins.js\";\nimport { err, ok } from \"@utils/result.js\";\n\nexport type PlaceFireTokenUseCase = (\n game: GameWithNextAction,\n lordId: string,\n position: Position,\n) => GameStateResult;\n\nexport const placeFireTokenUseCase: PlaceFireTokenUseCase = (\n game,\n lordId,\n position,\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 (!game.origins?.pendingFireToken) {\n return err(ErrorCode.NO_PENDING_FIRE_TOKEN);\n }\n\n const { fires, volcanoPosition } = game.origins.pendingFireToken;\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 existingTokens = currentPlayer.fireTokens ?? [];\n\n if (\n !isValidFireTokenPosition(\n currentPlayer.kingdom,\n position,\n volcanoPosition,\n fires,\n existingTokens,\n )\n ) {\n return err(ErrorCode.FIRE_TOKEN_INVALID_POSITION);\n }\n\n // Place the fire token\n const newToken: PlacedFireToken = { fires, position };\n const updatedFireTokens = [...existingTokens, newToken];\n\n // Destroy resource at position if any (Totem/Tribe modes)\n let updatedResources = currentPlayer.resources;\n if (updatedResources) {\n updatedResources = updatedResources.filter(\n (r) => !(r.position.x === position.x && r.position.y === position.y),\n );\n }\n\n // Destroy caveman at position if any (Tribe mode)\n let updatedCavemen = currentPlayer.cavemen;\n if (updatedCavemen) {\n updatedCavemen = updatedCavemen.filter(\n (c) => !(c.position.x === position.x && c.position.y === position.y),\n );\n }\n\n const updatedPlayers = game.players.map((player) => {\n if (player.id === currentPlayer.id) {\n return {\n ...player,\n fireTokens: updatedFireTokens,\n ...(updatedResources !== undefined && { resources: updatedResources }),\n ...(updatedCavemen !== undefined && { cavemen: updatedCavemen }),\n };\n }\n return player;\n });\n\n // Clear pending fire token\n const updatedOrigins = {\n ...game.origins,\n pendingFireToken: undefined,\n };\n\n // Determine next action\n const isLastTurn = game.turn === game.rules.basic.maxTurns;\n\n let nextGameAction: GameState;\n\n if (isLastTurn && allLordsHavePlayed(game.lords)) {\n nextGameAction = {\n ...game,\n players: updatedPlayers,\n origins: updatedOrigins,\n nextAction: { type: \"step\", step: gameSteps.result },\n };\n } else if (isLastTurn) {\n nextGameAction = {\n ...game,\n players: updatedPlayers,\n origins: updatedOrigins,\n nextAction: { type: \"step\", step: gameSteps.result },\n };\n } else {\n nextGameAction = {\n ...game,\n players: updatedPlayers,\n origins: updatedOrigins,\n nextAction: nextLordWithAction(game.lords) as NextAction,\n };\n }\n\n return ok(nextGameAction);\n};\n","import { isAgeOfGiantsQueenDominoMode } from \"@core/domain/entities/ageOfGiantsHelpers.js\";\nimport {\n placeGiantOnCrown,\n takeFromGiantPool,\n} from \"@core/domain/entities/giant.js\";\nimport {\n allLordsHavePlayed,\n nextAgeOfGiantsAction,\n nextLordWithAction,\n} from \"@core/domain/entities/lord.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameStateResult,\n type GameWithNextAction,\n gameSteps,\n type NextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Position } from \"@core/domain/types/kingdom.js\";\nimport { playerActions } from \"@core/domain/types/player.js\";\nimport { err, isErr, ok } from \"@utils/result.js\";\n\nexport type PlaceGiantUseCase = (\n game: GameWithNextAction,\n lordId: string,\n position: Position,\n) => GameStateResult;\n\nexport const placeGiantUseCase: PlaceGiantUseCase = (\n game,\n lordId,\n position,\n) => {\n const currentAction = game.nextAction;\n\n if (currentAction.nextAction !== playerActions.placeGiant) {\n return err(ErrorCode.INVALID_OPTIONAL_ACTION);\n }\n\n if (currentAction.nextLord !== lordId) {\n return err(ErrorCode.NOT_YOUR_TURN);\n }\n\n if (!game.ageOfGiants) {\n return err(ErrorCode.NOT_AOG_MODE);\n }\n\n // Take from giant pool\n const poolResult = takeFromGiantPool(game.ageOfGiants.giantPool);\n if (isErr(poolResult)) {\n return poolResult;\n }\n\n const currentLord = game.lords.find((l) => l.id === lordId);\n if (!currentLord) {\n return err(ErrorCode.LORD_NOT_FOUND);\n }\n\n const currentPlayer = game.players.find((p) => p.id === currentLord.playerId);\n if (!currentPlayer) {\n return err(ErrorCode.PLAYER_NOT_FOUND);\n }\n\n // Place giant on the chosen crown\n const placeResult = placeGiantOnCrown(currentPlayer, position);\n if (isErr(placeResult)) {\n return placeResult;\n }\n\n const updatedPlayers = game.players.map((p) =>\n p.id === currentPlayer.id ? placeResult.value : p,\n );\n\n const updatedAoG = {\n ...game.ageOfGiants,\n giantPool: poolResult.value,\n };\n\n // Determine next action\n const isAoGQD = isAgeOfGiantsQueenDominoMode(game.mode.name);\n const nextAction = nextAgeOfGiantsAction(playerActions.placeGiant, isAoGQD);\n\n if (nextAction === playerActions.pickDomino) {\n // No more optional actions — advance to next lord or result\n const isLastTurn = game.turn === game.rules.basic.maxTurns;\n if (isLastTurn && allLordsHavePlayed(game.lords)) {\n return ok({\n ...game,\n players: updatedPlayers,\n ageOfGiants: updatedAoG,\n nextAction: { type: \"step\", step: gameSteps.result },\n });\n }\n return ok({\n ...game,\n players: updatedPlayers,\n ageOfGiants: updatedAoG,\n nextAction: nextLordWithAction(game.lords) as NextAction,\n });\n }\n\n // More optional actions (e.g., placeKnight in AoG-QD)\n return ok({\n ...game,\n players: updatedPlayers,\n ageOfGiants: updatedAoG,\n nextAction: {\n type: \"action\",\n nextLord: lordId,\n nextAction: nextAction,\n },\n });\n};\n","import type { Kingdom, Position } from \"@core/domain/types/kingdom.js\";\nimport type { Knight, Player } from \"@core/domain/types/player.js\";\nimport { addCoins, MAX_KNIGHTS } from \"./economy.js\";\n\n/**\n * Count construction squares in the contiguous territory containing the given position.\n * Uses BFS flood-fill on same terrain type.\n */\nexport const countConstructionSquaresInTerritory = (\n kingdom: Kingdom,\n position: Position,\n): number => {\n const rows = kingdom.length;\n const cols = kingdom[0]?.length ?? 0;\n const startTile = kingdom[position.y]?.[position.x];\n\n if (!startTile || startTile.type === \"empty\" || startTile.type === \"castle\") {\n return 0;\n }\n\n const terrainType = startTile.type;\n const visited: boolean[][] = kingdom.map((row) => row.map(() => false));\n const queue: [number, number][] = [[position.x, position.y]];\n visited[position.y]![position.x] = true;\n let count = 0;\n\n const directions = [\n [-1, 0],\n [1, 0],\n [0, -1],\n [0, 1],\n ];\n\n while (queue.length > 0) {\n const [cx, cy] = queue.pop()!;\n const tile = kingdom[cy]![cx]!;\n\n if (\n tile.type !== \"empty\" &&\n tile.type !== \"castle\" &&\n \"hasConstructionSquare\" in tile &&\n tile.hasConstructionSquare\n ) {\n count++;\n }\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 === terrainType\n ) {\n visited[ny]![nx] = true;\n queue.push([nx, ny]);\n }\n }\n }\n\n return count;\n};\n\n/**\n * Get the terrain type at a position to identify the territory.\n */\nconst getTerritoryTerrain = (\n kingdom: Kingdom,\n position: Position,\n): string | null => {\n const tile = kingdom[position.y]?.[position.x];\n if (!tile || tile.type === \"empty\" || tile.type === \"castle\") return null;\n return tile.type;\n};\n\n/**\n * Check if a territory (identified by BFS from position) already has a knight.\n */\nconst territoryHasKnight = (\n kingdom: Kingdom,\n position: Position,\n knights: Knight[],\n): boolean => {\n const terrain = getTerritoryTerrain(kingdom, position);\n if (!terrain) return false;\n\n // BFS to find all positions in this territory\n const rows = kingdom.length;\n const cols = kingdom[0]?.length ?? 0;\n const visited: boolean[][] = kingdom.map((row) => row.map(() => false));\n const queue: [number, number][] = [[position.x, position.y]];\n visited[position.y]![position.x] = true;\n const territoryPositions = new Set<string>();\n\n const directions = [\n [-1, 0],\n [1, 0],\n [0, -1],\n [0, 1],\n ];\n\n while (queue.length > 0) {\n const [cx, cy] = queue.pop()!;\n territoryPositions.add(`${cx},${cy}`);\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 === terrain\n ) {\n visited[ny]![nx] = true;\n queue.push([nx, ny]);\n }\n }\n }\n\n return knights.some((k) =>\n territoryPositions.has(`${k.position.x},${k.position.y}`),\n );\n};\n\nexport const canPlaceKnight = (\n player: Player,\n kingdom: Kingdom,\n position: Position,\n): boolean => {\n const knights = player.knights ?? [];\n if (knights.length >= MAX_KNIGHTS) return false;\n\n const tile = kingdom[position.y]?.[position.x];\n if (!tile || tile.type === \"empty\" || tile.type === \"castle\") return false;\n\n if (territoryHasKnight(kingdom, position, knights)) return false;\n\n return true;\n};\n\nexport const placeKnight = (\n player: Player,\n kingdom: Kingdom,\n position: Position,\n): Player => {\n const knight: Knight = { playerId: player.id, position };\n const knights = [...(player.knights ?? []), knight];\n const taxAmount = countConstructionSquaresInTerritory(kingdom, position);\n const updatedPlayer = addCoins({ ...player, knights }, taxAmount);\n\n return updatedPlayer;\n};\n","import { canPlaceKnight, placeKnight } from \"@core/domain/entities/knight.js\";\nimport { nextQueenDominoAction } from \"@core/domain/entities/lord.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type {\n GameStateResult,\n GameWithNextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Position } from \"@core/domain/types/kingdom.js\";\nimport { playerActions } from \"@core/domain/types/player.js\";\nimport { err, ok } from \"@utils/result.js\";\n\nexport type PlaceKnightUseCase = (\n game: GameWithNextAction,\n lordId: string,\n position: Position,\n) => GameStateResult;\n\nexport const placeKnightUseCase: PlaceKnightUseCase = (\n game,\n lordId,\n position,\n) => {\n const currentAction = game.nextAction;\n\n if (currentAction.nextLord !== lordId) {\n return err(ErrorCode.NOT_YOUR_TURN);\n }\n\n if (currentAction.nextAction !== playerActions.placeKnight) {\n return err(ErrorCode.INVALID_OPTIONAL_ACTION);\n }\n\n const currentLord = game.lords.find((l) => l.id === lordId);\n if (!currentLord) return err(ErrorCode.LORD_NOT_FOUND);\n\n const currentPlayer = game.players.find((p) => p.id === currentLord.playerId);\n if (!currentPlayer) return err(ErrorCode.PLAYER_NOT_FOUND);\n\n if (!canPlaceKnight(currentPlayer, currentPlayer.kingdom, position)) {\n return err(ErrorCode.CANNOT_PLACE_KNIGHT);\n }\n\n const updatedPlayer = placeKnight(\n currentPlayer,\n currentPlayer.kingdom,\n position,\n );\n\n const updatedPlayers = game.players.map((p) =>\n p.id === currentPlayer.id ? updatedPlayer : p,\n );\n\n const nextAction = nextQueenDominoAction(playerActions.placeKnight);\n\n return ok({\n ...game,\n players: updatedPlayers,\n nextAction: {\n type: \"action\",\n nextLord: lordId,\n nextAction: nextAction,\n },\n });\n};\n","import {\n isValidCavemanPosition,\n takeCavemanFromDrawPile,\n takeCavemanFromVisible,\n} from \"@core/domain/entities/caveman.js\";\nimport {\n allLordsHavePlayed,\n nextLordWithAction,\n} from \"@core/domain/entities/lord.js\";\nimport {\n canSpendResources,\n spendResources,\n} from \"@core/domain/entities/resource.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameState,\n type GameStateResult,\n type GameWithNextAction,\n gameSteps,\n type NextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Position } from \"@core/domain/types/kingdom.js\";\nimport { err, ok } from \"@utils/result.js\";\n\nexport type RecruitCavemanUseCase = (\n game: GameWithNextAction,\n lordId: string,\n cavemanId: number,\n position: Position,\n resourcePositions: Position[],\n) => GameStateResult;\n\nexport const recruitCavemanUseCase: RecruitCavemanUseCase = (\n game,\n lordId,\n cavemanId,\n position,\n resourcePositions,\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 (!game.origins?.caveBoard) {\n return err(ErrorCode.NOT_TRIBE_MODE);\n }\n\n const currentPlayer = game.players.find((p) => p.id === currentLord.playerId);\n\n if (!currentPlayer) {\n return err(ErrorCode.PLAYER_NOT_FOUND);\n }\n\n const resources = currentPlayer.resources ?? [];\n const fireTokens = currentPlayer.fireTokens ?? [];\n const cavemen = currentPlayer.cavemen ?? [];\n\n // Determine if taking from visible (2 different resources) or draw pile (4 different)\n const isFromVisible = game.origins.caveBoard.visible.some(\n (c) => c.id === cavemanId,\n );\n const isFromDrawPile = game.origins.caveBoard.drawPile.some(\n (c) => c.id === cavemanId,\n );\n\n if (!isFromVisible && !isFromDrawPile) {\n return err(ErrorCode.CAVEMAN_NOT_FOUND);\n }\n\n const requiredDifferentTypes = isFromVisible ? 2 : 4;\n const requiredResourceCount = isFromVisible ? 2 : 4;\n\n if (resourcePositions.length !== requiredResourceCount) {\n return err(ErrorCode.INSUFFICIENT_RESOURCES);\n }\n\n if (\n !canSpendResources(resources, resourcePositions, requiredDifferentTypes)\n ) {\n return err(ErrorCode.INSUFFICIENT_RESOURCES);\n }\n\n // Validate caveman placement position\n if (\n !isValidCavemanPosition(\n currentPlayer.kingdom,\n position,\n fireTokens,\n resources,\n cavemen,\n )\n ) {\n return err(ErrorCode.INVALID_CAVEMAN_PLACEMENT);\n }\n\n // Take caveman from board\n let cavemanResult: ReturnType<typeof takeCavemanFromVisible>;\n if (isFromVisible) {\n cavemanResult = takeCavemanFromVisible(game.origins.caveBoard, cavemanId);\n } else {\n cavemanResult = takeCavemanFromDrawPile(game.origins.caveBoard, cavemanId);\n }\n\n if (!cavemanResult) {\n return err(ErrorCode.CAVEMAN_NOT_FOUND);\n }\n\n // Spend resources\n const updatedResources = spendResources(resources, resourcePositions);\n\n // Place caveman\n const updatedCavemen = [\n ...cavemen,\n { caveman: cavemanResult.caveman, position },\n ];\n\n const updatedPlayers = game.players.map((player) => {\n if (player.id === currentPlayer.id) {\n return {\n ...player,\n resources: updatedResources,\n cavemen: updatedCavemen,\n };\n }\n return player;\n });\n\n const updatedOrigins = {\n ...game.origins,\n caveBoard: cavemanResult.updatedBoard,\n };\n\n // Mark lord turn as ended and advance\n const updatedLords = game.lords.map((lord) => {\n if (lord.id === currentLord.id) {\n return { ...lord, turnEnded: true };\n }\n return lord;\n });\n\n const isLastTurn = game.turn === game.rules.basic.maxTurns;\n\n let nextGameAction: GameState;\n\n if (isLastTurn && allLordsHavePlayed(updatedLords)) {\n nextGameAction = {\n ...game,\n players: updatedPlayers,\n lords: updatedLords,\n origins: updatedOrigins,\n nextAction: { type: \"step\", step: gameSteps.result },\n };\n } else {\n nextGameAction = {\n ...game,\n players: updatedPlayers,\n lords: updatedLords,\n origins: updatedOrigins,\n nextAction: nextLordWithAction(updatedLords) as NextAction,\n };\n }\n\n return ok(nextGameAction);\n};\n","import { isAgeOfGiantsQueenDominoMode } from \"@core/domain/entities/ageOfGiantsHelpers.js\";\nimport { sendGiantToOpponent } from \"@core/domain/entities/giant.js\";\nimport {\n allLordsHavePlayed,\n nextAgeOfGiantsAction,\n nextLordWithAction,\n} from \"@core/domain/entities/lord.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameStateResult,\n type GameWithNextAction,\n gameSteps,\n type NextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Position } from \"@core/domain/types/kingdom.js\";\nimport { playerActions } from \"@core/domain/types/player.js\";\nimport { err, isErr, ok } from \"@utils/result.js\";\n\nexport type SendGiantUseCase = (\n game: GameWithNextAction,\n lordId: string,\n giantIndex: number,\n targetPlayerId: string,\n targetCrownPosition: Position,\n) => GameStateResult;\n\nexport const sendGiantUseCase: SendGiantUseCase = (\n game,\n lordId,\n giantIndex,\n targetPlayerId,\n targetCrownPosition,\n) => {\n const currentAction = game.nextAction;\n\n if (currentAction.nextAction !== playerActions.sendGiant) {\n return err(ErrorCode.INVALID_OPTIONAL_ACTION);\n }\n\n if (currentAction.nextLord !== lordId) {\n return err(ErrorCode.NOT_YOUR_TURN);\n }\n\n if (!game.ageOfGiants) {\n return err(ErrorCode.NOT_AOG_MODE);\n }\n\n const currentLord = game.lords.find((l) => l.id === lordId);\n if (!currentLord) {\n return err(ErrorCode.LORD_NOT_FOUND);\n }\n\n const sourcePlayer = game.players.find((p) => p.id === currentLord.playerId);\n if (!sourcePlayer) {\n return err(ErrorCode.PLAYER_NOT_FOUND);\n }\n\n const targetPlayer = game.players.find((p) => p.id === targetPlayerId);\n if (!targetPlayer) {\n return err(ErrorCode.PLAYER_NOT_FOUND);\n }\n\n if (sourcePlayer.id === targetPlayer.id) {\n return err(ErrorCode.INVALID_GIANT_PLACEMENT);\n }\n\n const result = sendGiantToOpponent(\n sourcePlayer,\n targetPlayer,\n giantIndex,\n targetCrownPosition,\n );\n if (isErr(result)) {\n return result;\n }\n\n const updatedPlayers = game.players.map((p) => {\n if (p.id === result.value.source.id) return result.value.source;\n if (p.id === result.value.target.id) return result.value.target;\n return p;\n });\n\n // Determine next action\n const isAoGQD = isAgeOfGiantsQueenDominoMode(game.mode.name);\n const nextAction = nextAgeOfGiantsAction(playerActions.sendGiant, isAoGQD);\n\n if (nextAction === playerActions.pickDomino) {\n const isLastTurn = game.turn === game.rules.basic.maxTurns;\n if (isLastTurn && allLordsHavePlayed(game.lords)) {\n return ok({\n ...game,\n players: updatedPlayers,\n nextAction: { type: \"step\", step: gameSteps.result },\n });\n }\n return ok({\n ...game,\n players: updatedPlayers,\n nextAction: nextLordWithAction(game.lords) as NextAction,\n });\n }\n\n return ok({\n ...game,\n players: updatedPlayers,\n nextAction: {\n type: \"action\",\n nextLord: lordId,\n nextAction: nextAction,\n },\n });\n};\n","import { isAgeOfGiantsQueenDominoMode } from \"@core/domain/entities/ageOfGiantsHelpers.js\";\nimport {\n allLordsHavePlayed,\n nextAgeOfGiantsAction,\n nextLordWithAction,\n nextOriginsAction,\n nextQueenDominoAction,\n} from \"@core/domain/entities/lord.js\";\nimport { isTribeMode } from \"@core/domain/entities/originsHelpers.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameStateResult,\n type GameWithNextAction,\n gameSteps,\n type NextAction,\n} from \"@core/domain/types/game.js\";\nimport { playerActions } from \"@core/domain/types/player.js\";\nimport { err, ok } from \"@utils/result.js\";\n\nexport type SkipOptionalActionUseCase = (\n game: GameWithNextAction,\n lordId: string,\n) => GameStateResult;\n\nexport const skipOptionalActionUseCase: SkipOptionalActionUseCase = (\n game,\n lordId,\n) => {\n const currentAction = game.nextAction;\n\n if (currentAction.nextLord !== lordId) {\n return err(ErrorCode.NOT_YOUR_TURN);\n }\n\n const action = currentAction.nextAction;\n\n // Queendomino optional actions\n const isQueenDominoOptional =\n action === playerActions.placeKnight ||\n action === playerActions.constructBuilding ||\n action === playerActions.useDragon;\n\n // Origins optional actions\n const isOriginsOptional =\n action === playerActions.placeFireToken ||\n action === playerActions.recruitCaveman;\n\n // Age of Giants optional actions (sendGiant is optional; placeGiant is mandatory but auto-skipped when no crowns)\n const isAoGOptional =\n action === playerActions.sendGiant || action === playerActions.placeGiant;\n\n if (!isQueenDominoOptional && !isOriginsOptional && !isAoGOptional) {\n return err(ErrorCode.INVALID_OPTIONAL_ACTION);\n }\n\n if (isAoGOptional) {\n return handleAoGSkip(game, lordId, action);\n }\n\n if (isOriginsOptional) {\n return handleOriginsSkip(game, lordId, action);\n }\n\n // Queendomino skip logic\n const nextAction = nextQueenDominoAction(action);\n\n if (nextAction === playerActions.pickDomino) {\n return advanceToNextLordOrResult(game);\n }\n\n return ok({\n ...game,\n nextAction: {\n type: \"action\",\n nextLord: lordId,\n nextAction: nextAction,\n },\n });\n};\n\nconst handleOriginsSkip = (\n game: GameWithNextAction,\n lordId: string,\n action: string,\n): GameStateResult => {\n // Clear pending fire token if skipping fire token placement\n let updatedOrigins = game.origins;\n if (\n action === playerActions.placeFireToken &&\n updatedOrigins?.pendingFireToken\n ) {\n updatedOrigins = {\n ...updatedOrigins,\n pendingFireToken: undefined,\n };\n }\n\n const tribe = isTribeMode(game.mode.name);\n const nextAction = nextOriginsAction(\n action as typeof playerActions.placeFireToken,\n tribe,\n );\n\n const updatedGame = {\n ...game,\n ...(updatedOrigins !== undefined && { origins: updatedOrigins }),\n };\n\n // pickDomino means we're done with pre-pick optional actions\n if (nextAction === playerActions.pickDomino) {\n return advanceToNextLordOrResult(updatedGame);\n }\n\n // recruitCaveman is the final optional action in Tribe mode\n // The turn transition already happened in chooseDomino, just advance\n if (action === playerActions.recruitCaveman) {\n return advanceToNextLordOrResult(updatedGame);\n }\n\n return ok({\n ...updatedGame,\n nextAction: {\n type: \"action\",\n nextLord: lordId,\n nextAction: nextAction,\n },\n });\n};\n\nconst handleAoGSkip = (\n game: GameWithNextAction,\n lordId: string,\n action: string,\n): GameStateResult => {\n const isAoGQD = isAgeOfGiantsQueenDominoMode(game.mode.name);\n const nextAction = nextAgeOfGiantsAction(\n action as typeof playerActions.placeGiant | typeof playerActions.sendGiant,\n isAoGQD,\n );\n\n if (nextAction === playerActions.pickDomino) {\n return advanceToNextLordOrResult(game);\n }\n\n // More optional actions (e.g., QD actions in AoG-QD mode)\n return ok({\n ...game,\n nextAction: {\n type: \"action\",\n nextLord: lordId,\n nextAction: nextAction,\n },\n });\n};\n\nconst advanceToNextLordOrResult = (\n game: GameWithNextAction,\n): GameStateResult => {\n const maxTurns = game.rules.basic.maxTurns;\n const isLastTurn = game.turn === maxTurns;\n\n if (isLastTurn && allLordsHavePlayed(game.lords)) {\n return ok({\n ...game,\n nextAction: { type: \"step\", step: gameSteps.result },\n });\n }\n\n return ok({\n ...game,\n nextAction: nextLordWithAction(game.lords) as NextAction,\n });\n};\n","import { isAgeOfGiantsQueenDominoMode } from \"@core/domain/entities/ageOfGiantsHelpers.js\";\nimport { createBuildersBoard } from \"@core/domain/entities/building.js\";\nimport { createCaveBoard } from \"@core/domain/entities/caveman.js\";\nimport { createLord } from \"@core/domain/entities/lord\";\nimport { isTribeMode } from \"@core/domain/entities/originsHelpers.js\";\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\n // Age of Giants: discard some dominos from the sorted line before selection\n const discardCount = game.rules.basic.dominoesDiscardedPerTurn ?? 0;\n if (discardCount > 0) {\n dominoesDrawn.splice(0, discardCount);\n }\n\n const nextAction: NextAction = {\n type: \"action\",\n nextLord: shuffledLords[0]!.id,\n nextAction: playerActions.pickDomino,\n };\n\n // Setup Builders Board for QueenDomino mode (including AoG-QD)\n let queendomino = game.queendomino;\n if (\n queendomino &&\n (game.mode.name === \"QueenDomino\" ||\n isAgeOfGiantsQueenDominoMode(game.mode.name))\n ) {\n const buildingShuffle = game.seed\n ? createSeededShuffle(game.seed, \"buildings\")\n : shuffleMethod;\n const board = createBuildersBoard(\n queendomino.buildersBoard.drawPile,\n buildingShuffle,\n );\n queendomino = { ...queendomino, buildersBoard: board };\n }\n\n // Setup Cave Board for Tribe mode\n let origins = game.origins;\n if (origins?.caveBoard && isTribeMode(game.mode.name)) {\n const caveShuffle = game.seed\n ? createSeededShuffle(game.seed, \"cavemen\")\n : shuffleMethod;\n const board = createCaveBoard(origins.caveBoard.drawPile, caveShuffle);\n origins = { ...origins, caveBoard: board };\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 ...(queendomino !== undefined && { queendomino }),\n ...(origins !== undefined && { origins }),\n };\n\n return ok(newState);\n };\n","import { destroyWithDragon } from \"@core/domain/entities/building.js\";\nimport {\n allLordsHavePlayed,\n nextLordWithAction,\n} from \"@core/domain/entities/lord.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameStateResult,\n type GameWithNextAction,\n gameSteps,\n type NextAction,\n} from \"@core/domain/types/game.js\";\nimport { playerActions } from \"@core/domain/types/player.js\";\nimport { err, ok } from \"@utils/result.js\";\n\nexport type UseDragonUseCase = (\n game: GameWithNextAction,\n lordId: string,\n buildingId: number,\n) => GameStateResult;\n\nexport const useDragonUseCase: UseDragonUseCase = (\n game,\n lordId,\n buildingId,\n) => {\n const currentAction = game.nextAction;\n\n if (currentAction.nextLord !== lordId) {\n return err(ErrorCode.NOT_YOUR_TURN);\n }\n\n if (currentAction.nextAction !== playerActions.useDragon) {\n return err(ErrorCode.INVALID_OPTIONAL_ACTION);\n }\n\n if (!game.queendomino) {\n return err(ErrorCode.INVALID_OPTIONAL_ACTION);\n }\n\n if (\n !game.queendomino.dragonAvailable ||\n game.queendomino.dragonUsedThisRound\n ) {\n return err(ErrorCode.DRAGON_UNAVAILABLE);\n }\n\n const currentLord = game.lords.find((l) => l.id === lordId);\n if (!currentLord) return err(ErrorCode.LORD_NOT_FOUND);\n\n const currentPlayer = game.players.find((p) => p.id === currentLord.playerId);\n if (!currentPlayer) return err(ErrorCode.PLAYER_NOT_FOUND);\n\n // Queen holder cannot use dragon\n if (game.queendomino.queenHolderId === currentPlayer.id) {\n return err(ErrorCode.QUEEN_HOLDER_CANNOT_USE_DRAGON);\n }\n\n const result = destroyWithDragon(\n game.queendomino.buildersBoard,\n buildingId,\n currentPlayer,\n );\n\n if (!result) {\n return err(ErrorCode.BUILDING_NOT_FOUND);\n }\n\n const { updatedBoard, updatedPlayer } = result;\n\n const updatedPlayers = game.players.map((p) =>\n p.id === currentPlayer.id ? updatedPlayer : p,\n );\n\n // After dragon, advance to pickDomino (or result)\n const maxTurns = game.rules.basic.maxTurns;\n const isLastTurn = game.turn === maxTurns;\n\n if (isLastTurn && allLordsHavePlayed(game.lords)) {\n return ok({\n ...game,\n players: updatedPlayers,\n queendomino: {\n ...game.queendomino,\n buildersBoard: updatedBoard,\n dragonUsedThisRound: true,\n },\n nextAction: { type: \"step\", step: gameSteps.result },\n });\n }\n\n return ok({\n ...game,\n players: updatedPlayers,\n queendomino: {\n ...game.queendomino,\n buildersBoard: updatedBoard,\n dragonUsedThisRound: true,\n },\n nextAction: <NextAction>nextLordWithAction(game.lords),\n });\n};\n","import { consoleLogger, silentLogger } from \"@adapter/consoleLogger.js\";\nimport jsonBuildings from \"@adapter/jsonBuildings.js\";\nimport jsonCavemen from \"@adapter/jsonCavemen.js\";\nimport jsonDominoes from \"@adapter/jsonDominoes.js\";\nimport jsonModes from \"@adapter/jsonModes.js\";\nimport jsonQuestTiles from \"@adapter/jsonQuestTiles.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 { constructBuildingHandler } from \"@application/handlers/constructBuildingHandler.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 { placeFireTokenHandler } from \"@application/handlers/placeFireTokenHandler.js\";\nimport { placeGiantHandler } from \"@application/handlers/placeGiantHandler.js\";\nimport { placeKnightHandler } from \"@application/handlers/placeKnightHandler.js\";\nimport { recruitCavemanHandler } from \"@application/handlers/recruitCavemanHandler.js\";\nimport { sendGiantHandler } from \"@application/handlers/sendGiantHandler.js\";\nimport {\n deserializeGameHandler,\n serializeGameHandler,\n} from \"@application/handlers/serializeGameHandler.js\";\nimport { skipOptionalActionHandler } from \"@application/handlers/skipOptionalActionHandler.js\";\nimport { startGameHandler } from \"@application/handlers/startGameHandler.js\";\nimport { useDragonHandler } from \"@application/handlers/useDragonHandler.js\";\nimport type { Translator } from \"@core/i18n/translations.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 type { GameEngine } from \"@core/portUserside/engine.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 { constructBuildingUseCase } from \"@core/useCases/constructBuilding.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 { placeFireTokenUseCase } from \"@core/useCases/placeFireToken.js\";\nimport { placeGiantUseCase } from \"@core/useCases/placeGiant.js\";\nimport { placeKnightUseCase } from \"@core/useCases/placeKnight.js\";\nimport { recruitCavemanUseCase } from \"@core/useCases/recruitCaveman.js\";\nimport { sendGiantUseCase } from \"@core/useCases/sendGiant.js\";\nimport { skipOptionalActionUseCase } from \"@core/useCases/skipOptionalAction.js\";\nimport { startGameUseCase } from \"@core/useCases/startGame.js\";\nimport { useDragonUseCase } from \"@core/useCases/useDragon.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 placeGiantHandler: GameEngine[\"placeGiant\"];\n sendGiantHandler: GameEngine[\"sendGiant\"];\n placeKnightHandler: GameEngine[\"placeKnight\"];\n constructBuildingHandler: GameEngine[\"constructBuilding\"];\n useDragonHandler: GameEngine[\"useDragon\"];\n placeFireTokenHandler: GameEngine[\"placeFireToken\"];\n recruitCavemanHandler: GameEngine[\"recruitCaveman\"];\n skipOptionalActionHandler: GameEngine[\"skipOptionalAction\"];\n};\n\nexport const configureEngine = (\n config: Partial<EngineConfig>,\n): ConfiguredHandlers => {\n const modeRepository = jsonModes();\n const dominoesRepository = jsonDominoes();\n const buildingsRepository = jsonBuildings();\n const cavemenRepository = jsonCavemen();\n const questTilesRepository = jsonQuestTiles();\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 shuffleMethod: shuffle,\n buildingsRepository,\n cavemenRepository,\n questTilesRepository,\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 placeGiantHandler: placeGiantHandler(logger, translator, placeGiantUseCase),\n sendGiantHandler: sendGiantHandler(logger, translator, sendGiantUseCase),\n placeKnightHandler: placeKnightHandler(\n logger,\n translator,\n placeKnightUseCase,\n ),\n constructBuildingHandler: constructBuildingHandler(\n logger,\n translator,\n constructBuildingUseCase,\n ),\n useDragonHandler: useDragonHandler(logger, translator, useDragonUseCase),\n placeFireTokenHandler: placeFireTokenHandler(\n logger,\n translator,\n placeFireTokenUseCase,\n ),\n recruitCavemanHandler: recruitCavemanHandler(\n logger,\n translator,\n recruitCavemanUseCase,\n ),\n skipOptionalActionHandler: skipOptionalActionHandler(\n logger,\n translator,\n skipOptionalActionUseCase,\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 {\n ValidationIssue,\n ValidationSeverity,\n} 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(\n issue(\"id\", \"INVALID_ID\", \"Game id must be a non-empty string\"),\n );\n }\n if (!isNonNegativeInteger(game.turn)) {\n issues.push(\n issue(\"turn\", \"INVALID_TURN\", \"Turn must be a non-negative integer\"),\n );\n }\n if (!Array.isArray(game.dominoes)) {\n issues.push(\n issue(\"dominoes\", \"INVALID_DOMINOES\", \"Dominoes must be an array\"),\n );\n }\n if (!Array.isArray(game.currentDominoes)) {\n issues.push(\n issue(\n \"currentDominoes\",\n \"INVALID_CURRENT_DOMINOES\",\n \"CurrentDominoes must be an array\",\n ),\n );\n }\n if (!Array.isArray(game.players)) {\n issues.push(\n issue(\"players\", \"INVALID_PLAYERS\", \"Players must be an array\"),\n );\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(\n issue(\n \"rules.basic\",\n \"INVALID_BASIC_RULES\",\n \"Rules.basic must be an object\",\n ),\n );\n }\n if (!Array.isArray(game.rules.extra)) {\n issues.push(\n issue(\n \"rules.extra\",\n \"INVALID_EXTRA_RULES\",\n \"Rules.extra must be an array\",\n ),\n );\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(\n issue(\n \"mode.name\",\n \"INVALID_MODE_NAME\",\n \"Mode name must be a non-empty string\",\n ),\n );\n }\n }\n if (!game.nextAction || typeof game.nextAction !== \"object\") {\n issues.push(\n issue(\n \"nextAction\",\n \"INVALID_NEXT_ACTION\",\n \"NextAction must be an object\",\n ),\n );\n } else if (\n game.nextAction.type !== \"action\" &&\n game.nextAction.type !== \"step\"\n ) {\n issues.push(\n issue(\n \"nextAction.type\",\n \"INVALID_NEXT_ACTION_TYPE\",\n \"NextAction.type must be 'action' or 'step'\",\n ),\n );\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(\n issue(path, \"INVALID_TILE\", `Tile at ${path} must be an object`),\n );\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(\n issue(\n `${path}.type`,\n \"INVALID_TILE_TYPE\",\n `Invalid terrain type at ${path}`,\n ),\n );\n }\n if (typeof t.crowns !== \"number\" || t.crowns < 0) {\n issues.push(\n issue(\n `${path}.crowns`,\n \"INVALID_TILE_CROWNS\",\n `Invalid crowns at ${path}`,\n ),\n );\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(\n issue(\n `${path}.id`,\n \"INVALID_PLAYER_ID\",\n `Player id must be a non-empty string`,\n ),\n );\n } else if (playerIds.has(player.id)) {\n issues.push(\n issue(\n `${path}.id`,\n \"DUPLICATE_PLAYER_ID\",\n `Duplicate player id: ${player.id}`,\n ),\n );\n } else {\n playerIds.add(player.id);\n }\n\n if (typeof player.name !== \"string\" || player.name.length < 3) {\n issues.push(\n issue(\n `${path}.name`,\n \"INVALID_PLAYER_NAME\",\n `Player name must be at least 3 characters`,\n ),\n );\n }\n\n // Kingdom validation\n if (!Array.isArray(player.kingdom)) {\n issues.push(\n issue(\n `${path}.kingdom`,\n \"INVALID_KINGDOM\",\n `Kingdom must be a 2D array`,\n ),\n );\n continue;\n }\n if (player.kingdom.length !== GRIDSIZE) {\n issues.push(\n issue(\n `${path}.kingdom`,\n \"INVALID_KINGDOM_GRID\",\n `Kingdom must have ${GRIDSIZE} rows, got ${player.kingdom.length}`,\n ),\n );\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(\n issue(\n `${path}.kingdom[${y}]`,\n \"INVALID_KINGDOM_ROW\",\n `Kingdom row ${y} must have ${GRIDSIZE} columns`,\n ),\n );\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 (\n cell &&\n typeof cell === \"object\" &&\n (cell as Record<string, unknown>).type === \"castle\"\n ) {\n castleCount++;\n }\n }\n }\n if (castleCount === 0) {\n issues.push(\n issue(\n `${path}.kingdom`,\n \"MISSING_CASTLE\",\n `Kingdom must have exactly one castle tile`,\n \"warning\",\n ),\n );\n } else if (castleCount > 1) {\n issues.push(\n issue(\n `${path}.kingdom`,\n \"MULTIPLE_CASTLES\",\n `Kingdom has ${castleCount} castle tiles, expected 1`,\n ),\n );\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(\n issue(\n `${path}.number`,\n \"INVALID_DOMINO_NUMBER\",\n `Domino number must be a positive integer`,\n ),\n );\n } else if (allNumbers.has(domino.number)) {\n issues.push(\n issue(\n `${path}.number`,\n \"DUPLICATE_DOMINO_NUMBER\",\n `Duplicate domino number: ${domino.number}`,\n ),\n );\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(\n issue(\n `${path}.domino`,\n \"INVALID_REVEALED_DOMINO\",\n `Revealed domino must be an object`,\n ),\n );\n continue;\n }\n\n const domino = revealed.domino;\n if (!isPositiveInteger(domino.number)) {\n issues.push(\n issue(\n `${path}.domino.number`,\n \"INVALID_DOMINO_NUMBER\",\n `Domino number must be a positive integer`,\n ),\n );\n } else if (allNumbers.has(domino.number)) {\n issues.push(\n issue(\n `${path}.domino.number`,\n \"DUPLICATE_DOMINO_NUMBER\",\n `Duplicate domino number: ${domino.number}`,\n ),\n );\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(\n issue(\n `${path}`,\n \"PICKED_WITHOUT_LORD\",\n `Domino is marked as picked but has no lordId`,\n ),\n );\n }\n if (!revealed.picked && revealed.lordId !== null) {\n issues.push(\n issue(\n `${path}`,\n \"UNPICKED_WITH_LORD\",\n `Domino is not picked but has a lordId`,\n ),\n );\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(\n issue(\n `${path}.number`,\n \"INVALID_DOMINO_NUMBER\",\n `Domino number must be a positive integer`,\n ),\n );\n } else if (lordPickedNumbers.has(domino.number)) {\n issues.push(\n issue(\n `${path}.number`,\n \"DUPLICATE_DOMINO_NUMBER\",\n `Duplicate domino number among lords: ${domino.number}`,\n ),\n );\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(\n issue(\n `${path}.id`,\n \"INVALID_LORD_ID\",\n `Lord id must be a non-empty string`,\n ),\n );\n } else if (lordIds.has(lord.id)) {\n issues.push(\n issue(\n `${path}.id`,\n \"DUPLICATE_LORD_ID\",\n `Duplicate lord id: ${lord.id}`,\n ),\n );\n } else {\n lordIds.add(lord.id);\n }\n\n if (!isNonEmptyString(lord.playerId)) {\n issues.push(\n issue(\n `${path}.playerId`,\n \"INVALID_LORD_PLAYER_ID\",\n `Lord playerId must be a non-empty string`,\n ),\n );\n } else if (playerIds.size > 0 && !playerIds.has(lord.playerId)) {\n issues.push(\n issue(\n `${path}.playerId`,\n \"LORD_PLAYER_NOT_FOUND\",\n `Lord references non-existent player: ${lord.playerId}`,\n ),\n );\n }\n\n if (lord.turnEnded && (!lord.hasPick || !lord.hasPlace)) {\n issues.push(\n issue(\n path,\n \"INCONSISTENT_LORD_FLAGS\",\n `Lord has turnEnded=true but hasPick=${lord.hasPick}, hasPlace=${lord.hasPlace}`,\n \"warning\",\n ),\n );\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 {\n type: \"action\";\n nextLord?: unknown;\n nextAction?: unknown;\n };\n\n if (!isNonEmptyString(action.nextLord)) {\n issues.push(\n issue(\n \"nextAction.nextLord\",\n \"INVALID_NEXT_LORD\",\n \"nextLord must be a non-empty string\",\n ),\n );\n } else if (\n Array.isArray(game.lords) &&\n !game.lords.some((l) => l.id === action.nextLord)\n ) {\n issues.push(\n issue(\n \"nextAction.nextLord\",\n \"NEXT_LORD_NOT_FOUND\",\n `nextLord references non-existent lord: ${action.nextLord as string}`,\n ),\n );\n }\n\n if (\n typeof action.nextAction !== \"string\" ||\n !validPlayerActions.has(action.nextAction as string)\n ) {\n issues.push(\n issue(\n \"nextAction.nextAction\",\n \"INVALID_PLAYER_ACTION\",\n `nextAction must be one of: ${[...validPlayerActions].join(\", \")}`,\n ),\n );\n }\n } else if (nextAction.type === \"step\") {\n const step = nextAction as { type: \"step\"; step?: unknown };\n\n if (\n typeof step.step !== \"string\" ||\n !validGameSteps.has(step.step as string)\n ) {\n issues.push(\n issue(\n \"nextAction.step\",\n \"INVALID_GAME_STEP\",\n `step must be one of: ${[...validGameSteps].join(\", \")}`,\n ),\n );\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 = [\n \"lords\",\n \"maxDominoes\",\n \"dominoesPerTurn\",\n \"maxTurns\",\n \"maxKingdomSize\",\n ] as const;\n for (const field of fields) {\n const check = allowZero ? isNonNegativeInteger : isPositiveInteger;\n if (!check(basic[field])) {\n issues.push(\n issue(\n `rules.basic.${field}`,\n \"INVALID_BASIC_RULE_VALUE\",\n `rules.basic.${field} must be a positive integer`,\n ),\n );\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(\n issue(\n `rules.extra[${i}].name`,\n \"INVALID_EXTRA_RULE_NAME\",\n `Extra rule name must be a non-empty string`,\n ),\n );\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 advancedStrategy,\n expertStrategy,\n greedyStrategy,\n randomStrategy,\n} from \"./bot.js\";\n\n/**\n * Built-in strategy names.\n */\nexport type StrategyName = \"random\" | \"greedy\" | \"advanced\" | \"expert\";\n\n// Use a getter function to avoid circular dependency issues with bot.ts.\n// When biome sorts imports, bot.ts may not be fully initialized when this\n// module-level code runs. Deferring access to the strategies ensures they\n// are resolved at call time, not at module evaluation time.\nconst getDefaultStrategies = (): 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] ?? getDefaultStrategies()[name];\n};\n\n/**\n * Returns the list of built-in strategy names.\n */\nexport const getStrategyNames = (): string[] =>\n Object.keys(getDefaultStrategies());\n","import { findCrownsNotCoveredByGiants } from \"@core/domain/entities/giant.js\";\nimport { placeDomino } from \"@core/domain/entities/kingdom.js\";\nimport { isGameWithNextAction } from \"@core/domain/types/game.js\";\nimport type {\n Domino,\n GameState,\n GameWithNextAction,\n Kingdom,\n RevealsDomino,\n} from \"@core/domain/types/index.js\";\nimport type { GameEngine } from \"@core/portUserside/engine.js\";\nimport { isOk } from \"@utils/result.js\";\nimport { getStrategy } from \"./botRegistry.js\";\nimport { calculateScoreUseCase } from \"./calculateScore.js\";\nimport type { ValidPlacement } from \"./getValidPlacements.js\";\nimport { getValidPlacementsUseCase } from \"./getValidPlacements.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: {\n placement: ValidPlacement;\n score: number;\n kingdom: Kingdom;\n } | null = null;\n\n for (const placement of placements) {\n const newKingdom = simulatePlacement(\n kingdom,\n domino,\n placement,\n maxKingdomSize,\n );\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(\n kingdom,\n domino,\n validPlacements,\n maxSize,\n );\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(\n kingdom,\n nextDomino,\n maxSize,\n );\n const result = bestPlacementScore(\n kingdom,\n nextDomino,\n nextPlacements,\n maxSize,\n );\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\n ? result.score\n : scoreKingdom(player.kingdom);\n const kingdomAfter = result ? result.kingdom : player.kingdom;\n const futureScore = evaluateWithLookahead(\n kingdomAfter,\n maxSize,\n nextBatch,\n );\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 // Age of Giants: placeGiant — place on a crown (mandatory, auto-handled)\n if (action === \"placeGiant\") {\n // Find the least valuable crown to cover (one with most crowns in smallest property)\n const player = game.players.find((p) => {\n const lord = game.lords.find((l) => l.id === lordId);\n return lord && p.id === lord.playerId;\n });\n if (player) {\n const availableCrowns = findCrownsNotCoveredByGiants(\n player.kingdom,\n player.giants ?? [],\n );\n if (availableCrowns.length > 0) {\n // Pick first available crown (simple bot behavior)\n return engine.placeGiant({\n game,\n lordId,\n position: availableCrowns[0]!,\n });\n }\n }\n return engine.skipOptionalAction({ game, lordId });\n }\n\n // Optional actions (Queendomino, Origins, AoG sendGiant) - skip them\n if (\n action === \"placeKnight\" ||\n action === \"constructBuilding\" ||\n action === \"useDragon\" ||\n action === \"placeFireToken\" ||\n action === \"recruitCaveman\" ||\n action === \"sendGiant\"\n ) {\n return engine.skipOptionalAction({ game, lordId });\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 { PlayerInput } from \"@application/commands/addPlayersCommand.js\";\nimport type {\n GameState,\n GameWithNextAction,\n Position,\n Rotation,\n} from \"@core/domain/types/index.js\";\nimport type { GameEngine } from \"@core/portUserside/engine.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 | \"placeGiant\"\n | \"sendGiant\";\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 placeGiant: { lordId: string; position: Position };\n sendGiant: {\n lordId: string;\n giantIndex: number;\n targetPlayerId: string;\n targetCrownPosition: Position;\n };\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 // Queendomino methods — pass through (no action log recording yet)\n placeKnight: (cmd) => engine.placeKnight(cmd),\n constructBuilding: (cmd) => engine.constructBuilding(cmd),\n useDragon: (cmd) => engine.useDragon(cmd),\n skipOptionalAction: (cmd) => engine.skipOptionalAction(cmd),\n\n // Origins methods — pass through (no action log recording yet)\n placeFireToken: (cmd) => engine.placeFireToken(cmd),\n recruitCaveman: (cmd) => engine.recruitCaveman(cmd),\n\n // Age of Giants methods — record after execution\n placeGiant: (cmd) => {\n const game = engine.placeGiant(cmd);\n record(\n \"placeGiant\",\n { lordId: cmd.lordId, position: cmd.position },\n game.turn,\n );\n return game;\n },\n\n sendGiant: (cmd) => {\n const game = engine.sendGiant(cmd);\n record(\n \"sendGiant\",\n {\n lordId: cmd.lordId,\n giantIndex: cmd.giantIndex,\n targetPlayerId: cmd.targetPlayerId,\n targetCrownPosition: cmd.targetCrownPosition,\n },\n game.turn,\n );\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 case \"placeGiant\": {\n const payload = entry.payload as ActionPayloadMap[\"placeGiant\"];\n game = engine.placeGiant({\n game: game as GameWithNextAction,\n lordId: payload.lordId,\n position: payload.position,\n });\n break;\n }\n case \"sendGiant\": {\n const payload = entry.payload as ActionPayloadMap[\"sendGiant\"];\n game = engine.sendGiant({\n game: game as GameWithNextAction,\n lordId: payload.lordId,\n giantIndex: payload.giantIndex,\n targetPlayerId: payload.targetPlayerId,\n targetCrownPosition: payload.targetCrownPosition,\n });\n break;\n }\n }\n }\n\n return game;\n};\n","import { RedoError, UndoError } from \"@core/domain/errors/domainErrors.js\";\nimport type { GameState } from \"@core/domain/types/index.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\";\nexport type { ConstructBuildingUseCase } from \"@core/useCases/constructBuilding.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 type { PlaceFireTokenUseCase } from \"@core/useCases/placeFireToken.js\";\nexport type { PlaceGiantUseCase } from \"@core/useCases/placeGiant.js\";\nexport type { PlaceKnightUseCase } from \"@core/useCases/placeKnight.js\";\nexport type { RecruitCavemanUseCase } from \"@core/useCases/recruitCaveman.js\";\nexport type { SendGiantUseCase } from \"@core/useCases/sendGiant.js\";\nexport {\n createSavePoint,\n deserializeGame,\n type GameSavePoint,\n restoreFromSavePoint,\n serializeGame,\n} from \"@core/useCases/serialization.js\";\nexport type { SkipOptionalActionUseCase } from \"@core/useCases/skipOptionalAction.js\";\nexport type { UseDragonUseCase } from \"@core/useCases/useDragon.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 placeGiantHandler,\n sendGiantHandler,\n placeKnightHandler,\n constructBuildingHandler,\n useDragonHandler,\n placeFireTokenHandler,\n recruitCavemanHandler,\n skipOptionalActionHandler,\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 placeGiant: (command) => placeGiantHandler(command),\n sendGiant: (command) => sendGiantHandler(command),\n placeKnight: (command) => placeKnightHandler(command),\n constructBuilding: (command) => constructBuildingHandler(command),\n useDragon: (command) => useDragonHandler(command),\n placeFireToken: (command) => placeFireTokenHandler(command),\n recruitCaveman: (command) => recruitCavemanHandler(command),\n skipOptionalAction: (command) => skipOptionalActionHandler(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","ORIGINS_MODE_PREFIX","uuidMethod","shuffleMethod","lord","next","uuidMethod","shuffleMethod","getBoundingBox","currentPlayer","uuidMethod","shuffleMethod","createGameHandler","getModesHandler","getExtraRulesHandler","addPlayersHandler","addExtraRulesHandler","startGameHandler","chooseDominoHandler","placeDominoHandler","discardDominoHandler","getResultHandler","calculateScoreHandler","getValidPlacementsHandler","canPlaceDominoHandler","serializeGameHandler","deserializeGameHandler","getDynastyResultHandler","placeGiantHandler","sendGiantHandler","placeKnightHandler","constructBuildingHandler","useDragonHandler","placeFireTokenHandler","recruitCavemanHandler","skipOptionalActionHandler"]}
|
|
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/buildings.json","../src/adapterServerside/jsonBuildings.ts","../src/datasources/cavemen.json","../src/adapterServerside/jsonCavemen.ts","../src/datasources/dominoes.json","../src/adapterServerside/jsonDominoes.ts","../src/datasources/modes.json","../src/adapterServerside/jsonModes.ts","../src/datasources/questTiles.json","../src/adapterServerside/jsonQuestTiles.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/calculatePlayerScoreHandler.ts","../src/application/handlers/calculateScoreHandler.ts","../src/application/handlers/canPlaceDominoHandler.ts","../src/application/handlers/chooseDominoHandler.ts","../src/application/handlers/constructBuildingHandler.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/getValidActionTargetsHandler.ts","../src/application/handlers/getValidPlacementsHandler.ts","../src/application/handlers/placeDominoHandler.ts","../src/application/handlers/placeFireTokenHandler.ts","../src/application/handlers/placeGiantHandler.ts","../src/application/handlers/placeKnightHandler.ts","../src/application/handlers/recruitCavemanHandler.ts","../src/application/handlers/sendGiantHandler.ts","../src/core/useCases/serialization.ts","../src/application/handlers/serializeGameHandler.ts","../src/application/handlers/skipOptionalActionHandler.ts","../src/application/handlers/startGameHandler.ts","../src/application/handlers/useDragonHandler.ts","../src/core/domain/entities/rule.ts","../src/core/domain/types/ageOfGiants.ts","../src/core/domain/types/domino.ts","../src/core/domain/types/kingdom.ts","../src/core/domain/types/origins.ts","../src/core/domain/types/player.ts","../src/core/domain/types/score.ts","../src/utils/seededShuffle.ts","../src/core/useCases/addExtraRules.ts","../src/core/domain/entities/ageOfGiantsHelpers.ts","../src/core/domain/entities/economy.ts","../src/core/domain/entities/domino.ts","../src/core/domain/entities/kingdom.ts","../src/core/domain/entities/originsHelpers.ts","../src/core/domain/entities/player.ts","../src/core/useCases/addPlayers.ts","../src/core/domain/entities/caveman.ts","../src/core/domain/entities/originsScore.ts","../src/core/domain/entities/queen.ts","../src/core/domain/entities/questScore.ts","../src/core/domain/entities/resource.ts","../src/core/domain/entities/totem.ts","../src/core/domain/entities/scoreBreakdown.ts","../src/core/useCases/calculatePlayerScore.ts","../src/core/useCases/calculateScore.ts","../src/core/domain/entities/building.ts","../src/core/domain/entities/lord.ts","../src/core/useCases/chooseDomino.ts","../src/core/useCases/constructBuilding.ts","../src/core/domain/entities/fireToken.ts","../src/core/domain/entities/giant.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/domain/entities/knight.ts","../src/core/useCases/placeFireToken.ts","../src/core/useCases/sendGiant.ts","../src/core/useCases/placeGiant.ts","../src/core/useCases/placeKnight.ts","../src/core/useCases/recruitCaveman.ts","../src/core/useCases/skipOptionalAction.ts","../src/core/useCases/getValidActionTargets.ts","../src/core/useCases/placeDomino.ts","../src/core/useCases/startGame.ts","../src/core/useCases/useDragon.ts","../src/config.ts","../src/core/domain/entities/validateGameState.ts","../src/core/useCases/botExtensions.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 { AgeOfGiantsState } from \"./ageOfGiants.js\";\nimport type { Domino, RevealsDomino } from \"./domino.js\";\nimport type { Lord } from \"./lord.js\";\nimport type { GameMode } from \"./mode.js\";\nimport type { OriginsState } from \"./origins.js\";\nimport type { Player, PlayerActions } from \"./player.js\";\nimport type { QueenDominoState } from \"./queendomino.js\";\nimport type { SelectedRules } from \"./rule.js\";\nimport type { ScoreBreakdown } from \"./score.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 /** Queendomino-specific state (only present in QueenDomino mode) */\n queendomino?: QueenDominoState;\n /** Origins-specific state (only present in KingdominoOrigins modes) */\n origins?: OriginsState;\n /** Age of Giants-specific state (only present in AgeOfGiants modes) */\n ageOfGiants?: AgeOfGiantsState;\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 * Territory-by-territory and bonus-by-bonus score, computed by the same\n * function as `calculatePlayerScore` (`breakdown.total === details.points`).\n * Always set by `getResults`.\n */\n breakdown?: ScoreBreakdown;\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\n/**\n * Type guard to check if final results have been computed for the game\n * (i.e. the state returned by `getResults`).\n * @param game - The game state to check\n * @returns True if the game carries a `result` array\n */\nexport const isGameWithResults = (\n game: Game | GameWithResults,\n): game is GameWithResults => {\n return \"result\" in game && Array.isArray(game.result);\n};\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 placeKnight: wrapMethod(\"placeKnight\", engine.placeKnight, logger, level),\n constructBuilding: wrapMethod(\n \"constructBuilding\",\n engine.constructBuilding,\n logger,\n level,\n ),\n useDragon: wrapMethod(\"useDragon\", engine.useDragon, logger, level),\n skipOptionalAction: wrapMethod(\n \"skipOptionalAction\",\n engine.skipOptionalAction,\n logger,\n level,\n ),\n placeFireToken: wrapMethod(\n \"placeFireToken\",\n engine.placeFireToken,\n logger,\n level,\n ),\n recruitCaveman: wrapMethod(\n \"recruitCaveman\",\n engine.recruitCaveman,\n logger,\n level,\n ),\n placeGiant: wrapMethod(\"placeGiant\", engine.placeGiant, logger, level),\n sendGiant: wrapMethod(\"sendGiant\", engine.sendGiant, logger, level),\n getValidFireTokenPositions: wrapMethod(\n \"getValidFireTokenPositions\",\n engine.getValidFireTokenPositions,\n logger,\n level,\n ),\n getValidKnightPositions: wrapMethod(\n \"getValidKnightPositions\",\n engine.getValidKnightPositions,\n logger,\n level,\n ),\n getValidBuildingPositions: wrapMethod(\n \"getValidBuildingPositions\",\n engine.getValidBuildingPositions,\n logger,\n level,\n ),\n getAffordableBuildings: wrapMethod(\n \"getAffordableBuildings\",\n engine.getAffordableBuildings,\n logger,\n level,\n ),\n getValidCavemanPlacements: wrapMethod(\n \"getValidCavemanPlacements\",\n engine.getValidCavemanPlacements,\n logger,\n level,\n ),\n getValidGiantPositions: wrapMethod(\n \"getValidGiantPositions\",\n engine.getValidGiantPositions,\n logger,\n level,\n ),\n getValidGiantTargets: wrapMethod(\n \"getValidGiantTargets\",\n engine.getValidGiantTargets,\n logger,\n level,\n ),\n canSkipOptionalAction: wrapMethod(\n \"canSkipOptionalAction\",\n engine.canSkipOptionalAction,\n logger,\n level,\n ),\n calculatePlayerScore: wrapMethod(\n \"calculatePlayerScore\",\n engine.calculatePlayerScore,\n logger,\n level,\n ),\n };\n};\n","import { isGameWithNextStep } from \"@core/domain/types/game.js\";\nimport type {\n GameState,\n GameWithNextAction,\n GameWithNextStep,\n} from \"@core/domain/types/index.js\";\nimport type { PlayerActions } from \"@core/domain/types/player.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 once when the game reaches the result phase, whatever the action that ended it */\n onGameEnd?: (event: { game: GameState }) => void;\n /** Called after a lord places a knight on their kingdom (QueenDomino) */\n onKnightPlaced?: (event: { game: GameState; lordId: string }) => void;\n /** Called after a lord constructs a building (QueenDomino) */\n onBuildingConstructed?: (event: {\n game: GameState;\n lordId: string;\n buildingId: number;\n }) => void;\n /** Called after a lord uses the dragon to destroy a building (QueenDomino) */\n onDragonUsed?: (event: {\n game: GameState;\n lordId: string;\n buildingId: number;\n }) => void;\n /** Called after a lord places a fire token on their kingdom (Origins) */\n onFireTokenPlaced?: (event: { game: GameState; lordId: string }) => void;\n /** Called after a lord recruits a caveman from the cave board (Origins Tribe) */\n onCavemanRecruited?: (event: {\n game: GameState;\n lordId: string;\n cavemanId: number;\n }) => void;\n /** Called after a lord places a giant on a crown in their kingdom */\n onGiantPlaced?: (event: { game: GameState; lordId: string }) => void;\n /** Called after a lord sends a giant to an opponent's kingdom */\n onGiantSent?: (event: {\n game: GameState;\n lordId: string;\n targetPlayerId: string;\n }) => void;\n /** Called after extra rules are added to the game (setup) */\n onExtraRulesAdded?: (event: {\n game: GameWithNextStep;\n extraRules: string[];\n }) => void;\n /** Called after a lord skips an optional action (QueenDomino, Origins, Age of Giants) */\n onOptionalActionSkipped?: (event: {\n game: GameState;\n lordId: string;\n /** The optional action that was skipped (e.g. `\"placeKnight\"`, `\"sendGiant\"`) */\n skippedAction: PlayerActions;\n }) => 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 are detected centrally, by comparing the game state before\n * and after every gameplay method (whatever the method that caused it):\n * - `onTurnEnd` + `onTurnStart`: emitted when the turn number changes\n * - `onGameEnd`: emitted exactly once, when the game transitions to the\n * \"result\" step (placeDomino, discardDomino, skipOptionalAction,\n * placeFireToken, recruitCaveman, useDragon, placeGiant, sendGiant…)\n *\n * The action-specific event is always emitted before the derived ones.\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 /**\n * Emits the derived events for a gameplay transition `before → after`.\n */\n const emitDerived = (before: GameState, after: GameState): void => {\n if (after.turn !== before.turn) {\n callbacks.onTurnEnd?.({ game: after, turn: before.turn });\n callbacks.onTurnStart?.({ game: after, turn: after.turn });\n }\n if (!isGameEnded(before) && isGameEnded(after)) {\n callbacks.onGameEnd?.({ game: after });\n }\n };\n\n /**\n * Wraps a gameplay method: runs it, emits its specific event, then the\n * derived turn / game-end events.\n */\n const gameplay =\n <C extends { game: GameState }, R extends GameState>(\n run: (cmd: C) => R,\n emit: (game: R, cmd: C) => void,\n ) =>\n (cmd: C): R => {\n const game = run(cmd);\n emit(game, cmd);\n emitDerived(cmd.game, game);\n return game;\n };\n\n return {\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 getValidFireTokenPositions: (cmd) => engine.getValidFireTokenPositions(cmd),\n getValidKnightPositions: (cmd) => engine.getValidKnightPositions(cmd),\n getValidBuildingPositions: (cmd) => engine.getValidBuildingPositions(cmd),\n getAffordableBuildings: (cmd) => engine.getAffordableBuildings(cmd),\n getValidCavemanPlacements: (cmd) => engine.getValidCavemanPlacements(cmd),\n getValidGiantPositions: (cmd) => engine.getValidGiantPositions(cmd),\n getValidGiantTargets: (cmd) => engine.getValidGiantTargets(cmd),\n canSkipOptionalAction: (cmd) => engine.canSkipOptionalAction(cmd),\n calculatePlayerScore: (cmd) => engine.calculatePlayerScore(cmd),\n\n // Setup 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) => {\n const game = engine.addExtraRules(cmd);\n callbacks.onExtraRulesAdded?.({ game, extraRules: cmd.extraRules });\n return game;\n },\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 // Gameplay methods — specific event, then derived turn / game-end events\n chooseDomino: gameplay(\n (cmd) => engine.chooseDomino(cmd),\n (game, cmd) =>\n callbacks.onDominoPicked?.({\n game,\n lordId: cmd.lordId,\n dominoNumber: cmd.dominoPick,\n }),\n ),\n\n placeDomino: gameplay(\n (cmd) => engine.placeDomino(cmd),\n (game, cmd) => callbacks.onDominoPlaced?.({ game, lordId: cmd.lordId }),\n ),\n\n discardDomino: gameplay(\n (cmd) => engine.discardDomino(cmd),\n (game, cmd) =>\n callbacks.onDominoDiscarded?.({ game, lordId: cmd.lordId }),\n ),\n\n // Queendomino methods\n placeKnight: gameplay(\n (cmd) => engine.placeKnight(cmd),\n (game, cmd) => callbacks.onKnightPlaced?.({ game, lordId: cmd.lordId }),\n ),\n\n constructBuilding: gameplay(\n (cmd) => engine.constructBuilding(cmd),\n (game, cmd) =>\n callbacks.onBuildingConstructed?.({\n game,\n lordId: cmd.lordId,\n buildingId: cmd.buildingId,\n }),\n ),\n\n useDragon: gameplay(\n (cmd) => engine.useDragon(cmd),\n (game, cmd) =>\n callbacks.onDragonUsed?.({\n game,\n lordId: cmd.lordId,\n buildingId: cmd.buildingId,\n }),\n ),\n\n skipOptionalAction: gameplay(\n (cmd) => engine.skipOptionalAction(cmd),\n (game, cmd) =>\n callbacks.onOptionalActionSkipped?.({\n game,\n lordId: cmd.lordId,\n skippedAction: cmd.game.nextAction.nextAction,\n }),\n ),\n\n // Origins methods\n placeFireToken: gameplay(\n (cmd) => engine.placeFireToken(cmd),\n (game, cmd) =>\n callbacks.onFireTokenPlaced?.({ game, lordId: cmd.lordId }),\n ),\n\n recruitCaveman: gameplay(\n (cmd) => engine.recruitCaveman(cmd),\n (game, cmd) =>\n callbacks.onCavemanRecruited?.({\n game,\n lordId: cmd.lordId,\n cavemanId: cmd.cavemanId,\n }),\n ),\n\n // Age of Giants methods\n placeGiant: gameplay(\n (cmd) => engine.placeGiant(cmd),\n (game, cmd) => callbacks.onGiantPlaced?.({ game, lordId: cmd.lordId }),\n ),\n\n sendGiant: gameplay(\n (cmd) => engine.sendGiant(cmd),\n (game, cmd) =>\n callbacks.onGiantSent?.({\n game,\n lordId: cmd.lordId,\n targetPlayerId: cmd.targetPlayerId,\n }),\n ),\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 { \"id\": 1, \"name\": \"The Bakery\", \"cost\": 1, \"immediateBonus\": { \"type\": \"coins\", \"amount\": 2 }, \"crowns\": 0, \"towers\": 0 },\n { \"id\": 2, \"name\": \"The Bakery\", \"cost\": 1, \"immediateBonus\": { \"type\": \"coins\", \"amount\": 2 }, \"crowns\": 0, \"towers\": 0 },\n { \"id\": 3, \"name\": \"The Sawmill\", \"cost\": 2, \"crowns\": 0, \"towers\": 0, \"endGameScoring\": { \"type\": \"perTerrain\", \"terrain\": \"forest\", \"points\": 1 } },\n { \"id\": 4, \"name\": \"The Fishmonger's\", \"cost\": 2, \"immediateBonus\": { \"type\": \"coins\", \"amount\": 1 }, \"crowns\": 0, \"towers\": 0, \"endGameScoring\": { \"type\": \"perTerrain\", \"terrain\": \"sea\", \"points\": 1 } },\n { \"id\": 5, \"name\": \"The Fishmonger's\", \"cost\": 2, \"immediateBonus\": { \"type\": \"coins\", \"amount\": 1 }, \"crowns\": 0, \"towers\": 0, \"endGameScoring\": { \"type\": \"perTerrain\", \"terrain\": \"sea\", \"points\": 1 } },\n { \"id\": 6, \"name\": \"The Weaving Shop\", \"cost\": 3, \"crowns\": 1, \"towers\": 0, \"endGameScoring\": { \"type\": \"perTerrain\", \"terrain\": \"wheat\", \"points\": 1 } },\n { \"id\": 7, \"name\": \"The Magic School\", \"cost\": 4, \"crowns\": 1, \"towers\": 0, \"endGameScoring\": { \"type\": \"perCrown\", \"points\": 1 } },\n { \"id\": 8, \"name\": \"The Fountain\", \"cost\": 3, \"crowns\": 0, \"towers\": 1, \"endGameScoring\": { \"type\": \"perTower\", \"points\": 2 } },\n { \"id\": 9, \"name\": \"The Church\", \"cost\": 4, \"crowns\": 1, \"towers\": 0, \"endGameScoring\": { \"type\": \"perBuilding\", \"points\": 2 } },\n { \"id\": 10, \"name\": \"The Bath\", \"cost\": 2, \"immediateBonus\": { \"type\": \"coins\", \"amount\": 1 }, \"crowns\": 0, \"towers\": 0, \"endGameScoring\": { \"type\": \"flat\", \"points\": 4 } },\n { \"id\": 11, \"name\": \"The Guard Tower\", \"cost\": 1, \"crowns\": 0, \"towers\": 1, \"endGameScoring\": { \"type\": \"flat\", \"points\": 2 } },\n { \"id\": 12, \"name\": \"The Guard Tower\", \"cost\": 1, \"crowns\": 0, \"towers\": 1, \"endGameScoring\": { \"type\": \"flat\", \"points\": 2 } },\n { \"id\": 13, \"name\": \"The Big Tower\", \"cost\": 3, \"crowns\": 0, \"towers\": 2, \"endGameScoring\": { \"type\": \"flat\", \"points\": 4 } },\n { \"id\": 14, \"name\": \"The Guardhouse\", \"cost\": 2, \"crowns\": 0, \"towers\": 1, \"endGameScoring\": { \"type\": \"perBuilding\", \"points\": 1 } },\n { \"id\": 15, \"name\": \"The Fortified Castle\", \"cost\": 5, \"crowns\": 2, \"towers\": 1, \"endGameScoring\": { \"type\": \"flat\", \"points\": 6 } },\n { \"id\": 16, \"name\": \"The Travelling Castle\", \"cost\": 3, \"crowns\": 1, \"towers\": 1, \"endGameScoring\": { \"type\": \"perTower\", \"points\": 1 } },\n { \"id\": 17, \"name\": \"The Travelling Group\", \"cost\": 2, \"immediateBonus\": { \"type\": \"coins\", \"amount\": 1 }, \"crowns\": 0, \"towers\": 0, \"endGameScoring\": { \"type\": \"perBuilding\", \"points\": 1 } },\n { \"id\": 18, \"name\": \"The Harbour\", \"cost\": 3, \"crowns\": 0, \"towers\": 0, \"endGameScoring\": { \"type\": \"perTerrain\", \"terrain\": \"sea\", \"points\": 2 } }\n]\n","import type {\n BuildingTile,\n EndGameScoring,\n EndGameScoringType,\n ImmediateBonus,\n ImmediateBonusType,\n} from \"@core/domain/types/building.js\";\nimport type { BuildingsRepository } from \"@core/portServerside/buildingsRepository.js\";\nimport buildingsJson from \"../datasources/buildings.json\" with { type: \"json\" };\n\nconst jsonBuildings = (): BuildingsRepository => {\n const buildings: BuildingTile[] = buildingsJson.map((b) => {\n const tile: BuildingTile = {\n id: b.id,\n name: b.name,\n cost: b.cost,\n crowns: b.crowns,\n towers: b.towers,\n };\n\n if (b.immediateBonus) {\n tile.immediateBonus = {\n type: b.immediateBonus.type as ImmediateBonusType,\n amount: b.immediateBonus.amount,\n } satisfies ImmediateBonus;\n }\n\n if (\"endGameScoring\" in b && b.endGameScoring) {\n tile.endGameScoring = {\n type: b.endGameScoring.type as EndGameScoringType,\n points: b.endGameScoring.points,\n ...(\"terrain\" in b.endGameScoring && {\n terrain: b.endGameScoring.terrain,\n }),\n } satisfies EndGameScoring;\n }\n\n return tile;\n });\n\n return {\n getAll: () => buildings,\n };\n};\n\nexport default jsonBuildings;\n","[\n { \"kind\": \"hunterGatherer\", \"id\": 1, \"hunterType\": \"mammothHunter\", \"pointsPerMatch\": 3 },\n { \"kind\": \"hunterGatherer\", \"id\": 2, \"hunterType\": \"mammothHunter\", \"pointsPerMatch\": 3 },\n { \"kind\": \"hunterGatherer\", \"id\": 3, \"hunterType\": \"fisherman\", \"pointsPerMatch\": 3 },\n { \"kind\": \"hunterGatherer\", \"id\": 4, \"hunterType\": \"fisherman\", \"pointsPerMatch\": 3 },\n { \"kind\": \"hunterGatherer\", \"id\": 5, \"hunterType\": \"mushroomPicker\", \"pointsPerMatch\": 3 },\n { \"kind\": \"hunterGatherer\", \"id\": 6, \"hunterType\": \"mushroomPicker\", \"pointsPerMatch\": 3 },\n { \"kind\": \"hunterGatherer\", \"id\": 7, \"hunterType\": \"flintCollector\", \"pointsPerMatch\": 3 },\n { \"kind\": \"hunterGatherer\", \"id\": 8, \"hunterType\": \"flintCollector\", \"pointsPerMatch\": 3 },\n { \"kind\": \"hunterGatherer\", \"id\": 9, \"hunterType\": \"trapper\", \"pointsPerMatch\": 2 },\n { \"kind\": \"hunterGatherer\", \"id\": 10, \"hunterType\": \"trapper\", \"pointsPerMatch\": 2 },\n { \"kind\": \"hunterGatherer\", \"id\": 11, \"hunterType\": \"gatherer\", \"pointsPerMatch\": 1 },\n { \"kind\": \"hunterGatherer\", \"id\": 12, \"hunterType\": \"gatherer\", \"pointsPerMatch\": 1 },\n { \"kind\": \"hunterGatherer\", \"id\": 13, \"hunterType\": \"fireLady\", \"pointsPerMatch\": 1 },\n { \"kind\": \"hunterGatherer\", \"id\": 14, \"hunterType\": \"fireLady\", \"pointsPerMatch\": 1 },\n { \"kind\": \"warrior\", \"id\": 15, \"warriorType\": \"small\", \"power\": 1 },\n { \"kind\": \"warrior\", \"id\": 16, \"warriorType\": \"small\", \"power\": 1 },\n { \"kind\": \"warrior\", \"id\": 17, \"warriorType\": \"small\", \"power\": 1 },\n { \"kind\": \"warrior\", \"id\": 18, \"warriorType\": \"small\", \"power\": 1 },\n { \"kind\": \"warrior\", \"id\": 19, \"warriorType\": \"amazon\", \"power\": 2 },\n { \"kind\": \"warrior\", \"id\": 20, \"warriorType\": \"amazon\", \"power\": 2 },\n { \"kind\": \"warrior\", \"id\": 21, \"warriorType\": \"amazon\", \"power\": 2 },\n { \"kind\": \"warrior\", \"id\": 22, \"warriorType\": \"oafish\", \"power\": 3 }\n]\n","import type {\n CavemanTile,\n HunterGathererKind,\n HunterGathererTile,\n WarriorTile,\n WarriorType,\n} from \"@core/domain/types/origins.js\";\nimport type { CavemenRepository } from \"@core/portServerside/cavemenRepository.js\";\nimport cavemenJson from \"../datasources/cavemen.json\" with { type: \"json\" };\n\nconst mapCaveman = (raw: {\n kind: string;\n id: number;\n hunterType?: string;\n pointsPerMatch?: number;\n warriorType?: string;\n power?: number;\n}): CavemanTile => {\n if (raw.kind === \"hunterGatherer\") {\n return {\n kind: \"hunterGatherer\",\n id: raw.id,\n hunterType: raw.hunterType as HunterGathererKind,\n pointsPerMatch: raw.pointsPerMatch!,\n } satisfies HunterGathererTile;\n }\n return {\n kind: \"warrior\",\n id: raw.id,\n warriorType: raw.warriorType as WarriorType,\n power: raw.power!,\n } satisfies WarriorTile;\n};\n\nconst jsonCavemen = (): CavemenRepository => {\n const cavemen: CavemanTile[] = cavemenJson.map(mapCaveman);\n\n return {\n getAll: () => [...cavemen],\n };\n};\n\nexport default jsonCavemen;\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 \"QueenDomino\": [\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\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 5\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 6\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 7\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 8\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"number\": 9\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"number\": 10\n },\n {\n \"left\": {\n \"type\": \"mine\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 0\n },\n \"number\": 11\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 12\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 13\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 14\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 15\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 16\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 17\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"number\": 18\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\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 \"hasConstructionSquare\": true\n },\n \"number\": 21\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 22\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 23\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 24\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 25\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 26\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 27\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 28\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 0\n },\n \"number\": 29\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 30\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 1\n },\n \"number\": 31\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"number\": 32\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 1\n },\n \"number\": 33\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 1\n },\n \"number\": 34\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 1\n },\n \"number\": 35\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 2,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 36\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 37\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 38\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 39\n },\n {\n \"left\": {\n \"type\": \"mine\",\n \"crowns\": 2,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 40\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 2\n },\n \"number\": 41\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"number\": 42\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 1\n },\n \"number\": 43\n },\n {\n \"left\": {\n \"type\": \"mine\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 1\n },\n \"number\": 44\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 2\n },\n \"number\": 45\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 2,\n \"hasConstructionSquare\": true\n },\n \"number\": 46\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 3\n },\n \"number\": 47\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 3\n },\n \"number\": 48\n }\n ],\n \"KingdominoOrigins\": [\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"number\": 1\n },\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"lake\",\n \"crowns\": 0\n },\n \"number\": 2\n },\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"number\": 3\n },\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"quarry\",\n \"crowns\": 0\n },\n \"number\": 4\n },\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"desert\",\n \"crowns\": 0\n },\n \"number\": 5\n },\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"number\": 6\n },\n {\n \"left\": {\n \"type\": \"lake\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"lake\",\n \"crowns\": 0\n },\n \"number\": 7\n },\n {\n \"left\": {\n \"type\": \"lake\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"number\": 8\n },\n {\n \"left\": {\n \"type\": \"lake\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"quarry\",\n \"crowns\": 0\n },\n \"number\": 9\n },\n {\n \"left\": {\n \"type\": \"lake\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"desert\",\n \"crowns\": 0\n },\n \"number\": 10\n },\n {\n \"left\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"number\": 11\n },\n {\n \"left\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"quarry\",\n \"crowns\": 0\n },\n \"number\": 12\n },\n {\n \"left\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"desert\",\n \"crowns\": 0\n },\n \"number\": 13\n },\n {\n \"left\": {\n \"type\": \"quarry\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"quarry\",\n \"crowns\": 0\n },\n \"number\": 14\n },\n {\n \"left\": {\n \"type\": \"quarry\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"desert\",\n \"crowns\": 0\n },\n \"number\": 15\n },\n {\n \"left\": {\n \"type\": \"desert\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"desert\",\n \"crowns\": 0\n },\n \"number\": 16\n },\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"number\": 17\n },\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"lake\",\n \"crowns\": 0\n },\n \"number\": 18\n },\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"number\": 19\n },\n {\n \"left\": {\n \"type\": \"volcano\",\n \"crowns\": 0,\n \"volcanoCraters\": 1\n },\n \"right\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"number\": 20\n },\n {\n \"left\": {\n \"type\": \"lake\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"number\": 21\n },\n {\n \"left\": {\n \"type\": \"lake\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"desert\",\n \"crowns\": 0\n },\n \"number\": 22\n },\n {\n \"left\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"quarry\",\n \"crowns\": 0\n },\n \"number\": 23\n },\n {\n \"left\": {\n \"type\": \"volcano\",\n \"crowns\": 0,\n \"volcanoCraters\": 1\n },\n \"right\": {\n \"type\": \"lake\",\n \"crowns\": 0\n },\n \"number\": 24\n },\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"number\": 25\n },\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"lake\",\n \"crowns\": 1\n },\n \"number\": 26\n },\n {\n \"left\": {\n \"type\": \"volcano\",\n \"crowns\": 0,\n \"volcanoCraters\": 1\n },\n \"right\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"number\": 27\n },\n {\n \"left\": {\n \"type\": \"lake\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"quarry\",\n \"crowns\": 0\n },\n \"number\": 28\n },\n {\n \"left\": {\n \"type\": \"jungle\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"desert\",\n \"crowns\": 0\n },\n \"number\": 29\n },\n {\n \"left\": {\n \"type\": \"volcano\",\n \"crowns\": 0,\n \"volcanoCraters\": 1\n },\n \"right\": {\n \"type\": \"quarry\",\n \"crowns\": 0\n },\n \"number\": 30\n },\n {\n \"left\": {\n \"type\": \"desert\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"number\": 31\n },\n {\n \"left\": {\n \"type\": \"quarry\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"lake\",\n \"crowns\": 0\n },\n \"number\": 32\n },\n {\n \"left\": {\n \"type\": \"volcano\",\n \"crowns\": 0,\n \"volcanoCraters\": 2\n },\n \"right\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"number\": 33\n },\n {\n \"left\": {\n \"type\": \"jungle\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"number\": 34\n },\n {\n \"left\": {\n \"type\": \"lake\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"desert\",\n \"crowns\": 0\n },\n \"number\": 35\n },\n {\n \"left\": {\n \"type\": \"volcano\",\n \"crowns\": 0,\n \"volcanoCraters\": 2\n },\n \"right\": {\n \"type\": \"jungle\",\n \"crowns\": 0\n },\n \"number\": 36\n },\n {\n \"left\": {\n \"type\": \"grassland\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"quarry\",\n \"crowns\": 1\n },\n \"number\": 37\n },\n {\n \"left\": {\n \"type\": \"volcano\",\n \"crowns\": 0,\n \"volcanoCraters\": 1\n },\n \"right\": {\n \"type\": \"desert\",\n \"crowns\": 1\n },\n \"number\": 38\n },\n {\n \"left\": {\n \"type\": \"lake\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"jungle\",\n \"crowns\": 1\n },\n \"number\": 39\n },\n {\n \"left\": {\n \"type\": \"volcano\",\n \"crowns\": 0,\n \"volcanoCraters\": 2\n },\n \"right\": {\n \"type\": \"quarry\",\n \"crowns\": 1\n },\n \"number\": 40\n },\n {\n \"left\": {\n \"type\": \"desert\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"grassland\",\n \"crowns\": 1\n },\n \"number\": 41\n },\n {\n \"left\": {\n \"type\": \"quarry\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"number\": 42\n },\n {\n \"left\": {\n \"type\": \"volcano\",\n \"crowns\": 0,\n \"volcanoCraters\": 2\n },\n \"right\": {\n \"type\": \"lake\",\n \"crowns\": 1\n },\n \"number\": 43\n },\n {\n \"left\": {\n \"type\": \"jungle\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"desert\",\n \"crowns\": 0\n },\n \"number\": 44\n },\n {\n \"left\": {\n \"type\": \"lake\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"grassland\",\n \"crowns\": 0\n },\n \"number\": 45\n },\n {\n \"left\": {\n \"type\": \"desert\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"quarry\",\n \"crowns\": 1\n },\n \"number\": 46\n },\n {\n \"left\": {\n \"type\": \"volcano\",\n \"crowns\": 0,\n \"volcanoCraters\": 3\n },\n \"right\": {\n \"type\": \"grassland\",\n \"crowns\": 2\n },\n \"number\": 47\n },\n {\n \"left\": {\n \"type\": \"jungle\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"quarry\",\n \"crowns\": 2\n },\n \"number\": 48\n }\n ],\n \"AgeOfGiants\": [\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 \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.01,\n \"letter\": \"A\"\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.02,\n \"letter\": \"B\"\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.03,\n \"letter\": \"C\"\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.04,\n \"letter\": \"D\"\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.05,\n \"letter\": \"E\"\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.06,\n \"letter\": \"F\"\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 49\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 50\n },\n {\n \"left\": {\n \"type\": \"mine\",\n \"crowns\": 1,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 51\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 52\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 1,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 53\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 2,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 54\n }\n ],\n \"AgeOfGiants-QueenDomino\": [\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\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 5\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 6\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 7\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 8\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"number\": 9\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"number\": 10\n },\n {\n \"left\": {\n \"type\": \"mine\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 0\n },\n \"number\": 11\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 12\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 13\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 14\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 15\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 16\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 17\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"number\": 18\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\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 \"hasConstructionSquare\": true\n },\n \"number\": 21\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 22\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 23\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 24\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 25\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 26\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 27\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 28\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 0\n },\n \"number\": 29\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 30\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 1\n },\n \"number\": 31\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"number\": 32\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 1\n },\n \"number\": 33\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 1\n },\n \"number\": 34\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 1\n },\n \"number\": 35\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 2,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 36\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0,\n \"hasConstructionSquare\": true\n },\n \"number\": 37\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 38\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 39\n },\n {\n \"left\": {\n \"type\": \"mine\",\n \"crowns\": 2,\n \"hasConstructionSquare\": true\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 40\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 2\n },\n \"number\": 41\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 1,\n \"hasConstructionSquare\": true\n },\n \"number\": 42\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 1\n },\n \"number\": 43\n },\n {\n \"left\": {\n \"type\": \"mine\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 1\n },\n \"number\": 44\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 2\n },\n \"number\": 45\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 2,\n \"hasConstructionSquare\": true\n },\n \"number\": 46\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 3\n },\n \"number\": 47\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 2\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 3\n },\n \"number\": 48\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.01,\n \"letter\": \"A\"\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.02,\n \"letter\": \"B\"\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"swamp\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.03,\n \"letter\": \"C\"\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"mine\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.04,\n \"letter\": \"D\"\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.05,\n \"letter\": \"E\"\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 0\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 1,\n \"hasGiant\": true\n },\n \"number\": 0.06,\n \"letter\": \"F\"\n },\n {\n \"left\": {\n \"type\": \"forest\",\n \"crowns\": 1,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 49\n },\n {\n \"left\": {\n \"type\": \"wheat\",\n \"crowns\": 1,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"sea\",\n \"crowns\": 0\n },\n \"number\": 50\n },\n {\n \"left\": {\n \"type\": \"mine\",\n \"crowns\": 1,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 51\n },\n {\n \"left\": {\n \"type\": \"sea\",\n \"crowns\": 1,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"forest\",\n \"crowns\": 0\n },\n \"number\": 52\n },\n {\n \"left\": {\n \"type\": \"swamp\",\n \"crowns\": 1,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"plain\",\n \"crowns\": 0\n },\n \"number\": 53\n },\n {\n \"left\": {\n \"type\": \"plain\",\n \"crowns\": 2,\n \"hasFootprint\": true\n },\n \"right\": {\n \"type\": \"wheat\",\n \"crowns\": 0\n },\n \"number\": 54\n }\n ]\n}","import type { Domino, Ground, Tile } 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 mapTile = (raw: {\n type: string;\n crowns: number;\n hasConstructionSquare?: boolean;\n volcanoCraters?: number;\n hasGiant?: boolean;\n hasFootprint?: boolean;\n}): Tile => {\n const tile: Tile = {\n type: raw.type as Ground,\n crowns: raw.crowns,\n };\n if (raw.hasConstructionSquare) {\n tile.hasConstructionSquare = true;\n }\n if (raw.volcanoCraters) {\n tile.volcanoCraters = raw.volcanoCraters;\n }\n if (raw.hasGiant) {\n tile.hasGiant = true;\n }\n if (raw.hasFootprint) {\n tile.hasFootprint = true;\n }\n return tile;\n};\n\n/** Maps Origins sub-mode names to the shared domino data key */\nconst ORIGINS_MODE_PREFIX = \"KingdominoOrigins\";\nconst resolveDataKey = (modeName: string): string => {\n if (modeName.startsWith(ORIGINS_MODE_PREFIX)) {\n return ORIGINS_MODE_PREFIX;\n }\n return modeName;\n};\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 const d: Domino = {\n left: mapTile(domino.left),\n right: mapTile(domino.right),\n number: domino.number,\n };\n if (\"letter\" in domino && typeof domino.letter === \"string\") {\n d.letter = domino.letter;\n }\n currentDominoes.push(d);\n });\n\n dominoes[key] = currentDominoes;\n }\n\n return {\n getForMode: (mode: GameMode) => {\n const key = resolveDataKey(mode.name);\n return dominoes[key] || [];\n },\n };\n};\n\nexport default jsonDominoes;\n","[\n {\n \"name\": \"Classic\",\n \"description\": \"Original KingDomino rules\"\n },\n {\n \"name\": \"QueenDomino\",\n \"description\": \"Queendomino expansion with buildings, knights, coins, the Queen and the Dragon\"\n },\n {\n \"name\": \"KingdominoOrigins-Discovery\",\n \"description\": \"Kingdomino Origins - Discovery mode with volcanoes, fire tokens and fire-based scoring\"\n },\n {\n \"name\": \"KingdominoOrigins-Totem\",\n \"description\": \"Kingdomino Origins - Totem mode with resources, totem majority and fire mechanics\"\n },\n {\n \"name\": \"KingdominoOrigins-Tribe\",\n \"description\": \"Kingdomino Origins - Tribe mode with resources, cave board, cavemen recruitment and fire mechanics\"\n },\n {\n \"name\": \"AgeOfGiants\",\n \"description\": \"Age of Giants extension with giants, quest tiles, 5-player support and 12 new dominos on top of Classic Kingdomino\"\n },\n {\n \"name\": \"AgeOfGiants-QueenDomino\",\n \"description\": \"Age of Giants extension combined with Queendomino, adding giants and quest tiles to the Queendomino experience\"\n }\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 {\n \"id\": 1,\n \"type\": \"localTrade\",\n \"name\": \"Local Trade - Wheat\",\n \"description\": \"Each wheat tile adjacent (orthogonal + diagonal) to your castle scores 5 bonus points.\",\n \"points\": 5,\n \"terrain\": \"wheat\"\n },\n {\n \"id\": 2,\n \"type\": \"localTrade\",\n \"name\": \"Local Trade - Forest\",\n \"description\": \"Each forest tile adjacent (orthogonal + diagonal) to your castle scores 5 bonus points.\",\n \"points\": 5,\n \"terrain\": \"forest\"\n },\n {\n \"id\": 3,\n \"type\": \"localTrade\",\n \"name\": \"Local Trade - Sea\",\n \"description\": \"Each sea tile adjacent (orthogonal + diagonal) to your castle scores 5 bonus points.\",\n \"points\": 5,\n \"terrain\": \"sea\"\n },\n {\n \"id\": 4,\n \"type\": \"localTrade\",\n \"name\": \"Local Trade - Plain\",\n \"description\": \"Each plain tile adjacent (orthogonal + diagonal) to your castle scores 5 bonus points.\",\n \"points\": 5,\n \"terrain\": \"plain\"\n },\n {\n \"id\": 5,\n \"type\": \"kingdomBorders\",\n \"name\": \"Kingdom Borders - Wheat\",\n \"description\": \"Each wheat tile in the 4 corners of your kingdom scores 5 bonus points.\",\n \"points\": 5,\n \"terrain\": \"wheat\"\n },\n {\n \"id\": 6,\n \"type\": \"kingdomBorders\",\n \"name\": \"Kingdom Borders - Forest\",\n \"description\": \"Each forest tile in the 4 corners of your kingdom scores 5 bonus points.\",\n \"points\": 5,\n \"terrain\": \"forest\"\n },\n {\n \"id\": 7,\n \"type\": \"kingdomBorders\",\n \"name\": \"Kingdom Borders - Sea\",\n \"description\": \"Each sea tile in the 4 corners of your kingdom scores 5 bonus points.\",\n \"points\": 5,\n \"terrain\": \"sea\"\n },\n {\n \"id\": 8,\n \"type\": \"kingdomBorders\",\n \"name\": \"Kingdom Borders - Plain\",\n \"description\": \"Each plain tile in the 4 corners of your kingdom scores 5 bonus points.\",\n \"points\": 5,\n \"terrain\": \"plain\"\n },\n {\n \"id\": 9,\n \"type\": \"harmony\",\n \"name\": \"Harmony\",\n \"description\": \"Score 5 bonus points if your kingdom is complete (no discarded dominos).\",\n \"points\": 5\n },\n {\n \"id\": 10,\n \"type\": \"middleKingdom\",\n \"name\": \"Middle Kingdom\",\n \"description\": \"Score 10 bonus points if your castle is in the center of your kingdom.\",\n \"points\": 10\n },\n {\n \"id\": 11,\n \"type\": \"lostCorner\",\n \"name\": \"Lost Corner\",\n \"description\": \"Score 20 bonus points if your castle is in one of the 4 corners of your kingdom.\",\n \"points\": 20\n },\n {\n \"id\": 12,\n \"type\": \"megalomania\",\n \"name\": \"Megalomania\",\n \"description\": \"Score 10 bonus points for each alignment of 3 or more tiles with crowns (horizontal, vertical, or diagonal).\",\n \"points\": 10\n },\n {\n \"id\": 13,\n \"type\": \"megalomania\",\n \"name\": \"Megalomania\",\n \"description\": \"Score 10 bonus points for each alignment of 3 or more tiles with crowns (horizontal, vertical, or diagonal).\",\n \"points\": 10\n },\n {\n \"id\": 14,\n \"type\": \"austereKing\",\n \"name\": \"Austere King\",\n \"description\": \"Score 10 bonus points for each property of 5+ wheat, forest, sea, or plain tiles with zero crowns.\",\n \"points\": 10\n },\n {\n \"id\": 15,\n \"type\": \"austereKing\",\n \"name\": \"Austere King\",\n \"description\": \"Score 10 bonus points for each property of 5+ wheat, forest, sea, or plain tiles with zero crowns.\",\n \"points\": 10\n },\n {\n \"id\": 16,\n \"type\": \"lostCorner\",\n \"name\": \"Lost Corner\",\n \"description\": \"Score 20 bonus points if your castle is in one of the 4 corners of your kingdom.\",\n \"points\": 20\n },\n {\n \"id\": 17,\n \"type\": \"harmony\",\n \"name\": \"Harmony\",\n \"description\": \"Score 5 bonus points if your kingdom is complete (no discarded dominos).\",\n \"points\": 5\n }\n]\n","import type { QuestTile, QuestType } from \"@core/domain/types/ageOfGiants.js\";\nimport type { Ground } from \"@core/domain/types/domino.js\";\nimport type { QuestTilesRepository } from \"@core/portServerside/questTilesRepository.js\";\nimport questTilesJson from \"../datasources/questTiles.json\" with {\n type: \"json\",\n};\n\nconst mapQuestTile = (raw: {\n id: number;\n type: string;\n name: string;\n description: string;\n points: number;\n terrain?: string;\n}): QuestTile => {\n const tile: QuestTile = {\n id: raw.id,\n type: raw.type as QuestType,\n name: raw.name,\n description: raw.description,\n points: raw.points,\n };\n if (raw.terrain) {\n tile.terrain = raw.terrain as Ground;\n }\n return tile;\n};\n\nconst jsonQuestTiles = (): QuestTilesRepository => {\n const questTiles: QuestTile[] = questTilesJson.map(mapQuestTile);\n\n return {\n getAll: () => [...questTiles],\n };\n};\n\nexport default jsonQuestTiles;\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 \"aog\": [\n {\n \"playersLimit\": 2,\n \"lordsPerPlayer\": 2,\n \"maxDominoes\": 30,\n \"dominoesPerTurn\": 5,\n \"maxTurns\": 6,\n \"maxKingdomSize\": 5,\n \"dominoesDiscardedPerTurn\": 1\n },\n {\n \"playersLimit\": 3,\n \"lordsPerPlayer\": 1,\n \"maxDominoes\": 60,\n \"dominoesPerTurn\": 5,\n \"maxTurns\": 12,\n \"maxKingdomSize\": 5,\n \"dominoesDiscardedPerTurn\": 2\n },\n {\n \"playersLimit\": 4,\n \"lordsPerPlayer\": 1,\n \"maxDominoes\": 60,\n \"dominoesPerTurn\": 5,\n \"maxTurns\": 12,\n \"maxKingdomSize\": 5,\n \"dominoesDiscardedPerTurn\": 1\n },\n {\n \"playersLimit\": 5,\n \"lordsPerPlayer\": 1,\n \"maxDominoes\": 60,\n \"dominoesPerTurn\": 5,\n \"maxTurns\": 12,\n \"maxKingdomSize\": 5,\n \"dominoesDiscardedPerTurn\": 0\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\": [\n { \"name\": \"Classic\", \"description\": \"King Domino classic mode\" },\n { \"name\": \"QueenDomino\", \"description\": \"Queendomino expansion with buildings, knights, coins, the Queen and the Dragon\" }\n ]\n },\n {\n \"name\": \"Harmony\",\n \"description\": \"Gain 5 additional points if your kingdom is complete (no discarded dominoes).\",\n \"mode\": [\n { \"name\": \"Classic\", \"description\": \"King Domino classic mode\" },\n { \"name\": \"QueenDomino\", \"description\": \"Queendomino expansion with buildings, knights, coins, the Queen and the Dragon\" }\n ]\n },\n {\n \"name\": \"The Mighty Duel\",\n \"description\": \"Use all 48 dominoes and build a 7x7 kingdom. For 2 players only.\",\n \"mode\": [\n { \"name\": \"Classic\", \"description\": \"King Domino classic mode\" },\n { \"name\": \"QueenDomino\", \"description\": \"Queendomino expansion with buildings, knights, coins, the Queen and the Dragon\" }\n ],\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\": [\n { \"name\": \"Classic\", \"description\": \"King Domino classic mode\" },\n { \"name\": \"QueenDomino\", \"description\": \"Queendomino expansion with buildings, knights, coins, the Queen and the Dragon\" }\n ]\n },\n {\n \"name\": \"Empire of Fire\",\n \"description\": \"Gain 10 additional points if your hut is in the center of your territory.\",\n \"mode\": [\n { \"name\": \"KingdominoOrigins-Discovery\", \"description\": \"Kingdomino Origins - Discovery mode\" },\n { \"name\": \"KingdominoOrigins-Totem\", \"description\": \"Kingdomino Origins - Totem mode\" },\n { \"name\": \"KingdominoOrigins-Tribe\", \"description\": \"Kingdomino Origins - Tribe mode\" }\n ]\n },\n {\n \"name\": \"Homo Habilis\",\n \"description\": \"Gain 5 additional points if your 5x5 territory is complete (no discarded dominoes).\",\n \"mode\": [\n { \"name\": \"KingdominoOrigins-Discovery\", \"description\": \"Kingdomino Origins - Discovery mode\" },\n { \"name\": \"KingdominoOrigins-Totem\", \"description\": \"Kingdomino Origins - Totem mode\" },\n { \"name\": \"KingdominoOrigins-Tribe\", \"description\": \"Kingdomino Origins - Tribe mode\" }\n ]\n },\n {\n \"name\": \"Neolithic\",\n \"description\": \"Use all 48 dominoes and build a 7x7 territory. For 2 players only.\",\n \"mode\": [\n { \"name\": \"KingdominoOrigins-Discovery\", \"description\": \"Kingdomino Origins - Discovery mode\" },\n { \"name\": \"KingdominoOrigins-Totem\", \"description\": \"Kingdomino Origins - Totem mode\" },\n { \"name\": \"KingdominoOrigins-Tribe\", \"description\": \"Kingdomino Origins - Tribe mode\" }\n ],\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\": [\n { \"name\": \"KingdominoOrigins-Discovery\", \"description\": \"Kingdomino Origins - Discovery mode\" },\n { \"name\": \"KingdominoOrigins-Totem\", \"description\": \"Kingdomino Origins - Totem mode\" },\n { \"name\": \"KingdominoOrigins-Tribe\", \"description\": \"Kingdomino Origins - Tribe mode\" }\n ]\n },\n {\n \"name\": \"Dynasty\",\n \"description\": \"Play 3 games in a row. The player with the highest total points wins.\",\n \"mode\": [\n { \"name\": \"AgeOfGiants\", \"description\": \"Age of Giants extension on Classic Kingdomino\" },\n { \"name\": \"AgeOfGiants-QueenDomino\", \"description\": \"Age of Giants extension on Queendomino\" }\n ]\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 aogRules = rulesJson.aog;\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 if (aogRules) {\n rules.aogBasic = {};\n aogRules.forEach((rule) => {\n rules.aogBasic![rule.playersLimit] = {\n lords: rule.lordsPerPlayer,\n maxDominoes: rule.maxDominoes,\n dominoesPerTurn: rule.dominoesPerTurn,\n maxTurns: rule.maxTurns,\n maxKingdomSize: rule.maxKingdomSize,\n dominoesDiscardedPerTurn: rule.dominoesDiscardedPerTurn,\n };\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 EXTRA_RULE_NOT_AVAILABLE: \"EXTRA_RULE_NOT_AVAILABLE\",\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\n // Queendomino errors\n CANNOT_PLACE_KNIGHT: \"CANNOT_PLACE_KNIGHT\",\n MAX_KNIGHTS_REACHED: \"MAX_KNIGHTS_REACHED\",\n KNIGHT_TERRITORY_OCCUPIED: \"KNIGHT_TERRITORY_OCCUPIED\",\n CANNOT_AFFORD_BUILDING: \"CANNOT_AFFORD_BUILDING\",\n NO_CONSTRUCTION_SQUARE: \"NO_CONSTRUCTION_SQUARE\",\n DRAGON_UNAVAILABLE: \"DRAGON_UNAVAILABLE\",\n QUEEN_HOLDER_CANNOT_USE_DRAGON: \"QUEEN_HOLDER_CANNOT_USE_DRAGON\",\n BUILDING_NOT_FOUND: \"BUILDING_NOT_FOUND\",\n INVALID_OPTIONAL_ACTION: \"INVALID_OPTIONAL_ACTION\",\n\n // Age of Giants errors\n GIANT_POOL_EMPTY: \"GIANT_POOL_EMPTY\",\n GIANT_NOT_FOUND: \"GIANT_NOT_FOUND\",\n INVALID_GIANT_PLACEMENT: \"INVALID_GIANT_PLACEMENT\",\n NOT_AOG_MODE: \"NOT_AOG_MODE\",\n\n // Origins errors\n FIRE_TOKEN_POOL_EMPTY: \"FIRE_TOKEN_POOL_EMPTY\",\n FIRE_TOKEN_INVALID_POSITION: \"FIRE_TOKEN_INVALID_POSITION\",\n NO_PENDING_FIRE_TOKEN: \"NO_PENDING_FIRE_TOKEN\",\n CANNOT_RECRUIT_CAVEMAN: \"CANNOT_RECRUIT_CAVEMAN\",\n INSUFFICIENT_RESOURCES: \"INSUFFICIENT_RESOURCES\",\n INVALID_CAVEMAN_PLACEMENT: \"INVALID_CAVEMAN_PLACEMENT\",\n CAVEMAN_NOT_FOUND: \"CAVEMAN_NOT_FOUND\",\n NOT_TRIBE_MODE: \"NOT_TRIBE_MODE\",\n\n // Player id errors\n INVALID_PLAYER_ID: \"INVALID_PLAYER_ID\",\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\";\nimport type { QuestType } from \"@core/domain/types/ageOfGiants.js\";\nimport type { Ground } from \"@core/domain/types/domino.js\";\nimport type {\n CavemanKind,\n HunterGathererKind,\n ResourceType,\n WarriorType,\n} from \"@core/domain/types/origins.js\";\nimport type { PlayerActions } from \"@core/domain/types/player.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_EXTRA_RULE_NOT_AVAILABLE: \"error.extraRuleNotAvailable\",\n ERROR_UNDO_UNAVAILABLE: \"error.undoUnavailable\",\n ERROR_REDO_UNAVAILABLE: \"error.redoUnavailable\",\n\n // Game mode names\n MODE_CLASSIC: \"mode.classic\",\n MODE_QUEENDOMINO: \"mode.queenDomino\",\n MODE_ORIGINS_DISCOVERY: \"mode.originsDiscovery\",\n MODE_ORIGINS_TOTEM: \"mode.originsTotem\",\n MODE_ORIGINS_TRIBE: \"mode.originsTribe\",\n MODE_AGE_OF_GIANTS: \"mode.ageOfGiants\",\n MODE_AGE_OF_GIANTS_QUEENDOMINO: \"mode.ageOfGiantsQueenDomino\",\n\n // Extra rule names\n RULE_MIDDLE_KINGDOM: \"rule.middleKingdom\",\n RULE_HARMONY: \"rule.harmony\",\n RULE_MIGHTY_DUEL: \"rule.mightyDuel\",\n RULE_DYNASTY: \"rule.dynasty\",\n RULE_EMPIRE_OF_FIRE: \"rule.empireOfFire\",\n RULE_HOMO_HABILIS: \"rule.homoHabilis\",\n RULE_NEOLITHIC: \"rule.neolithic\",\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 // Ground types (Kingdomino Origins)\n GROUND_GRASSLAND: \"ground.grassland\",\n GROUND_LAKE: \"ground.lake\",\n GROUND_JUNGLE: \"ground.jungle\",\n GROUND_QUARRY: \"ground.quarry\",\n GROUND_DESERT: \"ground.desert\",\n GROUND_VOLCANO: \"ground.volcano\",\n\n // Resources (Kingdomino Origins — Totem / Tribe)\n RESOURCE_MAMMOTH: \"resource.mammoth\",\n RESOURCE_FISH: \"resource.fish\",\n RESOURCE_MUSHROOM: \"resource.mushroom\",\n RESOURCE_FLINT: \"resource.flint\",\n\n // Cavemen (Kingdomino Origins — Tribe)\n CAVEMAN_HUNTER_GATHERER: \"caveman.hunterGatherer\",\n CAVEMAN_WARRIOR: \"caveman.warrior\",\n CAVEMAN_MAMMOTH_HUNTER: \"caveman.mammothHunter\",\n CAVEMAN_FISHERMAN: \"caveman.fisherman\",\n CAVEMAN_MUSHROOM_PICKER: \"caveman.mushroomPicker\",\n CAVEMAN_FLINT_COLLECTOR: \"caveman.flintCollector\",\n CAVEMAN_TRAPPER: \"caveman.trapper\",\n CAVEMAN_GATHERER: \"caveman.gatherer\",\n CAVEMAN_FIRE_LADY: \"caveman.fireLady\",\n CAVEMAN_WARRIOR_SMALL: \"caveman.warriorSmall\",\n CAVEMAN_WARRIOR_AMAZON: \"caveman.warriorAmazon\",\n CAVEMAN_WARRIOR_OAFISH: \"caveman.warriorOafish\",\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 ACTION_PLACE_KNIGHT: \"action.placeKnight\",\n ACTION_CONSTRUCT_BUILDING: \"action.constructBuilding\",\n ACTION_USE_DRAGON: \"action.useDragon\",\n ACTION_SKIP_OPTIONAL_ACTION: \"action.skipOptionalAction\",\n ACTION_PLACE_GIANT: \"action.placeGiant\",\n ACTION_SEND_GIANT: \"action.sendGiant\",\n ACTION_PLACE_FIRE_TOKEN: \"action.placeFireToken\",\n ACTION_RECRUIT_CAVEMAN: \"action.recruitCaveman\",\n\n // Queendomino errors\n ERROR_CANNOT_PLACE_KNIGHT: \"error.cannotPlaceKnight\",\n ERROR_MAX_KNIGHTS_REACHED: \"error.maxKnightsReached\",\n ERROR_KNIGHT_TERRITORY_OCCUPIED: \"error.knightTerritoryOccupied\",\n ERROR_CANNOT_AFFORD_BUILDING: \"error.cannotAffordBuilding\",\n ERROR_NO_CONSTRUCTION_SQUARE: \"error.noConstructionSquare\",\n ERROR_DRAGON_UNAVAILABLE: \"error.dragonUnavailable\",\n ERROR_QUEEN_HOLDER_CANNOT_USE_DRAGON: \"error.queenHolderCannotUseDragon\",\n ERROR_BUILDING_NOT_FOUND: \"error.buildingNotFound\",\n ERROR_INVALID_OPTIONAL_ACTION: \"error.invalidOptionalAction\",\n\n // Age of Giants errors\n ERROR_GIANT_POOL_EMPTY: \"error.giantPoolEmpty\",\n ERROR_GIANT_NOT_FOUND: \"error.giantNotFound\",\n ERROR_INVALID_GIANT_PLACEMENT: \"error.invalidGiantPlacement\",\n ERROR_NOT_AOG_MODE: \"error.notAogMode\",\n\n // Origins errors\n ERROR_FIRE_TOKEN_POOL_EMPTY: \"error.fireTokenPoolEmpty\",\n ERROR_FIRE_TOKEN_INVALID_POSITION: \"error.fireTokenInvalidPosition\",\n ERROR_NO_PENDING_FIRE_TOKEN: \"error.noPendingFireToken\",\n ERROR_CANNOT_RECRUIT_CAVEMAN: \"error.cannotRecruitCaveman\",\n ERROR_INSUFFICIENT_RESOURCES: \"error.insufficientResources\",\n ERROR_INVALID_CAVEMAN_PLACEMENT: \"error.invalidCavemanPlacement\",\n ERROR_CAVEMAN_NOT_FOUND: \"error.cavemanNotFound\",\n ERROR_NOT_TRIBE_MODE: \"error.notTribeMode\",\n ERROR_INVALID_PLAYER_ID: \"error.invalidPlayerId\",\n\n // Score breakdown labels (extra rules reuse the RULE_* keys,\n // hunter-gatherers reuse the CAVEMAN_* keys)\n SCORE_QUEEN: \"score.queen\",\n SCORE_BUILDING: \"score.building\",\n SCORE_TOTEM_MAMMOTH: \"score.totemMammoth\",\n SCORE_TOTEM_FISH: \"score.totemFish\",\n SCORE_TOTEM_MUSHROOM: \"score.totemMushroom\",\n SCORE_TOTEM_FLINT: \"score.totemFlint\",\n SCORE_RESOURCES: \"score.resources\",\n SCORE_WARRIORS: \"score.warriors\",\n SCORE_FIRE: \"score.fire\",\n QUEST_LOCAL_TRADE: \"quest.localTrade\",\n QUEST_KINGDOM_BORDERS: \"quest.kingdomBorders\",\n QUEST_HARMONY: \"quest.harmony\",\n QUEST_MIDDLE_KINGDOM: \"quest.middleKingdom\",\n QUEST_LOST_CORNER: \"quest.lostCorner\",\n QUEST_MEGALOMANIA: \"quest.megalomania\",\n QUEST_AUSTERE_KING: \"quest.austereKing\",\n} as const;\n\nexport type TranslationKeyType =\n (typeof TranslationKey)[keyof typeof TranslationKey];\n\n/**\n * Default English translations.\n * Also available as `englishTranslations` / `translations.en`.\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_EXTRA_RULE_NOT_AVAILABLE]:\n \"Extra rule is not available for this game mode or number of players\",\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 [TranslationKey.MODE_QUEENDOMINO]: \"Queendomino\",\n [TranslationKey.MODE_ORIGINS_DISCOVERY]: \"Kingdomino Origins — Discovery\",\n [TranslationKey.MODE_ORIGINS_TOTEM]: \"Kingdomino Origins — Totem\",\n [TranslationKey.MODE_ORIGINS_TRIBE]: \"Kingdomino Origins — Tribe\",\n [TranslationKey.MODE_AGE_OF_GIANTS]: \"Age of Giants\",\n [TranslationKey.MODE_AGE_OF_GIANTS_QUEENDOMINO]:\n \"Age of Giants — Queendomino\",\n\n // Extra rule names\n [TranslationKey.RULE_MIDDLE_KINGDOM]: \"The Middle Kingdom\",\n [TranslationKey.RULE_HARMONY]: \"Harmony\",\n [TranslationKey.RULE_MIGHTY_DUEL]: \"The Mighty Duel\",\n [TranslationKey.RULE_DYNASTY]: \"Dynasty\",\n [TranslationKey.RULE_EMPIRE_OF_FIRE]: \"Empire of Fire\",\n [TranslationKey.RULE_HOMO_HABILIS]: \"Homo Habilis\",\n [TranslationKey.RULE_NEOLITHIC]: \"Neolithic\",\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 [TranslationKey.GROUND_GRASSLAND]: \"Grassland\",\n [TranslationKey.GROUND_LAKE]: \"Lake\",\n [TranslationKey.GROUND_JUNGLE]: \"Jungle\",\n [TranslationKey.GROUND_QUARRY]: \"Quarry\",\n [TranslationKey.GROUND_DESERT]: \"Desert\",\n [TranslationKey.GROUND_VOLCANO]: \"Volcano\",\n\n // Resources\n [TranslationKey.RESOURCE_MAMMOTH]: \"Mammoth\",\n [TranslationKey.RESOURCE_FISH]: \"Fish\",\n [TranslationKey.RESOURCE_MUSHROOM]: \"Mushroom\",\n [TranslationKey.RESOURCE_FLINT]: \"Flint\",\n\n // Cavemen\n [TranslationKey.CAVEMAN_HUNTER_GATHERER]: \"Hunter-gatherer\",\n [TranslationKey.CAVEMAN_WARRIOR]: \"Warrior\",\n [TranslationKey.CAVEMAN_MAMMOTH_HUNTER]: \"Mammoth Hunter\",\n [TranslationKey.CAVEMAN_FISHERMAN]: \"Fisherman\",\n [TranslationKey.CAVEMAN_MUSHROOM_PICKER]: \"Mushroom Picker\",\n [TranslationKey.CAVEMAN_FLINT_COLLECTOR]: \"Flint Collector\",\n [TranslationKey.CAVEMAN_TRAPPER]: \"Trapper\",\n [TranslationKey.CAVEMAN_GATHERER]: \"Gatherer\",\n [TranslationKey.CAVEMAN_FIRE_LADY]: \"Fire Lady\",\n [TranslationKey.CAVEMAN_WARRIOR_SMALL]: \"Small Warrior\",\n [TranslationKey.CAVEMAN_WARRIOR_AMAZON]: \"Amazon\",\n [TranslationKey.CAVEMAN_WARRIOR_OAFISH]: \"Oafish Warrior\",\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 [TranslationKey.ACTION_PLACE_KNIGHT]: \"Place Knight\",\n [TranslationKey.ACTION_CONSTRUCT_BUILDING]: \"Construct Building\",\n [TranslationKey.ACTION_USE_DRAGON]: \"Use the Dragon\",\n [TranslationKey.ACTION_SKIP_OPTIONAL_ACTION]: \"Skip\",\n [TranslationKey.ACTION_PLACE_GIANT]: \"Place Giant\",\n [TranslationKey.ACTION_SEND_GIANT]: \"Send Giant\",\n [TranslationKey.ACTION_PLACE_FIRE_TOKEN]: \"Place Fire Token\",\n [TranslationKey.ACTION_RECRUIT_CAVEMAN]: \"Recruit Caveman\",\n\n // Queendomino errors\n [TranslationKey.ERROR_CANNOT_PLACE_KNIGHT]: \"Cannot place knight here\",\n [TranslationKey.ERROR_MAX_KNIGHTS_REACHED]:\n \"Maximum number of knights reached (3)\",\n [TranslationKey.ERROR_KNIGHT_TERRITORY_OCCUPIED]:\n \"This territory already has a knight\",\n [TranslationKey.ERROR_CANNOT_AFFORD_BUILDING]:\n \"Not enough coins to purchase this building\",\n [TranslationKey.ERROR_NO_CONSTRUCTION_SQUARE]:\n \"No open construction square available\",\n [TranslationKey.ERROR_DRAGON_UNAVAILABLE]:\n \"The Dragon is not available this round\",\n [TranslationKey.ERROR_QUEEN_HOLDER_CANNOT_USE_DRAGON]:\n \"The Queen holder cannot use the Dragon\",\n [TranslationKey.ERROR_BUILDING_NOT_FOUND]:\n \"Building not found on the Builders Board\",\n [TranslationKey.ERROR_INVALID_OPTIONAL_ACTION]:\n \"Invalid optional action for this game state\",\n\n // Age of Giants errors\n [TranslationKey.ERROR_GIANT_POOL_EMPTY]: \"No giants remaining in the pool\",\n [TranslationKey.ERROR_GIANT_NOT_FOUND]: \"Giant not found on the kingdom\",\n [TranslationKey.ERROR_INVALID_GIANT_PLACEMENT]:\n \"Invalid position for giant placement — must be an uncovered crown\",\n [TranslationKey.ERROR_NOT_AOG_MODE]: \"Age of Giants mode is not enabled\",\n\n // Origins errors\n [TranslationKey.ERROR_FIRE_TOKEN_POOL_EMPTY]:\n \"No fire tokens remaining in the pool\",\n [TranslationKey.ERROR_FIRE_TOKEN_INVALID_POSITION]:\n \"Invalid position for fire token placement\",\n [TranslationKey.ERROR_NO_PENDING_FIRE_TOKEN]:\n \"No pending fire token to place\",\n [TranslationKey.ERROR_CANNOT_RECRUIT_CAVEMAN]: \"Cannot recruit a caveman\",\n [TranslationKey.ERROR_INSUFFICIENT_RESOURCES]:\n \"Insufficient resources for this action\",\n [TranslationKey.ERROR_INVALID_CAVEMAN_PLACEMENT]:\n \"Invalid position for caveman placement\",\n [TranslationKey.ERROR_CAVEMAN_NOT_FOUND]: \"Caveman not found\",\n [TranslationKey.ERROR_NOT_TRIBE_MODE]: \"Tribe mode is not enabled\",\n [TranslationKey.ERROR_INVALID_PLAYER_ID]:\n \"Player ids must be non-empty and unique\",\n\n // Score breakdown labels\n [TranslationKey.SCORE_QUEEN]: \"Queen\",\n [TranslationKey.SCORE_BUILDING]: \"Building: {{name}}\",\n [TranslationKey.SCORE_TOTEM_MAMMOTH]: \"Mammoth totem\",\n [TranslationKey.SCORE_TOTEM_FISH]: \"Fish totem\",\n [TranslationKey.SCORE_TOTEM_MUSHROOM]: \"Mushroom totem\",\n [TranslationKey.SCORE_TOTEM_FLINT]: \"Flint totem\",\n [TranslationKey.SCORE_RESOURCES]: \"Resources\",\n [TranslationKey.SCORE_WARRIORS]: \"Warrior groups\",\n [TranslationKey.SCORE_FIRE]: \"Fire tokens\",\n [TranslationKey.QUEST_LOCAL_TRADE]: \"Local Trade\",\n [TranslationKey.QUEST_KINGDOM_BORDERS]: \"Kingdom Borders\",\n [TranslationKey.QUEST_HARMONY]: \"Harmony\",\n [TranslationKey.QUEST_MIDDLE_KINGDOM]: \"Middle Kingdom\",\n [TranslationKey.QUEST_LOST_CORNER]: \"Lost Corner\",\n [TranslationKey.QUEST_MEGALOMANIA]: \"Megalomania\",\n [TranslationKey.QUEST_AUSTERE_KING]: \"Austere King\",\n};\n\n/** English translations (alias of `defaultTranslations`). */\nexport const englishTranslations: Record<TranslationKeyType, string> =\n defaultTranslations;\n\n/**\n * French translations.\n */\nexport const frenchTranslations: Record<TranslationKeyType, string> = {\n // Error messages\n [TranslationKey.ERROR_INVALID_STEP]: \"Étape de jeu invalide\",\n [TranslationKey.ERROR_STEP_EXECUTION_FAILED]:\n \"L'exécution de l'étape a échoué\",\n [TranslationKey.ERROR_ACTION_EXECUTION_FAILED]:\n \"L'exécution de l'action a échoué\",\n [TranslationKey.ERROR_LORD_NOT_FOUND]: \"Seigneur introuvable\",\n [TranslationKey.ERROR_PLAYER_NOT_FOUND]: \"Joueur introuvable\",\n [TranslationKey.ERROR_DOMINO_NOT_FOUND]: \"Domino introuvable\",\n [TranslationKey.ERROR_MODE_NOT_FOUND]: \"Mode de jeu introuvable\",\n [TranslationKey.ERROR_INVALID_PLACEMENT]: \"Placement invalide\",\n [TranslationKey.ERROR_PLACEMENT_NOT_EMPTY]: \"Cette position n'est pas libre\",\n [TranslationKey.ERROR_PLACEMENT_NOT_ADJACENT]:\n \"Le domino n'est adjacent à aucune tuile existante\",\n [TranslationKey.ERROR_PLACEMENT_INVALID_TERRAIN]:\n \"Le type de terrain ne correspond pas\",\n [TranslationKey.ERROR_PLACEMENT_OUT_OF_BOUNDS]: \"Placement hors des limites\",\n [TranslationKey.ERROR_PLACEMENT_EXCEEDS_KINGDOM_SIZE]:\n \"Le placement dépasse la taille du royaume\",\n [TranslationKey.ERROR_NOT_YOUR_TURN]: \"Ce n'est pas votre tour\",\n [TranslationKey.ERROR_CANNOT_PICK]:\n \"Impossible de choisir un domino maintenant\",\n [TranslationKey.ERROR_CANNOT_PLACE]:\n \"Impossible de placer un domino maintenant\",\n [TranslationKey.ERROR_DOMINO_ALREADY_PICKED]: \"Ce domino a déjà été choisi\",\n [TranslationKey.ERROR_INVALID_PLAYER_COUNT]:\n \"Nombre de joueurs invalide (1 à 4 requis)\",\n [TranslationKey.ERROR_INVALID_PLAYER_NAME]:\n \"Le nom du joueur doit contenir au moins 3 caractères\",\n [TranslationKey.ERROR_EXTRA_RULE_NOT_AVAILABLE]:\n \"Cette règle optionnelle n'est pas disponible pour ce mode ou ce nombre de joueurs\",\n [TranslationKey.ERROR_UNDO_UNAVAILABLE]: \"Aucun état à annuler\",\n [TranslationKey.ERROR_REDO_UNAVAILABLE]: \"Aucun état à rétablir\",\n\n // Game mode names\n [TranslationKey.MODE_CLASSIC]: \"Classique\",\n [TranslationKey.MODE_QUEENDOMINO]: \"Queendomino\",\n [TranslationKey.MODE_ORIGINS_DISCOVERY]: \"Kingdomino Origins — Découverte\",\n [TranslationKey.MODE_ORIGINS_TOTEM]: \"Kingdomino Origins — Totem\",\n [TranslationKey.MODE_ORIGINS_TRIBE]: \"Kingdomino Origins — Tribu\",\n [TranslationKey.MODE_AGE_OF_GIANTS]: \"L'Âge des Géants\",\n [TranslationKey.MODE_AGE_OF_GIANTS_QUEENDOMINO]:\n \"L'Âge des Géants — Queendomino\",\n\n // Extra rule names\n [TranslationKey.RULE_MIDDLE_KINGDOM]: \"L'Empire du Milieu\",\n [TranslationKey.RULE_HARMONY]: \"Harmonie\",\n [TranslationKey.RULE_MIGHTY_DUEL]: \"Le Grand Duel\",\n [TranslationKey.RULE_DYNASTY]: \"Dynastie\",\n [TranslationKey.RULE_EMPIRE_OF_FIRE]: \"L'Empire du Feu\",\n [TranslationKey.RULE_HOMO_HABILIS]: \"Homo Habilis\",\n [TranslationKey.RULE_NEOLITHIC]: \"Néolithique\",\n\n // Ground types\n [TranslationKey.GROUND_CASTLE]: \"Château\",\n [TranslationKey.GROUND_WHEAT]: \"Champ de blé\",\n [TranslationKey.GROUND_FOREST]: \"Forêt\",\n [TranslationKey.GROUND_SEA]: \"Mer\",\n [TranslationKey.GROUND_PLAIN]: \"Prairie\",\n [TranslationKey.GROUND_SWAMP]: \"Marécage\",\n [TranslationKey.GROUND_MINE]: \"Mine\",\n [TranslationKey.GROUND_GRASSLAND]: \"Steppe\",\n [TranslationKey.GROUND_LAKE]: \"Lac\",\n [TranslationKey.GROUND_JUNGLE]: \"Jungle\",\n [TranslationKey.GROUND_QUARRY]: \"Carrière\",\n [TranslationKey.GROUND_DESERT]: \"Désert\",\n [TranslationKey.GROUND_VOLCANO]: \"Volcan\",\n\n // Resources\n [TranslationKey.RESOURCE_MAMMOTH]: \"Mammouth\",\n [TranslationKey.RESOURCE_FISH]: \"Poisson\",\n [TranslationKey.RESOURCE_MUSHROOM]: \"Champignon\",\n [TranslationKey.RESOURCE_FLINT]: \"Silex\",\n\n // Cavemen\n [TranslationKey.CAVEMAN_HUNTER_GATHERER]: \"Chasseur-cueilleur\",\n [TranslationKey.CAVEMAN_WARRIOR]: \"Guerrier\",\n [TranslationKey.CAVEMAN_MAMMOTH_HUNTER]: \"Chasseur de mammouths\",\n [TranslationKey.CAVEMAN_FISHERMAN]: \"Pêcheur\",\n [TranslationKey.CAVEMAN_MUSHROOM_PICKER]: \"Cueilleur de champignons\",\n [TranslationKey.CAVEMAN_FLINT_COLLECTOR]: \"Tailleur de silex\",\n [TranslationKey.CAVEMAN_TRAPPER]: \"Trappeur\",\n [TranslationKey.CAVEMAN_GATHERER]: \"Cueilleur\",\n [TranslationKey.CAVEMAN_FIRE_LADY]: \"Dame du Feu\",\n [TranslationKey.CAVEMAN_WARRIOR_SMALL]: \"Petit guerrier\",\n [TranslationKey.CAVEMAN_WARRIOR_AMAZON]: \"Amazone\",\n [TranslationKey.CAVEMAN_WARRIOR_OAFISH]: \"Gros balourd\",\n\n // Game phases\n [TranslationKey.PHASE_ADD_PLAYERS]: \"Ajout des joueurs\",\n [TranslationKey.PHASE_OPTIONS]: \"Options de jeu\",\n [TranslationKey.PHASE_START]: \"Début de la partie\",\n [TranslationKey.PHASE_RESULT]: \"Résultats\",\n\n // Actions\n [TranslationKey.ACTION_PICK_DOMINO]: \"Choisir un domino\",\n [TranslationKey.ACTION_PLACE_DOMINO]: \"Placer le domino\",\n [TranslationKey.ACTION_PASS]: \"Passer\",\n [TranslationKey.ACTION_PLACE_KNIGHT]: \"Placer un chevalier\",\n [TranslationKey.ACTION_CONSTRUCT_BUILDING]: \"Construire un bâtiment\",\n [TranslationKey.ACTION_USE_DRAGON]: \"Utiliser le Dragon\",\n [TranslationKey.ACTION_SKIP_OPTIONAL_ACTION]: \"Passer l'action\",\n [TranslationKey.ACTION_PLACE_GIANT]: \"Placer un géant\",\n [TranslationKey.ACTION_SEND_GIANT]: \"Envoyer un géant\",\n [TranslationKey.ACTION_PLACE_FIRE_TOKEN]: \"Placer un jeton feu\",\n [TranslationKey.ACTION_RECRUIT_CAVEMAN]: \"Recruter un homme préhistorique\",\n\n // Queendomino errors\n [TranslationKey.ERROR_CANNOT_PLACE_KNIGHT]:\n \"Impossible de placer un chevalier ici\",\n [TranslationKey.ERROR_MAX_KNIGHTS_REACHED]:\n \"Nombre maximal de chevaliers atteint (3)\",\n [TranslationKey.ERROR_KNIGHT_TERRITORY_OCCUPIED]:\n \"Ce territoire a déjà un chevalier\",\n [TranslationKey.ERROR_CANNOT_AFFORD_BUILDING]:\n \"Pas assez de pièces pour acheter ce bâtiment\",\n [TranslationKey.ERROR_NO_CONSTRUCTION_SQUARE]:\n \"Aucune case de construction libre disponible\",\n [TranslationKey.ERROR_DRAGON_UNAVAILABLE]:\n \"Le Dragon n'est pas disponible ce tour-ci\",\n [TranslationKey.ERROR_QUEEN_HOLDER_CANNOT_USE_DRAGON]:\n \"Le détenteur de la Reine ne peut pas utiliser le Dragon\",\n [TranslationKey.ERROR_BUILDING_NOT_FOUND]:\n \"Bâtiment introuvable sur le plateau des bâtisseurs\",\n [TranslationKey.ERROR_INVALID_OPTIONAL_ACTION]:\n \"Action optionnelle invalide pour cet état de jeu\",\n\n // Age of Giants errors\n [TranslationKey.ERROR_GIANT_POOL_EMPTY]:\n \"Il ne reste plus de géant en réserve\",\n [TranslationKey.ERROR_GIANT_NOT_FOUND]: \"Géant introuvable dans le royaume\",\n [TranslationKey.ERROR_INVALID_GIANT_PLACEMENT]:\n \"Position invalide pour le géant — elle doit être une couronne non couverte\",\n [TranslationKey.ERROR_NOT_AOG_MODE]:\n \"Le mode L'Âge des Géants n'est pas activé\",\n\n // Origins errors\n [TranslationKey.ERROR_FIRE_TOKEN_POOL_EMPTY]:\n \"Il ne reste plus de jeton feu en réserve\",\n [TranslationKey.ERROR_FIRE_TOKEN_INVALID_POSITION]:\n \"Position invalide pour le jeton feu\",\n [TranslationKey.ERROR_NO_PENDING_FIRE_TOKEN]: \"Aucun jeton feu à placer\",\n [TranslationKey.ERROR_CANNOT_RECRUIT_CAVEMAN]:\n \"Impossible de recruter un homme préhistorique\",\n [TranslationKey.ERROR_INSUFFICIENT_RESOURCES]:\n \"Ressources insuffisantes pour cette action\",\n [TranslationKey.ERROR_INVALID_CAVEMAN_PLACEMENT]:\n \"Position invalide pour l'homme préhistorique\",\n [TranslationKey.ERROR_CAVEMAN_NOT_FOUND]: \"Homme préhistorique introuvable\",\n [TranslationKey.ERROR_NOT_TRIBE_MODE]: \"Le mode Tribu n'est pas activé\",\n [TranslationKey.ERROR_INVALID_PLAYER_ID]:\n \"Les identifiants des joueurs doivent être non vides et uniques\",\n\n // Score breakdown labels\n [TranslationKey.SCORE_QUEEN]: \"Reine\",\n [TranslationKey.SCORE_BUILDING]: \"Bâtiment : {{name}}\",\n [TranslationKey.SCORE_TOTEM_MAMMOTH]: \"Totem mammouth\",\n [TranslationKey.SCORE_TOTEM_FISH]: \"Totem poisson\",\n [TranslationKey.SCORE_TOTEM_MUSHROOM]: \"Totem champignon\",\n [TranslationKey.SCORE_TOTEM_FLINT]: \"Totem silex\",\n [TranslationKey.SCORE_RESOURCES]: \"Ressources\",\n [TranslationKey.SCORE_WARRIORS]: \"Groupes de guerriers\",\n [TranslationKey.SCORE_FIRE]: \"Jetons feu\",\n [TranslationKey.QUEST_LOCAL_TRADE]: \"Commerce local\",\n [TranslationKey.QUEST_KINGDOM_BORDERS]: \"Frontières du royaume\",\n [TranslationKey.QUEST_HARMONY]: \"Harmonie\",\n [TranslationKey.QUEST_MIDDLE_KINGDOM]: \"Empire du Milieu\",\n [TranslationKey.QUEST_LOST_CORNER]: \"Coin perdu\",\n [TranslationKey.QUEST_MEGALOMANIA]: \"Mégalomanie\",\n [TranslationKey.QUEST_AUSTERE_KING]: \"Roi austère\",\n};\n\n/** Locales shipped with the engine. */\nexport const supportedLocales = [\"en\", \"fr\"] as const;\n\n/** A locale shipped with the engine. */\nexport type SupportedLocale = (typeof supportedLocales)[number];\n\n/**\n * Built-in translation dictionaries, indexed by locale.\n * Every dictionary contains every `TranslationKey`.\n *\n * @example\n * ```typescript\n * const translator = createTranslator(localeTranslations.fr);\n * ```\n */\nexport const localeTranslations: Record<\n SupportedLocale,\n Record<TranslationKeyType, string>\n> = {\n en: englishTranslations,\n fr: frenchTranslations,\n};\n\n/**\n * Maps every terrain type (`Ground`) to its translation key.\n */\nexport const groundToTranslationKey: Record<Ground, TranslationKeyType> = {\n castle: TranslationKey.GROUND_CASTLE,\n wheat: TranslationKey.GROUND_WHEAT,\n forest: TranslationKey.GROUND_FOREST,\n sea: TranslationKey.GROUND_SEA,\n plain: TranslationKey.GROUND_PLAIN,\n swamp: TranslationKey.GROUND_SWAMP,\n mine: TranslationKey.GROUND_MINE,\n grassland: TranslationKey.GROUND_GRASSLAND,\n lake: TranslationKey.GROUND_LAKE,\n jungle: TranslationKey.GROUND_JUNGLE,\n quarry: TranslationKey.GROUND_QUARRY,\n desert: TranslationKey.GROUND_DESERT,\n volcano: TranslationKey.GROUND_VOLCANO,\n};\n\n/**\n * Maps every player action (`PlayerActions`) to its translation key.\n */\nexport const playerActionToTranslationKey: Record<\n PlayerActions,\n TranslationKeyType\n> = {\n pickDomino: TranslationKey.ACTION_PICK_DOMINO,\n placeDomino: TranslationKey.ACTION_PLACE_DOMINO,\n pass: TranslationKey.ACTION_PASS,\n placeKnight: TranslationKey.ACTION_PLACE_KNIGHT,\n constructBuilding: TranslationKey.ACTION_CONSTRUCT_BUILDING,\n useDragon: TranslationKey.ACTION_USE_DRAGON,\n skipOptionalAction: TranslationKey.ACTION_SKIP_OPTIONAL_ACTION,\n placeGiant: TranslationKey.ACTION_PLACE_GIANT,\n sendGiant: TranslationKey.ACTION_SEND_GIANT,\n placeFireToken: TranslationKey.ACTION_PLACE_FIRE_TOKEN,\n recruitCaveman: TranslationKey.ACTION_RECRUIT_CAVEMAN,\n};\n\n/**\n * Maps every Origins resource type to its translation key.\n */\nexport const resourceToTranslationKey: Record<\n ResourceType,\n TranslationKeyType\n> = {\n mammoth: TranslationKey.RESOURCE_MAMMOTH,\n fish: TranslationKey.RESOURCE_FISH,\n mushroom: TranslationKey.RESOURCE_MUSHROOM,\n flint: TranslationKey.RESOURCE_FLINT,\n};\n\n/**\n * Maps every caveman tile kind (`CavemanKind`) to its translation key.\n */\nexport const cavemanKindToTranslationKey: Record<\n CavemanKind,\n TranslationKeyType\n> = {\n hunterGatherer: TranslationKey.CAVEMAN_HUNTER_GATHERER,\n warrior: TranslationKey.CAVEMAN_WARRIOR,\n};\n\n/**\n * Maps every hunter-gatherer type to its translation key.\n */\nexport const hunterGathererKindToTranslationKey: Record<\n HunterGathererKind,\n TranslationKeyType\n> = {\n mammothHunter: TranslationKey.CAVEMAN_MAMMOTH_HUNTER,\n fisherman: TranslationKey.CAVEMAN_FISHERMAN,\n mushroomPicker: TranslationKey.CAVEMAN_MUSHROOM_PICKER,\n flintCollector: TranslationKey.CAVEMAN_FLINT_COLLECTOR,\n trapper: TranslationKey.CAVEMAN_TRAPPER,\n gatherer: TranslationKey.CAVEMAN_GATHERER,\n fireLady: TranslationKey.CAVEMAN_FIRE_LADY,\n};\n\n/**\n * Maps every warrior type to its translation key.\n */\nexport const warriorTypeToTranslationKey: Record<\n WarriorType,\n TranslationKeyType\n> = {\n small: TranslationKey.CAVEMAN_WARRIOR_SMALL,\n amazon: TranslationKey.CAVEMAN_WARRIOR_AMAZON,\n oafish: TranslationKey.CAVEMAN_WARRIOR_OAFISH,\n};\n\n/**\n * Maps game mode names (`GameMode[\"name\"]`, as returned by `getModes`)\n * to their translation key.\n */\nexport const modeNameToTranslationKey: Readonly<\n Record<string, TranslationKeyType>\n> = {\n Classic: TranslationKey.MODE_CLASSIC,\n QueenDomino: TranslationKey.MODE_QUEENDOMINO,\n \"KingdominoOrigins-Discovery\": TranslationKey.MODE_ORIGINS_DISCOVERY,\n \"KingdominoOrigins-Totem\": TranslationKey.MODE_ORIGINS_TOTEM,\n \"KingdominoOrigins-Tribe\": TranslationKey.MODE_ORIGINS_TRIBE,\n AgeOfGiants: TranslationKey.MODE_AGE_OF_GIANTS,\n \"AgeOfGiants-QueenDomino\": TranslationKey.MODE_AGE_OF_GIANTS_QUEENDOMINO,\n};\n\n/**\n * Maps extra rule names (`ExtraRule[\"name\"]`, as returned by `getExtraRules`)\n * to their translation key.\n */\nexport const extraRuleNameToTranslationKey: Readonly<\n Record<string, TranslationKeyType>\n> = {\n \"The middle Kingdom\": TranslationKey.RULE_MIDDLE_KINGDOM,\n Harmony: TranslationKey.RULE_HARMONY,\n \"The Mighty Duel\": TranslationKey.RULE_MIGHTY_DUEL,\n Dynasty: TranslationKey.RULE_DYNASTY,\n \"Empire of Fire\": TranslationKey.RULE_EMPIRE_OF_FIRE,\n \"Homo Habilis\": TranslationKey.RULE_HOMO_HABILIS,\n Neolithic: TranslationKey.RULE_NEOLITHIC,\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.EXTRA_RULE_NOT_AVAILABLE]:\n TranslationKey.ERROR_EXTRA_RULE_NOT_AVAILABLE,\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 [ErrorCode.CANNOT_PLACE_KNIGHT]: TranslationKey.ERROR_CANNOT_PLACE_KNIGHT,\n [ErrorCode.MAX_KNIGHTS_REACHED]: TranslationKey.ERROR_MAX_KNIGHTS_REACHED,\n [ErrorCode.KNIGHT_TERRITORY_OCCUPIED]:\n TranslationKey.ERROR_KNIGHT_TERRITORY_OCCUPIED,\n [ErrorCode.CANNOT_AFFORD_BUILDING]:\n TranslationKey.ERROR_CANNOT_AFFORD_BUILDING,\n [ErrorCode.NO_CONSTRUCTION_SQUARE]:\n TranslationKey.ERROR_NO_CONSTRUCTION_SQUARE,\n [ErrorCode.DRAGON_UNAVAILABLE]: TranslationKey.ERROR_DRAGON_UNAVAILABLE,\n [ErrorCode.QUEEN_HOLDER_CANNOT_USE_DRAGON]:\n TranslationKey.ERROR_QUEEN_HOLDER_CANNOT_USE_DRAGON,\n [ErrorCode.BUILDING_NOT_FOUND]: TranslationKey.ERROR_BUILDING_NOT_FOUND,\n [ErrorCode.INVALID_OPTIONAL_ACTION]:\n TranslationKey.ERROR_INVALID_OPTIONAL_ACTION,\n [ErrorCode.GIANT_POOL_EMPTY]: TranslationKey.ERROR_GIANT_POOL_EMPTY,\n [ErrorCode.GIANT_NOT_FOUND]: TranslationKey.ERROR_GIANT_NOT_FOUND,\n [ErrorCode.INVALID_GIANT_PLACEMENT]:\n TranslationKey.ERROR_INVALID_GIANT_PLACEMENT,\n [ErrorCode.NOT_AOG_MODE]: TranslationKey.ERROR_NOT_AOG_MODE,\n [ErrorCode.FIRE_TOKEN_POOL_EMPTY]: TranslationKey.ERROR_FIRE_TOKEN_POOL_EMPTY,\n [ErrorCode.FIRE_TOKEN_INVALID_POSITION]:\n TranslationKey.ERROR_FIRE_TOKEN_INVALID_POSITION,\n [ErrorCode.NO_PENDING_FIRE_TOKEN]: TranslationKey.ERROR_NO_PENDING_FIRE_TOKEN,\n [ErrorCode.CANNOT_RECRUIT_CAVEMAN]:\n TranslationKey.ERROR_CANNOT_RECRUIT_CAVEMAN,\n [ErrorCode.INSUFFICIENT_RESOURCES]:\n TranslationKey.ERROR_INSUFFICIENT_RESOURCES,\n [ErrorCode.INVALID_CAVEMAN_PLACEMENT]:\n TranslationKey.ERROR_INVALID_CAVEMAN_PLACEMENT,\n [ErrorCode.CAVEMAN_NOT_FOUND]: TranslationKey.ERROR_CAVEMAN_NOT_FOUND,\n [ErrorCode.NOT_TRIBE_MODE]: TranslationKey.ERROR_NOT_TRIBE_MODE,\n [ErrorCode.INVALID_PLAYER_ID]: TranslationKey.ERROR_INVALID_PLAYER_ID,\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\n/**\n * Maps every Age of Giants quest type to the translation key of its name\n * (used as `label` of `quest` score bonuses).\n */\nexport const questTypeToTranslationKey: Record<QuestType, TranslationKeyType> =\n {\n localTrade: TranslationKey.QUEST_LOCAL_TRADE,\n kingdomBorders: TranslationKey.QUEST_KINGDOM_BORDERS,\n harmony: TranslationKey.QUEST_HARMONY,\n middleKingdom: TranslationKey.QUEST_MIDDLE_KINGDOM,\n lostCorner: TranslationKey.QUEST_LOST_CORNER,\n megalomania: TranslationKey.QUEST_MEGALOMANIA,\n austereKing: TranslationKey.QUEST_AUSTERE_KING,\n };\n\n/**\n * Maps every Origins totem (by resource type) to the translation key of its\n * name (used as `label` of `totem` score bonuses).\n */\nexport const totemToTranslationKey: Record<ResourceType, TranslationKeyType> = {\n mammoth: TranslationKey.SCORE_TOTEM_MAMMOTH,\n fish: TranslationKey.SCORE_TOTEM_FISH,\n mushroom: TranslationKey.SCORE_TOTEM_MUSHROOM,\n flint: TranslationKey.SCORE_TOTEM_FLINT,\n};\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 { CalculatePlayerScoreCommand } from \"@application/commands/calculatePlayerScoreCommand.js\";\nimport {\n type ErrorCodeType,\n NotFoundError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { PlayerScore } from \"@core/domain/types/score.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 { CalculatePlayerScoreUseCase } from \"@core/useCases/calculatePlayerScore.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype CalculatePlayerScoreHandler = (\n command: CalculatePlayerScoreCommand,\n) => PlayerScore;\n\nexport const calculatePlayerScoreHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: CalculatePlayerScoreUseCase,\n ): CalculatePlayerScoreHandler =>\n (command) => {\n const { game, playerId } = command;\n logger.info(`Calculating score of player ${playerId} in game: ${game.id}`);\n\n const result = useCase(game, playerId);\n\n if (isErr(result)) {\n logger.error(`Error calculating player score: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new NotFoundError(translateErrorCode(translator, code), code, {\n gameId: game.id,\n playerId,\n });\n }\n\n logger.info(\n `Player score calculated: ${result.value.points} (${result.value.final ? \"final\" : \"live\"})`,\n );\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 { ConstructBuildingCommand } from \"@application/commands/constructBuildingCommand.js\";\nimport {\n ActionExecutionError,\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { GameState } 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 { ConstructBuildingUseCase } from \"@core/useCases/constructBuilding.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype ConstructBuildingHandler = (\n command: ConstructBuildingCommand,\n) => GameState;\n\nexport const constructBuildingHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: ConstructBuildingUseCase,\n ): ConstructBuildingHandler =>\n (command: ConstructBuildingCommand) => {\n const { game, lordId, buildingId, position } = command;\n logger.info(\n `Constructing building: ${buildingId} for lord: ${lordId} at position: ${JSON.stringify(\n position,\n )} in game: ${game.id}`,\n );\n\n if (game.nextAction.nextAction !== \"constructBuilding\") {\n logger.error(\n `Required game with constructBuilding action but got: ${game.nextAction.nextAction}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"constructBuilding\",\n actual: game.nextAction.nextAction,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(game, lordId, buildingId, position);\n\n if (isErr(result)) {\n logger.error(`Error constructing building: ${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 buildingId: command.buildingId,\n position: command.position,\n },\n );\n }\n\n logger.info(\n `Building constructed: ${buildingId} for lord: ${lordId} at position: ${JSON.stringify(\n position,\n )} 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, command.groupBy);\n logger.info(`Dynasty results calculated`);\n return results;\n };\n};\n","import type { GetExtraRulesCommand } from \"@application/commands/getExtraRulesCommand.js\";\nimport {\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 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} from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameWithResults,\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 { 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 },\n ): GetResultHandler =>\n (command: GetResultCommand) => {\n const { getResultUseCase } = 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 // Every player is scored by the mode-aware score breakdown (same\n // computation as calculatePlayerScore), then ranked.\n const result = getResultUseCase(game);\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 { GetValidActionTargetsCommand } from \"@application/commands/getValidActionTargetsCommand.js\";\nimport type { Translator } from \"@core/i18n/translations.js\";\nimport type { Logger } from \"@core/portServerside/logger.js\";\nimport type { ValidActionTargetsUseCase } from \"@core/useCases/getValidActionTargets.js\";\n\ntype GetValidActionTargetsHandler<T> = (\n command: GetValidActionTargetsCommand,\n) => T;\n\n/**\n * Creates a handler for one valid-target query (`getValidKnightPositions`,\n * `canSkipOptionalAction`, ...). Queries never throw: they answer empty when\n * the action does not apply.\n *\n * @param name - Query name, used in log messages\n * @param useCase - The query use case\n * @param describe - Summarizes the answer for the logs\n */\nexport const getValidActionTargetsHandler = <T>(\n logger: Logger,\n _translator: Translator,\n name: string,\n useCase: ValidActionTargetsUseCase<T>,\n describe: (answer: T) => string,\n): GetValidActionTargetsHandler<T> => {\n return (command) => {\n const { game, lordId } = command;\n logger.info(`${name} for lord: ${lordId ?? \"current\"} in game: ${game.id}`);\n const answer = useCase(game, lordId);\n logger.info(`${name}: ${describe(answer)}`);\n return answer;\n };\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 { PlaceFireTokenCommand } from \"@application/commands/placeFireTokenCommand.js\";\nimport {\n ActionExecutionError,\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { GameState } 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 { PlaceFireTokenUseCase } from \"@core/useCases/placeFireToken.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype PlaceFireTokenHandler = (command: PlaceFireTokenCommand) => GameState;\n\nexport const placeFireTokenHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: PlaceFireTokenUseCase,\n ): PlaceFireTokenHandler =>\n (command: PlaceFireTokenCommand) => {\n const { game, lordId, position } = command;\n logger.info(\n `Placing fire token for lord: ${lordId} at position: ${JSON.stringify(\n position,\n )} in game: ${game.id}`,\n );\n\n if (game.nextAction.nextAction !== \"placeFireToken\") {\n logger.error(\n `Required game with placeFireToken action but got: ${game.nextAction.nextAction}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"placeFireToken\",\n actual: game.nextAction.nextAction,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(game, lordId, position);\n\n if (isErr(result)) {\n logger.error(`Error placing fire token: ${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 },\n );\n }\n\n logger.info(\n `Fire token placed for lord: ${lordId} at position: ${JSON.stringify(\n position,\n )} in game: ${game.id}`,\n );\n return result.value;\n };\n","import type { PlaceGiantCommand } from \"@application/commands/placeGiantCommand.js\";\nimport {\n ActionExecutionError,\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { GameState } 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 { PlaceGiantUseCase } from \"@core/useCases/placeGiant.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype PlaceGiantHandler = (command: PlaceGiantCommand) => GameState;\n\nexport const placeGiantHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: PlaceGiantUseCase,\n ): PlaceGiantHandler =>\n (command: PlaceGiantCommand) => {\n const { game, lordId, position } = command;\n logger.info(\n `Placing giant for lord: ${lordId} at position: ${JSON.stringify(position)} in game: ${game.id}`,\n );\n\n if (game.nextAction.nextAction !== \"placeGiant\") {\n logger.error(\n `Required game with placeGiant action but got: ${game.nextAction.nextAction}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"placeGiant\",\n actual: game.nextAction.nextAction,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(game, lordId, position);\n\n if (isErr(result)) {\n logger.error(`Error placing giant: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new ActionExecutionError(\n translateErrorCode(translator, code),\n code,\n { gameId: game.id, lordId, position },\n );\n }\n\n logger.info(`Giant placed for lord: ${lordId} in game: ${game.id}`);\n return result.value;\n };\n","import type { PlaceKnightCommand } from \"@application/commands/placeKnightCommand.js\";\nimport {\n ActionExecutionError,\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { GameState } 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 { PlaceKnightUseCase } from \"@core/useCases/placeKnight.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype PlaceKnightHandler = (command: PlaceKnightCommand) => GameState;\n\nexport const placeKnightHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: PlaceKnightUseCase,\n ): PlaceKnightHandler =>\n (command: PlaceKnightCommand) => {\n const { game, lordId, position } = command;\n logger.info(\n `Placing knight for lord: ${lordId} at position: ${JSON.stringify(\n position,\n )} in game: ${game.id}`,\n );\n\n if (game.nextAction.nextAction !== \"placeKnight\") {\n logger.error(\n `Required game with placeKnight action but got: ${game.nextAction.nextAction}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"placeKnight\",\n actual: game.nextAction.nextAction,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(game, lordId, position);\n\n if (isErr(result)) {\n logger.error(`Error placing knight: ${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 },\n );\n }\n\n logger.info(\n `Knight placed for lord: ${lordId} at position: ${JSON.stringify(\n position,\n )} in game: ${game.id}`,\n );\n return result.value;\n };\n","import type { RecruitCavemanCommand } from \"@application/commands/recruitCavemanCommand.js\";\nimport {\n ActionExecutionError,\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { GameState } 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 { RecruitCavemanUseCase } from \"@core/useCases/recruitCaveman.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype RecruitCavemanHandler = (command: RecruitCavemanCommand) => GameState;\n\nexport const recruitCavemanHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: RecruitCavemanUseCase,\n ): RecruitCavemanHandler =>\n (command: RecruitCavemanCommand) => {\n const { game, lordId, cavemanId, position, resourcePositions } = command;\n logger.info(\n `Recruiting caveman ${cavemanId} for lord: ${lordId} in game: ${game.id}`,\n );\n\n if (game.nextAction.nextAction !== \"recruitCaveman\") {\n logger.error(\n `Required game with recruitCaveman action but got: ${game.nextAction.nextAction}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"recruitCaveman\",\n actual: game.nextAction.nextAction,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(\n game,\n lordId,\n cavemanId,\n position,\n resourcePositions,\n );\n\n if (isErr(result)) {\n logger.error(`Error recruiting caveman: ${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,\n cavemanId,\n position,\n },\n );\n }\n\n logger.info(\n `Caveman ${cavemanId} recruited for lord: ${lordId} in game: ${game.id}`,\n );\n return result.value;\n };\n","import type { SendGiantCommand } from \"@application/commands/sendGiantCommand.js\";\nimport {\n ActionExecutionError,\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { GameState } 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 { SendGiantUseCase } from \"@core/useCases/sendGiant.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype SendGiantHandler = (command: SendGiantCommand) => GameState;\n\nexport const sendGiantHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: SendGiantUseCase,\n ): SendGiantHandler =>\n (command: SendGiantCommand) => {\n const { game, lordId, giantIndex, targetPlayerId, targetCrownPosition } =\n command;\n logger.info(\n `Sending giant for lord: ${lordId} to player: ${targetPlayerId} in game: ${game.id}`,\n );\n\n if (game.nextAction.nextAction !== \"sendGiant\") {\n logger.error(\n `Required game with sendGiant action but got: ${game.nextAction.nextAction}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"sendGiant\",\n actual: game.nextAction.nextAction,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(\n game,\n lordId,\n giantIndex,\n targetPlayerId,\n targetCrownPosition,\n );\n\n if (isErr(result)) {\n logger.error(`Error sending giant: ${result.error}`);\n const code = result.error as ErrorCodeType;\n throw new ActionExecutionError(\n translateErrorCode(translator, code),\n code,\n { gameId: game.id, lordId, targetPlayerId, targetCrownPosition },\n );\n }\n\n logger.info(\n `Giant sent from lord: ${lordId} to player: ${targetPlayerId} in game: ${game.id}`,\n );\n return result.value;\n };\n","import type { GameState } from \"@core/domain/types/index.js\";\nimport { err, ok, 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 { SkipOptionalActionCommand } from \"@application/commands/skipOptionalActionCommand.js\";\nimport {\n ActionExecutionError,\n type ErrorCodeType,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { GameState } 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 { SkipOptionalActionUseCase } from \"@core/useCases/skipOptionalAction.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype SkipOptionalActionHandler = (\n command: SkipOptionalActionCommand,\n) => GameState;\n\nexport const skipOptionalActionHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: SkipOptionalActionUseCase,\n ): SkipOptionalActionHandler =>\n (command: SkipOptionalActionCommand) => {\n const { game, lordId } = command;\n logger.info(\n `Skipping optional action for lord: ${lordId} in game: ${game.id}`,\n );\n\n const result = useCase(game, lordId);\n\n if (isErr(result)) {\n logger.error(`Error skipping optional action: ${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 logger.info(\n `Optional action skipped for lord: ${lordId} in game: ${game.id}`,\n );\n return result.value;\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 { UseDragonCommand } from \"@application/commands/useDragonCommand.js\";\nimport {\n ActionExecutionError,\n ErrorCode,\n type ErrorCodeType,\n InvalidStepError,\n} from \"@core/domain/errors/domainErrors.js\";\nimport type { GameState } 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 { UseDragonUseCase } from \"@core/useCases/useDragon.js\";\nimport { isErr } from \"@utils/result.js\";\n\ntype UseDragonHandler = (command: UseDragonCommand) => GameState;\n\nexport const useDragonHandler =\n (\n logger: Logger,\n translator: Translator,\n useCase: UseDragonUseCase,\n ): UseDragonHandler =>\n (command: UseDragonCommand) => {\n const { game, lordId, buildingId } = command;\n logger.info(\n `Using dragon on building: ${buildingId} for lord: ${lordId} in game: ${game.id}`,\n );\n\n if (game.nextAction.nextAction !== \"useDragon\") {\n logger.error(\n `Required game with useDragon action but got: ${game.nextAction.nextAction}`,\n );\n throw new InvalidStepError(\n translateErrorCode(translator, ErrorCode.INVALID_STEP),\n {\n expected: \"useDragon\",\n actual: game.nextAction.nextAction,\n gameId: game.id,\n },\n );\n }\n\n const result = useCase(game, lordId, buildingId);\n\n if (isErr(result)) {\n logger.error(`Error using dragon: ${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 buildingId: command.buildingId,\n },\n );\n }\n\n logger.info(\n `Dragon used on building: ${buildingId} for lord: ${lordId} in game: ${game.id}`,\n );\n return result.value;\n };\n","import type { ExtraRule } from \"@core/domain/types/rule.js\";\nimport { ok, type Result } from \"@utils/result.js\";\n\n/**\n * Extra rules that replace the 2-player setup with all 48 dominoes and a\n * 7x7 kingdom: \"The Mighty Duel\" (Kingdomino/Queendomino) and its Origins\n * counterpart \"Neolithic\".\n */\nexport const LARGE_KINGDOM_EXTRA_RULES: readonly string[] = [\n \"The Mighty Duel\",\n \"Neolithic\",\n];\n\nexport const isLargeKingdomExtraRule = (rule: ExtraRule): boolean =>\n LARGE_KINGDOM_EXTRA_RULES.includes(rule.name);\n\n/**\n * Checks whether an extra rule can be used for a mode and a player count.\n * `playersLimit` is the exact number of players the rule requires.\n */\nexport const isExtraRuleAvailable = (\n rule: ExtraRule,\n mode: string,\n numberOfPlayers: number,\n): boolean =>\n rule.mode.some((m) => m.name === mode) &&\n (!rule.playersLimit || rule.playersLimit === numberOfPlayers);\n\n/**\n * Returns the extra rules available for a mode and a player count.\n * An empty list is a valid answer (e.g. a mode without optional rules).\n */\nexport const getAvailablesExtraRules = (\n extraRules: ExtraRule[],\n mode: string,\n numberOfPlayers: number,\n): Result<ExtraRule[]> =>\n ok(\n extraRules.filter((rule) =>\n isExtraRuleAvailable(rule, mode, numberOfPlayers),\n ),\n );\n","import type { Ground } from \"./domino.js\";\nimport type { Position } from \"./kingdom.js\";\nimport type { ObjectValues } from \"./utils.js\";\n\n// ─── Giants ─────────────────────────────────────────────────────────\n\n/**\n * A giant placed on a player's kingdom, covering a crown.\n * The covered crown does not count for scoring.\n */\nexport type PlacedGiant = {\n /** Position on the kingdom grid where the giant covers a crown */\n position: Position;\n};\n\n// ─── Quest Tiles ────────────────────────────────────────────────────\n\n/**\n * All quest tile types available in Age of Giants.\n */\nexport const questTypes = {\n /** 5pts per matching terrain tile adjacent (8-dir) to castle */\n localTrade: \"localTrade\",\n /** 5pts per matching terrain tile in the 4 corners of the kingdom */\n kingdomBorders: \"kingdomBorders\",\n /** 5pts if kingdom is complete (no discarded dominos) */\n harmony: \"harmony\",\n /** 10pts if castle is in the center of the kingdom */\n middleKingdom: \"middleKingdom\",\n /** 20pts if castle is in one of the 4 corners of the kingdom */\n lostCorner: \"lostCorner\",\n /** 10pts per alignment of 3+ tiles with crowns (H/V/diagonal) */\n megalomania: \"megalomania\",\n /** 10pts per property of 5+ wheat/forest/sea/plain tiles with 0 crowns */\n austereKing: \"austereKing\",\n} as const;\n\nexport type QuestType = ObjectValues<typeof questTypes>;\n\n/**\n * A quest tile drawn at game start.\n * Provides a specific end-of-game bonus scoring condition.\n */\nexport type QuestTile = {\n /** Unique identifier for the quest tile */\n id: number;\n /** Type of quest determining the scoring rule */\n type: QuestType;\n /** Display name of the quest */\n name: string;\n /** Description of the scoring condition */\n description: string;\n /** Points awarded per match (e.g., 5 for localTrade, 10 for megalomania) */\n points: number;\n /** Target terrain type (only for localTrade and kingdomBorders quests) */\n terrain?: Ground;\n};\n\n// ─── Age of Giants Game State ───────────────────────────────────────\n\n/**\n * A giant sent with `sendGiant` that the targeted opponent must now place on\n * one of their own crowns (official rule: the opponent chooses the crown).\n * While it is set, `nextAction` is `placeGiant` for a lord of the target.\n */\nexport type PendingGiant = {\n /** Lord who sent the giant; their turn resumes once the giant is placed */\n fromLordId: string;\n /** Player who received the giant and must choose the crown */\n targetPlayerId: string;\n};\n\n/**\n * Complete Age of Giants-specific game state.\n * Stored as an optional field on Game and only present in AoG modes.\n */\nexport type AgeOfGiantsState = {\n /** Number of giant figurines remaining in the pool (starts at 6) */\n giantPool: number;\n /** The 2 quest tiles drawn for this game */\n questTiles: QuestTile[];\n /** Giant sent to an opponent, waiting for that opponent to choose a crown */\n pendingGiant?: PendingGiant;\n};\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 \"grassland\",\n \"lake\",\n \"jungle\",\n \"quarry\",\n \"desert\",\n \"volcano\",\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. In Origins, represents fire symbols. */\n crowns: Crown;\n /** Whether this tile has a construction square for buildings (Queendomino) */\n hasConstructionSquare?: boolean;\n /** Number of volcanic craters on this tile (Origins, 1-3). Determines fire token type. */\n volcanoCraters?: number;\n /** Whether this tile has a giant icon (Age of Giants, letter dominos A-F) */\n hasGiant?: boolean;\n /** Whether this tile has footprint icons (Age of Giants, dominos 49-54) */\n hasFootprint?: boolean;\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). Letter dominos use fractional numbers (A=0.01...F=0.06). */\n number: number;\n /** Display letter for Age of Giants giant dominos (A-F). Undefined for numbered dominos. */\n letter?: string;\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 { 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","import type { Position } from \"./kingdom.js\";\nimport type { ObjectValues } from \"./utils.js\";\n\n// ─── Origins Sub-Modes ───────────────────────────────────────────────\n\n/**\n * The three gameplay modes within Kingdomino Origins.\n * Discovery is the base, Totem adds resources/totems, Tribe adds cavemen.\n */\nexport const originsSubModes = {\n discovery: \"Discovery\",\n totem: \"Totem\",\n tribe: \"Tribe\",\n} as const;\n\nexport type OriginsSubMode = ObjectValues<typeof originsSubModes>;\n\n// ─── Fire Tokens ─────────────────────────────────────────────────────\n\n/**\n * Represents the pool of available fire tokens.\n * Discovery Mode starts with: 5×1-fire, 4×2-fire, 1×3-fire = 10 total.\n */\nexport type FireTokenPool = {\n ones: number;\n twos: number;\n threes: number;\n};\n\n/**\n * A fire token that has been placed on a player's kingdom.\n */\nexport type PlacedFireToken = {\n /** Number of fires on this token (1, 2, or 3) */\n fires: 1 | 2 | 3;\n /** Position on the kingdom grid */\n position: Position;\n};\n\n/**\n * Tracks which volcano granted the current pending fire token,\n * so the placement validation knows the launch position.\n */\nexport type PendingFireToken = {\n /** Number of fires on the token to place */\n fires: 1 | 2 | 3;\n /** Position of the volcano that granted this token */\n volcanoPosition: Position;\n};\n\n// ─── Resources ───────────────────────────────────────────────────────\n\n/**\n * Types of wooden resources in Origins.\n * Each maps to a specific terrain type.\n */\nexport const resourceTypes = {\n mammoth: \"mammoth\",\n fish: \"fish\",\n mushroom: \"mushroom\",\n flint: \"flint\",\n} as const;\n\nexport type ResourceType = ObjectValues<typeof resourceTypes>;\n\n/**\n * A wooden resource placed on a player's kingdom tile.\n */\nexport type Resource = {\n /** Type of resource */\n type: ResourceType;\n /** Position on the kingdom grid */\n position: Position;\n};\n\n// ─── Totems ──────────────────────────────────────────────────────────\n\n/**\n * Tracks which player holds each totem tile.\n * null means no player currently holds that totem.\n */\nexport type TotemState = Record<ResourceType, string | null>;\n\n/**\n * Point values for each totem tile at end of game.\n */\nexport type TotemBonus = Record<ResourceType, number>;\n\n// ─── Cavemen ─────────────────────────────────────────────────────────\n\n/**\n * The 7 kinds of hunter-gatherers.\n * Each has a specific scoring rule based on surrounding resources.\n */\nexport const hunterGathererKinds = {\n /** Scores per mammoth adjacent */\n mammothHunter: \"mammothHunter\",\n /** Scores per fish adjacent */\n fisherman: \"fisherman\",\n /** Scores per mushroom adjacent */\n mushroomPicker: \"mushroomPicker\",\n /** Scores per flint adjacent */\n flintCollector: \"flintCollector\",\n /** Scores per unique resource type adjacent */\n trapper: \"trapper\",\n /** Scores per total resource adjacent (any type) */\n gatherer: \"gatherer\",\n /** Scores per fire symbol adjacent (Fire Lady) */\n fireLady: \"fireLady\",\n} as const;\n\nexport type HunterGathererKind = ObjectValues<typeof hunterGathererKinds>;\n\n/**\n * Warrior size categories with their power values.\n */\nexport const warriorTypes = {\n small: \"small\",\n amazon: \"amazon\",\n oafish: \"oafish\",\n} as const;\n\nexport type WarriorType = ObjectValues<typeof warriorTypes>;\n\n/**\n * Power values for each warrior type.\n */\nexport const WARRIOR_POWER: Record<WarriorType, number> = {\n small: 1,\n amazon: 2,\n oafish: 3,\n};\n\n/**\n * A hunter-gatherer caveman tile.\n */\nexport type HunterGathererTile = {\n kind: \"hunterGatherer\";\n id: number;\n /** Specific hunter-gatherer type determining scoring rule */\n hunterType: HunterGathererKind;\n /** Points per matching adjacent resource/symbol */\n pointsPerMatch: number;\n};\n\n/**\n * A warrior caveman tile.\n */\nexport type WarriorTile = {\n kind: \"warrior\";\n id: number;\n /** Warrior size category */\n warriorType: WarriorType;\n /** Combat power (1, 2, or 3) */\n power: number;\n};\n\n/**\n * Discriminant values of `CavemanTile[\"kind\"]`.\n */\nexport const cavemanKinds = {\n hunterGatherer: \"hunterGatherer\",\n warrior: \"warrior\",\n} as const;\n\nexport type CavemanKind = ObjectValues<typeof cavemanKinds>;\n\n/** Discriminated union of all caveman tile types (discriminant: `kind`). */\nexport type CavemanTile = HunterGathererTile | WarriorTile;\n\n/**\n * Type guard to check if a caveman tile is a hunter-gatherer.\n * @param caveman - The caveman tile to check\n * @returns True if the tile is a `HunterGathererTile`\n */\nexport const isHunterGathererTile = (\n caveman: CavemanTile,\n): caveman is HunterGathererTile => {\n return caveman.kind === cavemanKinds.hunterGatherer;\n};\n\n/**\n * Type guard to check if a caveman tile is a warrior.\n * @param caveman - The caveman tile to check\n * @returns True if the tile is a `WarriorTile`\n */\nexport const isWarriorTile = (caveman: CavemanTile): caveman is WarriorTile => {\n return caveman.kind === cavemanKinds.warrior;\n};\n\n/**\n * A caveman tile placed on a player's kingdom.\n */\nexport type PlacedCaveman = {\n caveman: CavemanTile;\n position: Position;\n};\n\n/**\n * The Cave board used in Tribe mode.\n * Shows 4 visible caveman tiles and a face-down draw pile.\n */\nexport type CaveBoard = {\n /** Up to 4 visible caveman tiles available for recruitment */\n visible: CavemanTile[];\n /** Face-down draw pile */\n drawPile: CavemanTile[];\n};\n\n// ─── Origins Game State ──────────────────────────────────────────────\n\n/**\n * Complete Origins-specific game state.\n * Stored as an optional field on Game and only present in Origins modes.\n */\nexport type OriginsState = {\n /** Which Origins sub-mode is being played */\n subMode: OriginsSubMode;\n /** Available fire tokens pool */\n fireTokenPool: FireTokenPool;\n /** Pending fire token to place (set after placing a volcano domino) */\n pendingFireToken?: PendingFireToken;\n /** Totem holder state (Totem mode only) */\n totems?: TotemState;\n /** Cave board state (Tribe mode only) */\n caveBoard?: CaveBoard;\n};\n","import type { PlacedGiant } from \"./ageOfGiants.js\";\nimport type { PlacedBuilding } from \"./building.js\";\nimport type { Kingdom, Position } from \"./kingdom.js\";\nimport type { PlacedCaveman, PlacedFireToken, Resource } from \"./origins.js\";\nimport type { ObjectValues } from \"./utils.js\";\n\n/**\n * Represents a knight placed on a player's kingdom (Queendomino).\n */\nexport type Knight = {\n /** ID of the player who owns this knight */\n playerId: string;\n /** Position on the kingdom grid where the knight is placed */\n position: Position;\n};\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 /** Number of coins the player has (Queendomino) */\n coins?: number;\n /** Number of towers the player has (Queendomino) */\n towers?: number;\n /** Knights placed on the kingdom (Queendomino) */\n knights?: Knight[];\n /**\n * Extra knights granted by building immediate bonuses (Queendomino).\n * Each one raises the player's knight limit above the base maximum.\n */\n bonusKnights?: number;\n /** Buildings placed on the kingdom (Queendomino) */\n buildings?: PlacedBuilding[];\n /** Fire tokens placed on the kingdom (Origins) */\n fireTokens?: PlacedFireToken[];\n /** Wooden resources on the kingdom (Origins Totem/Tribe) */\n resources?: Resource[];\n /** Cavemen placed on the kingdom (Origins Tribe) */\n cavemen?: PlacedCaveman[];\n /** Giants placed on the kingdom covering crowns (Age of Giants) */\n giants?: PlacedGiant[];\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 /** Place a knight on the just-placed domino (Queendomino, optional) */\n placeKnight: \"placeKnight\",\n /** Construct a building on a construction square (Queendomino, optional) */\n constructBuilding: \"constructBuilding\",\n /** Use the Dragon to burn a building tile (Queendomino, optional) */\n useDragon: \"useDragon\",\n /** Skip the current optional action (Queendomino/Origins/AoG) */\n skipOptionalAction: \"skipOptionalAction\",\n /** Place a giant on a crown after placing a giant domino (Age of Giants, mandatory) */\n placeGiant: \"placeGiant\",\n /** Send a giant to an opponent after placing a footprint domino (Age of Giants, optional) */\n sendGiant: \"sendGiant\",\n /** Place a fire token after placing a volcano domino (Origins, optional) */\n placeFireToken: \"placeFireToken\",\n /** Recruit a caveman from the cave board (Origins Tribe, optional) */\n recruitCaveman: \"recruitCaveman\",\n} as const;\n\n/** Union type of all player actions */\nexport type PlayerActions = ObjectValues<typeof playerActions>;\n","import type { TranslationKeyType } from \"@core/i18n/translations.js\";\nimport type { QuestType } from \"./ageOfGiants.js\";\nimport type { Ground } from \"./domino.js\";\nimport type { Position } from \"./kingdom.js\";\nimport type { ResourceType } from \"./origins.js\";\nimport type { ObjectValues } from \"./utils.js\";\n\n/**\n * One scored territory (a group of orthogonally connected squares of the\n * same terrain) of a kingdom. The castle is never part of a territory.\n */\nexport type ScoreTerritory = {\n /** Terrain shared by every square of the territory */\n terrain: Ground;\n /** Squares of the territory, sorted by row then column */\n cells: Position[];\n /**\n * Crowns counted for scoring (Origins: fire symbols). Crowns covered by an\n * Age of Giants giant are not counted.\n */\n crowns: number;\n /** Crowns of the territory covered by giants (not counted in `crowns`) */\n coveredCrowns: number;\n /** Points scored by the territory: `cells.length * crowns` */\n points: number;\n};\n\n/**\n * Kinds of bonus that can appear in a score breakdown.\n */\nexport const scoreBonusTypes = {\n /** \"The middle Kingdom\" optional rule: castle in the middle (+10) */\n middleKingdom: \"middleKingdom\",\n /** \"Empire of Fire\" optional rule (Origins): hut in the middle (+10) */\n empireOfFire: \"empireOfFire\",\n /** \"Harmony\" optional rule: complete kingdom, no discarded domino (+5) */\n harmony: \"harmony\",\n /** \"Homo Habilis\" optional rule (Origins): complete territory (+5) */\n homoHabilis: \"homoHabilis\",\n /** Queendomino: the Queen counts as an extra crown on the largest territory */\n queen: \"queen\",\n /** Queendomino: end-game scoring of one constructed building */\n building: \"building\",\n /** Age of Giants: one quest tile */\n quest: \"quest\",\n /** Origins Totem: one totem held by the player */\n totem: \"totem\",\n /** Origins Totem: 1 point per wooden resource left in the kingdom */\n resources: \"resources\",\n /** Origins Tribe: one hunter-gatherer */\n hunterGatherer: \"hunterGatherer\",\n /** Origins Tribe: every warrior group */\n warriors: \"warriors\",\n /** Origins: fire tokens placed in the kingdom's territories */\n fire: \"fire\",\n} as const;\n\n/** Union of every bonus kind */\nexport type ScoreBonusType = ObjectValues<typeof scoreBonusTypes>;\n\n/**\n * One bonus of a score breakdown.\n */\nexport type ScoreBonus = {\n /** Kind of bonus */\n type: ScoreBonusType;\n /**\n * Translation key of the bonus name (see `TranslationKey`). Translate it\n * with `translator.t(bonus.label, bonus.labelParams)`.\n */\n label: TranslationKeyType;\n /** Interpolation parameters of the label (e.g. the building name) */\n labelParams?: Record<string, string | number>;\n /** Points granted by the bonus (may be 0 when its condition is not met) */\n points: number;\n /**\n * `true` while the game is in progress: the bonus is evaluated on the\n * current state and may still change (or disappear) before the end of the\n * game. `false` once the game is over.\n */\n provisional: boolean;\n /** Building id (`building` bonuses) */\n buildingId?: number;\n /** Quest tile id (`quest` bonuses) */\n questId?: number;\n /** Quest type (`quest` bonuses) */\n questType?: QuestType;\n /** Target terrain of the quest (Local Trade, Kingdom Borders) */\n terrain?: Ground;\n /** Resource of the totem (`totem` bonuses) */\n resource?: ResourceType;\n /** Caveman tile id (`hunterGatherer` bonuses) */\n cavemanId?: number;\n /** Kingdom position the bonus relates to (building, hunter-gatherer) */\n position?: Position;\n};\n\n/**\n * Detailed score of one kingdom.\n * Invariant: `total === territoryPoints + bonusPoints`, where\n * `territoryPoints` is the sum of the territory points and `bonusPoints`\n * the sum of the bonus points.\n */\nexport type ScoreBreakdown = {\n /** Every scored territory of the kingdom */\n territories: ScoreTerritory[];\n /** Every bonus applying to the player in the current game mode */\n bonuses: ScoreBonus[];\n /** Sum of the territory points */\n territoryPoints: number;\n /** Sum of the bonus points */\n bonusPoints: number;\n /** Total score: `territoryPoints + bonusPoints` */\n total: number;\n};\n\n/**\n * Mode-aware score of one player, as returned by `calculatePlayerScore`.\n */\nexport type PlayerScore = {\n /** Player's unique identifier */\n playerId: string;\n /** Player's display name */\n playerName: string;\n /** Total score (same as `breakdown.total`) */\n points: number;\n /** Size of the largest territory (tie-breaker) */\n maxPropertiesSize: number;\n /** Total crowns counted in the kingdom */\n totalCrowns: number;\n /**\n * `true` when the game is over: the score is the final score, identical\n * to the one returned by `getResults`. `false` during the game: the score\n * is a live estimate of the current state (end-of-game-only bonuses such\n * as Harmony are not included yet).\n */\n final: boolean;\n /** Detailed score */\n breakdown: ScoreBreakdown;\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\n/**\n * Deterministic pseudo-random generator (values in [0, 1)) derived from a\n * seed and a salt: the same seed and salt always give the same sequence.\n */\nexport const createSeededRandom = (\n seed: string,\n salt: string,\n): (() => number) => mulberry32(hashSeed(`${seed}|${salt}`));\n\nexport const createSeededShuffle = (\n seed: string,\n salt: string,\n): ShuffleMethod => {\n const random = createSeededRandom(seed, salt);\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 isExtraRuleAvailable,\n isLargeKingdomExtraRule,\n} from \"@core/domain/entities/rule.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport {\n type ExtraRule,\n type GameWithNextStep,\n gameSteps,\n type NextStep,\n} from \"@core/domain/types/index.js\";\nimport type { DominoesRepository } from \"@core/portServerside/dominoesRepository.js\";\nimport type { RuleRepository } from \"@core/portServerside/ruleRepository.js\";\nimport type { ShuffleMethod } from \"@core/portServerside/shuffleMethod.js\";\nimport { err, ok, type Result } from \"@utils/result.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 const numberOfPlayers = game.players.length;\n\n for (const rule of rules) {\n const candidates = availableExtraRules.filter((r) => r.name === rule);\n\n if (candidates.length === 0) {\n return err(ErrorCode.STEP_EXECUTION_FAILED);\n }\n\n // A rule name may be declared several times (one entry per mode family,\n // e.g. Dynasty): keep the entry matching this mode and player count.\n const extraRule = candidates.find((r) =>\n isExtraRuleAvailable(r, game.mode.name, numberOfPlayers),\n );\n\n if (!extraRule) {\n return err(ErrorCode.EXTRA_RULE_NOT_AVAILABLE);\n }\n\n newExtraRules.push(extraRule);\n }\n\n // The Mighty Duel (Classic/QueenDomino) and Neolithic (Origins) override\n // the 2-player setup: all 48 dominoes, 12 turns and a 7x7 kingdom.\n let updatedBasic = game.rules.basic;\n let updatedDominoes = game.dominoes;\n const hasLargeKingdomRule = newExtraRules.some(isLargeKingdomExtraRule);\n if (hasLargeKingdomRule) {\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 type { Domino } from \"@core/domain/types/domino.js\";\n\nconst AOG_MODE_PREFIX = \"AgeOfGiants\";\n\n/**\n * Checks whether the given mode name is an Age of Giants mode.\n */\nexport const isAgeOfGiantsMode = (modeName: string): boolean =>\n modeName.startsWith(AOG_MODE_PREFIX);\n\n/**\n * Checks whether the mode is Age of Giants combined with QueenDomino.\n */\nexport const isAgeOfGiantsQueenDominoMode = (modeName: string): boolean =>\n modeName === \"AgeOfGiants-QueenDomino\";\n\n/**\n * Checks whether a domino is a \"giant domino\" (has a giant icon on one of its tiles).\n * Giant dominos trigger the mandatory placeGiant action.\n */\nexport const isGiantDomino = (domino: Domino): boolean =>\n (domino.left.hasGiant ?? false) || (domino.right.hasGiant ?? false);\n\n/**\n * Positions (0-based, in the sorted 5-domino line) discarded before selection,\n * per the official Age of Giants rulebook illustration (\"Setting up lines of\n * dominoes\"): with 2 or 4 players the middle domino (3rd) is discarded, with\n * 3 players the 2nd and 4th. With 5 players nothing is discarded.\n */\nconst AOG_DISCARD_POSITIONS: Readonly<Record<number, readonly number[]>> = {\n 1: [2],\n 2: [1, 3],\n};\n\n/**\n * Removes the dominoes discarded from a sorted Age of Giants line before the\n * players choose. The line must already be sorted (letter dominoes A-F first,\n * then by number), so giant dominoes can be revealed at any player count.\n */\nexport const discardFromAgeOfGiantsLine = <T>(\n sortedLine: T[],\n discardCount: number,\n): T[] => {\n if (discardCount <= 0) {\n return sortedLine;\n }\n const positions = AOG_DISCARD_POSITIONS[discardCount] ?? [];\n return sortedLine.filter((_, index) => !positions.includes(index));\n};\n\n/**\n * Checks whether a domino is a \"footprint domino\" (has footprint icons on one of its tiles).\n * Footprint dominos trigger the optional sendGiant action.\n */\nexport const isFootprintDomino = (domino: Domino): boolean =>\n (domino.left.hasFootprint ?? false) || (domino.right.hasFootprint ?? false);\n","import type { Player } from \"@core/domain/types/player.js\";\n\n/** Default starting coins for each player in Queendomino */\nexport const STARTING_COINS = 7;\n\n/** Maximum number of knights a player can place */\nexport const MAX_KNIGHTS = 3;\n\nexport const initializeCoins = (): number => STARTING_COINS;\n\nexport const addCoins = (player: Player, amount: number): Player => ({\n ...player,\n coins: (player.coins ?? 0) + amount,\n});\n\nexport const removeCoins = (player: Player, amount: number): Player => ({\n ...player,\n coins: (player.coins ?? 0) - amount,\n});\n\nexport const canAfford = (player: Player, cost: number): boolean =>\n (player.coins ?? 0) >= cost;\n\nexport const addTowers = (player: Player, amount: number): Player => ({\n ...player,\n towers: (player.towers ?? 0) + amount,\n});\n\nexport const getTowerCount = (player: Player): number => player.towers ?? 0;\n\n/** Grant extra knights (building immediate bonus), raising the knight limit. */\nexport const addBonusKnights = (player: Player, amount: number): Player => ({\n ...player,\n bonusKnights: (player.bonusKnights ?? 0) + amount,\n});\n\n/** Maximum number of knights the player may place (base + building bonuses). */\nexport const getMaxKnights = (player: Player): number =>\n MAX_KNIGHTS + (player.bonusKnights ?? 0);\n","import {\n type Crown,\n type EmptyGround,\n type EmptyTile,\n GROUND,\n type Ground,\n type Tile,\n} from \"@core/domain/types/domino.js\";\n\nconst isGround = (ground: unknown): ground is Ground => {\n return GROUND.includes(ground as 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 { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport {\n type Domino,\n type EmptyTile,\n GRIDSIZE,\n type Kingdom,\n MAX_KINGDOM_SIZE,\n type Position,\n type Rotation,\n type Tile,\n} from \"@core/domain/types/index.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 (\n exceedsMaxSize(\n kingdom,\n firstTile.position,\n secondTile.position,\n maxKingdomSize,\n )\n ) {\n return err(ErrorCode.PLACEMENT_EXCEEDS_KINGDOM_SIZE);\n }\n\n const adjacentPairs = isAdjacent(kingdom, firstTile, secondTile);\n\n if (adjacentPairs.length === 0) {\n return err(ErrorCode.PLACEMENT_NOT_ADJACENT);\n }\n\n if (!hasValidAdjacent(adjacentPairs)) {\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\ntype AdjacentPair = { neighbor: Tile; own: Tile };\n\nconst isAdjacent = (\n kingdom: Kingdom,\n firstTile: { tile: Tile; position: Position },\n secondTile: { tile: Tile; position: Position },\n): AdjacentPair[] => {\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 === firstTile.position.x && y === firstTile.position.y) ||\n (x === secondTile.position.x && y === secondTile.position.y);\n\n const pairs: AdjacentPair[] = [];\n\n for (const own of [firstTile, secondTile]) {\n for (const offset of offsets) {\n const nx = own.position.x + offset.x;\n const ny = own.position.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 pairs.push({ neighbor: tile.value, own: own.tile });\n }\n }\n }\n\n return pairs;\n};\n\nconst hasValidAdjacent = (pairs: AdjacentPair[]): boolean => {\n return pairs.some(\n ({ neighbor, own }) =>\n neighbor.type === \"castle\" || neighbor.type === own.type,\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 type { OriginsSubMode } from \"@core/domain/types/origins.js\";\n\nconst ORIGINS_MODE_PREFIX = \"KingdominoOrigins-\";\n\n/**\n * Checks whether the given mode name is an Origins mode.\n */\nexport const isOriginsMode = (modeName: string): boolean =>\n modeName.startsWith(ORIGINS_MODE_PREFIX);\n\n/**\n * Extracts the sub-mode from an Origins mode name.\n * Returns undefined if not an Origins mode.\n */\nexport const getOriginsSubMode = (\n modeName: string,\n): OriginsSubMode | undefined => {\n if (!isOriginsMode(modeName)) return undefined;\n return modeName.slice(ORIGINS_MODE_PREFIX.length) as OriginsSubMode;\n};\n\n/**\n * Checks whether the mode is a Totem or Tribe mode (modes that use resources).\n */\nexport const isResourceMode = (modeName: string): boolean => {\n const sub = getOriginsSubMode(modeName);\n return sub === \"Totem\" || sub === \"Tribe\";\n};\n\n/**\n * Checks whether the mode is the Tribe mode (has cave board + cavemen).\n */\nexport const isTribeMode = (modeName: string): boolean => {\n return getOriginsSubMode(modeName) === \"Tribe\";\n};\n\n/**\n * Checks whether the mode is the Totem mode (has totem majority tiles).\n */\nexport const isTotemMode = (modeName: string): boolean => {\n return getOriginsSubMode(modeName) === \"Totem\";\n};\n","import { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type { Kingdom } from \"@core/domain/types/kingdom.js\";\nimport type { Player } from \"@core/domain/types/player.js\";\nimport { err, isErr, ok, type Result } from \"@utils/result.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 type { PlayerInput } from \"@application/commands/addPlayersCommand.js\";\nimport {\n isAgeOfGiantsMode,\n isAgeOfGiantsQueenDominoMode,\n} from \"@core/domain/entities/ageOfGiantsHelpers.js\";\nimport { STARTING_COINS } from \"@core/domain/entities/economy.js\";\nimport {\n createEmptyKingdom,\n placeCastle,\n} from \"@core/domain/entities/kingdom.js\";\nimport {\n isOriginsMode,\n isResourceMode,\n isTribeMode,\n} from \"@core/domain/entities/originsHelpers.js\";\nimport { createPlayer } from \"@core/domain/entities/player.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.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 { err, isErr, ok, type Result } from \"@utils/result.js\";\nimport { createSeededShuffle } from \"@utils/seededShuffle.js\";\n\nexport type AddPlayersUseCase = (\n game: GameWithNextStep,\n players: PlayerInput[],\n) => Result<GameWithNextStep>;\n\nconst normalizePlayerInput = (\n input: PlayerInput,\n): { id?: string; name: string; bot?: { strategyName: string } } => {\n if (typeof input === \"string\") {\n return { name: input };\n }\n return { id: input.id, name: input.name, bot: input.bot };\n};\n\n/**\n * Caller-provided ids must be non-empty strings, unique within the call.\n */\nconst hasValidPlayerIds = (players: PlayerInput[]): boolean => {\n const seen = new Set<string>();\n for (const player of players) {\n if (typeof player === \"string\" || player.id === undefined) continue;\n if (typeof player.id !== \"string\" || player.id.trim().length === 0) {\n return false;\n }\n if (seen.has(player.id)) return false;\n seen.add(player.id);\n }\n return true;\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 const isAoG = isAgeOfGiantsMode(game.mode.name);\n const maxPlayers = isAoG ? 5 : 4;\n const minPlayers = isAoG ? 2 : 1;\n\n if (\n !players ||\n players.length < minPlayers ||\n players.length > maxPlayers\n ) {\n return err(ErrorCode.INVALID_PLAYER_COUNT);\n }\n\n if (!hasValidPlayerIds(players)) {\n return err(ErrorCode.INVALID_PLAYER_ID);\n }\n\n const newPlayers: Players = [];\n\n for (const player of players) {\n const { id: providedId, name, bot } = normalizePlayerInput(player);\n let kingdom = createEmptyKingdom();\n kingdom = placeCastle(kingdom);\n const id = providedId ?? uuidMethod();\n const newPlayer = createPlayer(name, id, kingdom, bot);\n\n if (isErr(newPlayer)) {\n return newPlayer;\n }\n\n // Initialize Queendomino-specific player state\n if (game.mode.name === \"QueenDomino\") {\n newPlayer.value.coins = STARTING_COINS;\n newPlayer.value.towers = 0;\n newPlayer.value.knights = [];\n newPlayer.value.buildings = [];\n }\n\n // Initialize Age of Giants-specific player state\n if (isAoG) {\n newPlayer.value.giants = [];\n // AoG-QueenDomino also needs Queendomino player state\n if (isAgeOfGiantsQueenDominoMode(game.mode.name)) {\n newPlayer.value.coins = STARTING_COINS;\n newPlayer.value.towers = 0;\n newPlayer.value.knights = [];\n newPlayer.value.buildings = [];\n }\n }\n\n // Initialize Origins-specific player state\n if (isOriginsMode(game.mode.name)) {\n newPlayer.value.fireTokens = [];\n if (isResourceMode(game.mode.name)) {\n newPlayer.value.resources = [];\n }\n if (isTribeMode(game.mode.name)) {\n newPlayer.value.cavemen = [];\n }\n }\n\n newPlayers.push(newPlayer.value);\n }\n\n // set rules\n const rules = ruleRepository.getAll();\n const basicRules =\n isAoG && rules.aogBasic\n ? rules.aogBasic[newPlayers.length]\n : 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, Position } from \"@core/domain/types/kingdom.js\";\nimport type {\n CaveBoard,\n CavemanTile,\n PlacedCaveman,\n PlacedFireToken,\n Resource,\n ResourceType,\n} from \"@core/domain/types/origins.js\";\nimport type { ShuffleMethod } from \"@core/portServerside/shuffleMethod.js\";\n\nconst CAVE_BOARD_VISIBLE = 4;\n\n// ─── Cave Board Management ──────────────────────────────────────────\n\n/**\n * Creates a cave board from a list of caveman tiles.\n * Shuffles the tiles, reveals 4, and puts the rest in the draw pile.\n */\nexport const createCaveBoard = (\n tiles: CavemanTile[],\n shuffle: ShuffleMethod,\n): CaveBoard => {\n const shuffled = shuffle(tiles);\n return {\n visible: shuffled.slice(0, CAVE_BOARD_VISIBLE),\n drawPile: shuffled.slice(CAVE_BOARD_VISIBLE),\n };\n};\n\n/**\n * Takes a caveman from the visible slots and refills from draw pile.\n */\nexport const takeCavemanFromVisible = (\n board: CaveBoard,\n cavemanId: number,\n): { caveman: CavemanTile; updatedBoard: CaveBoard } | undefined => {\n const index = board.visible.findIndex((c) => c.id === cavemanId);\n if (index === -1) return undefined;\n\n const caveman = board.visible[index]!;\n const newVisible = [...board.visible];\n newVisible.splice(index, 1);\n\n // Refill from draw pile\n const newDrawPile = [...board.drawPile];\n if (newDrawPile.length > 0) {\n newVisible.push(newDrawPile.shift()!);\n }\n\n return {\n caveman,\n updatedBoard: { visible: newVisible, drawPile: newDrawPile },\n };\n};\n\n/**\n * Takes a caveman from the draw pile (face-down, player's choice).\n */\nexport const takeCavemanFromDrawPile = (\n board: CaveBoard,\n cavemanId: number,\n): { caveman: CavemanTile; updatedBoard: CaveBoard } | undefined => {\n const index = board.drawPile.findIndex((c) => c.id === cavemanId);\n if (index === -1) return undefined;\n\n const caveman = board.drawPile[index]!;\n const newDrawPile = [...board.drawPile];\n newDrawPile.splice(index, 1);\n\n return {\n caveman,\n updatedBoard: { visible: [...board.visible], drawPile: newDrawPile },\n };\n};\n\n// ─── Recruitment Cost ────────────────────────────────────────────────\n\n/**\n * Price of recruiting one caveman of the cave board.\n */\nexport type RecruitmentCost = {\n /** Where the caveman is taken from */\n source: \"visible\" | \"drawPile\";\n /** Number of resources to spend */\n resourceCount: number;\n /** Number of different resource types among the spent resources */\n differentTypes: number;\n};\n\n/**\n * Returns the cost of recruiting `cavemanId`: 2 different resources for a\n * visible caveman, 4 different resources for one taken from the draw pile.\n * Returns undefined when the caveman is not on the cave board.\n */\nexport const getRecruitmentCost = (\n board: CaveBoard,\n cavemanId: number,\n): RecruitmentCost | undefined => {\n if (board.visible.some((c) => c.id === cavemanId)) {\n return { source: \"visible\", resourceCount: 2, differentTypes: 2 };\n }\n if (board.drawPile.some((c) => c.id === cavemanId)) {\n return { source: \"drawPile\", resourceCount: 4, differentTypes: 4 };\n }\n return undefined;\n};\n\n// ─── Caveman Placement ───────────────────────────────────────────────\n\n/**\n * Checks if a position is valid for placing a caveman.\n * Must be on a placed tile with: no fire symbol, no fire token, no resource.\n */\nexport const isValidCavemanPosition = (\n kingdom: Kingdom,\n position: Position,\n fireTokens: PlacedFireToken[],\n resources: Resource[],\n cavemen: PlacedCaveman[],\n): boolean => {\n const tile = kingdom[position.y]?.[position.x];\n if (!tile) return false;\n if (tile.type === \"empty\" || tile.type === \"castle\") return false;\n\n // No fire symbols on tile\n if (tile.crowns > 0) return false;\n\n // No fire token at position\n if (\n fireTokens.some(\n (ft) => ft.position.x === position.x && ft.position.y === position.y,\n )\n )\n return false;\n\n // No resource at position\n if (\n resources.some(\n (r) => r.position.x === position.x && r.position.y === position.y,\n )\n )\n return false;\n\n // No existing caveman at position\n if (\n cavemen.some(\n (c) => c.position.x === position.x && c.position.y === position.y,\n )\n )\n return false;\n\n return true;\n};\n\n// ─── Caveman Scoring ─────────────────────────────────────────────────\n\n/**\n * All 8 directions (including diagonals) for adjacent resource counting.\n */\nconst EIGHT_DIRECTIONS = [\n [-1, -1],\n [-1, 0],\n [-1, 1],\n [0, -1],\n [0, 1],\n [1, -1],\n [1, 0],\n [1, 1],\n];\n\n/**\n * Calculates the score for a single hunter-gatherer based on surrounding resources/fire.\n */\nexport const calculateHunterGathererScore = (\n caveman: PlacedCaveman,\n kingdom: Kingdom,\n resources: Resource[],\n fireTokens: PlacedFireToken[],\n): number => {\n if (caveman.caveman.kind !== \"hunterGatherer\") return 0;\n\n const { hunterType, pointsPerMatch } = caveman.caveman;\n const { x, y } = caveman.position;\n let matches = 0;\n\n for (const [dx, dy] of EIGHT_DIRECTIONS) {\n const nx = x + (dx as number);\n const ny = y + (dy as number);\n\n switch (hunterType) {\n case \"mammothHunter\":\n if (\n resources.some(\n (r) =>\n r.position.x === nx &&\n r.position.y === ny &&\n r.type === \"mammoth\",\n )\n )\n matches++;\n break;\n case \"fisherman\":\n if (\n resources.some(\n (r) =>\n r.position.x === nx && r.position.y === ny && r.type === \"fish\",\n )\n )\n matches++;\n break;\n case \"mushroomPicker\":\n if (\n resources.some(\n (r) =>\n r.position.x === nx &&\n r.position.y === ny &&\n r.type === \"mushroom\",\n )\n )\n matches++;\n break;\n case \"flintCollector\":\n if (\n resources.some(\n (r) =>\n r.position.x === nx && r.position.y === ny && r.type === \"flint\",\n )\n )\n matches++;\n break;\n case \"trapper\": {\n // Count unique resource types adjacent\n const adjacentTypes = new Set<ResourceType>();\n for (const r of resources) {\n if (r.position.x === nx && r.position.y === ny) {\n adjacentTypes.add(r.type);\n }\n }\n matches += adjacentTypes.size;\n break;\n }\n case \"gatherer\":\n // Count all resources adjacent (any type)\n if (resources.some((r) => r.position.x === nx && r.position.y === ny))\n matches++;\n break;\n case \"fireLady\": {\n // Count fire symbols (on tiles + fire tokens)\n const tile = kingdom[ny]?.[nx];\n if (tile && tile.type !== \"empty\") {\n matches += tile.crowns;\n }\n if (\n fireTokens.some((ft) => ft.position.x === nx && ft.position.y === ny)\n ) {\n const token = fireTokens.find(\n (ft) => ft.position.x === nx && ft.position.y === ny,\n );\n if (token) matches += token.fires;\n }\n break;\n }\n }\n }\n\n return matches * pointsPerMatch;\n};\n\n/**\n * Calculates warrior group scoring.\n * Groups are connected warrior tiles (perpendicular only).\n * Score per group = number_of_warriors × total_power.\n */\nexport const calculateWarriorGroupScore = (\n cavemen: PlacedCaveman[],\n): number => {\n const warriors = cavemen.filter((c) => c.caveman.kind === \"warrior\");\n if (warriors.length === 0) return 0;\n\n const visited = new Set<string>();\n let totalScore = 0;\n\n const directions = [\n [-1, 0],\n [1, 0],\n [0, -1],\n [0, 1],\n ];\n\n for (const warrior of warriors) {\n const key = `${warrior.position.x},${warrior.position.y}`;\n if (visited.has(key)) continue;\n\n // BFS to find connected group\n let groupSize = 0;\n let groupPower = 0;\n const queue: PlacedCaveman[] = [warrior];\n visited.add(key);\n\n while (queue.length > 0) {\n const current = queue.pop()!;\n groupSize++;\n if (current.caveman.kind === \"warrior\") {\n groupPower += current.caveman.power;\n }\n\n for (const [dx, dy] of directions) {\n const nx = current.position.x + (dx as number);\n const ny = current.position.y + (dy as number);\n const nKey = `${nx},${ny}`;\n\n if (!visited.has(nKey)) {\n const neighbor = warriors.find(\n (w) => w.position.x === nx && w.position.y === ny,\n );\n if (neighbor) {\n visited.add(nKey);\n queue.push(neighbor);\n }\n }\n }\n }\n\n totalScore += groupSize * groupPower;\n }\n\n return totalScore;\n};\n\n/**\n * Calculates the total caveman bonus score for Tribe mode.\n */\nexport const calculateTribeCavemanScore = (\n cavemen: PlacedCaveman[],\n kingdom: Kingdom,\n resources: Resource[],\n fireTokens: PlacedFireToken[],\n): number => {\n let totalScore = 0;\n\n // Hunter-gatherer scores\n for (const caveman of cavemen) {\n if (caveman.caveman.kind === \"hunterGatherer\") {\n totalScore += calculateHunterGathererScore(\n caveman,\n kingdom,\n resources,\n fireTokens,\n );\n }\n }\n\n // Warrior group scores\n totalScore += calculateWarriorGroupScore(cavemen);\n\n return totalScore;\n};\n","import type { Kingdom } from \"@core/domain/types/kingdom.js\";\nimport type { PlacedFireToken } from \"@core/domain/types/origins.js\";\n\n/**\n * Calculates the fire token bonus for Origins scoring.\n *\n * For each region in the kingdom, fire tokens placed within that region\n * contribute their fire value as additional multiplier.\n * The bonus is: for each region, fire_tokens_in_region × region_size.\n *\n * This is added on top of the base score (which already accounts for\n * fire symbols printed on tiles via the crowns field).\n */\nexport const calculateOriginsFireBonus = (\n kingdom: Kingdom,\n placedFireTokens: PlacedFireToken[],\n): number => {\n if (placedFireTokens.length === 0) return 0;\n\n const rows = kingdom.length;\n const cols = kingdom[0]!.length;\n const visited: boolean[][] = kingdom.map((row) => row.map(() => false));\n\n const directions = [\n [-1, 0],\n [1, 0],\n [0, -1],\n [0, 1],\n ];\n\n // Build a map of fire token positions to fire values\n const tokenMap = new Map<string, number>();\n for (const token of placedFireTokens) {\n const key = `${token.position.x},${token.position.y}`;\n tokenMap.set(key, (tokenMap.get(key) ?? 0) + token.fires);\n }\n\n let totalBonus = 0;\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 (\n visited[y]![x] ||\n tile.type === \"empty\" ||\n tile.type === \"castle\" ||\n tile.type === \"volcano\"\n ) {\n continue;\n }\n\n // BFS flood-fill for this region\n const type = tile.type;\n let size = 0;\n let fireTokenFires = 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 size++;\n\n // Check for fire token at this position\n const key = `${cx},${cy}`;\n if (tokenMap.has(key)) {\n fireTokenFires += tokenMap.get(key)!;\n }\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 // Fire token bonus for this region: size × fire_token_fires\n totalBonus += size * fireTokenFires;\n }\n }\n\n return totalBonus;\n};\n","import type { PlacedBuilding } from \"@core/domain/types/building.js\";\nimport type { Kingdom, Position } from \"@core/domain/types/kingdom.js\";\nimport type { Player } from \"@core/domain/types/player.js\";\nimport { getTowerCount } from \"./economy.js\";\n\n/**\n * Determine which player should hold the Queen.\n * The player with the most towers gets the Queen.\n * If tied, the Queen doesn't move (returns current holder).\n */\nexport const determineQueenHolder = (\n players: Player[],\n currentHolderId: string | null,\n): string | null => {\n let maxTowers = 0;\n let leaderId: string | null = null;\n let isTied = false;\n\n for (const player of players) {\n const towers = getTowerCount(player);\n if (towers > maxTowers) {\n maxTowers = towers;\n leaderId = player.id;\n isTied = false;\n } else if (towers === maxTowers && towers > 0 && leaderId !== null) {\n isTied = true;\n }\n }\n\n if (isTied || maxTowers === 0) {\n return currentHolderId;\n }\n\n return leaderId;\n};\n\ntype Property = {\n size: number;\n crowns: number;\n};\n\n/**\n * Find all properties (contiguous territories) in a kingdom using BFS.\n * Returns array of { size, crowns } for each property.\n */\nconst findProperties = (kingdom: Kingdom): Property[] => {\n const rows = kingdom.length;\n const cols = kingdom[0]?.length ?? 0;\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 const terrainType = 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 === terrainType\n ) {\n visited[ny]![nx] = true;\n queue.push([nx, ny]);\n }\n }\n }\n\n properties.push({ size, crowns });\n }\n }\n\n return properties;\n};\n\n/**\n * Calculate the Queen bonus.\n *\n * Official Queendomino rule (Blue Orange rulebook, \"End of the Game\"): the\n * player hosting the Queen places her on their **largest territory** (the one\n * with the most connecting squares) where she counts as an extra crown.\n *\n * Adding 1 crown to a territory of `size` squares and `crowns` crowns changes\n * its score from `size * crowns` to `size * (crowns + 1)`: the bonus is always\n * the territory size, even when that territory had no crown.\n *\n * Returns the additional points the Queen grants (0 for an empty kingdom).\n */\nexport const getQueenBonus = (kingdom: Kingdom): number => {\n const properties = findProperties(kingdom);\n let largest = 0;\n for (const prop of properties) {\n if (prop.size > largest) {\n largest = prop.size;\n }\n }\n return largest;\n};\n\n/**\n * End-game scoring of one building constructed in a player's kingdom\n * (0 for a building without end-game scoring).\n */\nexport const calculateBuildingEndGameScore = (\n placed: PlacedBuilding,\n player: Player,\n): number => {\n const scoring = placed.building.endGameScoring;\n if (!scoring) return 0;\n\n switch (scoring.type) {\n case \"flat\":\n return scoring.points;\n case \"perBuilding\":\n return (player.buildings ?? []).length * scoring.points;\n case \"perTower\":\n return getTowerCount(player) * scoring.points;\n case \"perCrown\": {\n const totalCrowns = countKingdomCrowns(\n player.kingdom,\n (player.giants ?? []).map((g) => g.position),\n );\n return totalCrowns * scoring.points;\n }\n case \"perTerrain\":\n return scoring.terrain\n ? countTerrainTiles(player.kingdom, scoring.terrain) * scoring.points\n : 0;\n default:\n return 0;\n }\n};\n\n/**\n * Calculate end-game building bonus points for a player.\n */\nexport const calculateBuildingEndGameBonus = (player: Player): number =>\n (player.buildings ?? []).reduce(\n (bonus, placed) => bonus + calculateBuildingEndGameScore(placed, player),\n 0,\n );\n\n/**\n * Total crowns in a kingdom. Crowns covered by a giant (Age of Giants +\n * Queendomino) do not count, consistently with territory scoring.\n */\nconst countKingdomCrowns = (\n kingdom: Kingdom,\n giantPositions: Position[] = [],\n): number => {\n const covered = new Set(giantPositions.map((p) => `${p.x},${p.y}`));\n let total = 0;\n for (let y = 0; y < kingdom.length; y++) {\n const row = kingdom[y]!;\n for (let x = 0; x < row.length; x++) {\n const tile = row[x]!;\n if (tile.type !== \"empty\" && tile.type !== \"castle\") {\n total += covered.has(`${x},${y}`)\n ? Math.max(0, tile.crowns - 1)\n : tile.crowns;\n }\n }\n }\n return total;\n};\n\n/**\n * End-game Queendomino bonus for one player: Queen bonus (if the player hosts\n * the Queen at the end of the game) plus the end-game scoring of every\n * building constructed in their kingdom.\n */\nexport const calculateQueenDominoEndGameBonus = (\n player: Player,\n queenHolderId: string | null,\n): number => {\n const queenBonus =\n queenHolderId !== null && queenHolderId === player.id\n ? getQueenBonus(player.kingdom)\n : 0;\n return queenBonus + calculateBuildingEndGameBonus(player);\n};\n\nconst countTerrainTiles = (kingdom: Kingdom, terrain: string): number => {\n let count = 0;\n for (const row of kingdom) {\n for (const tile of row) {\n if (tile.type === terrain) {\n count++;\n }\n }\n }\n return count;\n};\n","import type { PlacedGiant, QuestTile } from \"@core/domain/types/ageOfGiants.js\";\nimport { questTypes } from \"@core/domain/types/ageOfGiants.js\";\nimport type { Ground } from \"@core/domain/types/domino.js\";\nimport type { Kingdom } from \"@core/domain/types/kingdom.js\";\nimport { checkCastleIsInMiddle, countDominoes } from \"./kingdom.js\";\n\n/**\n * Finds the castle position in the kingdom.\n */\nconst findCastlePosition = (\n kingdom: Kingdom,\n): { x: number; y: number } | undefined => {\n for (let y = 0; y < kingdom.length; y++) {\n const row = kingdom[y]!;\n for (let x = 0; x < row.length; x++) {\n if (row[x]!.type === \"castle\") {\n return { x, y };\n }\n }\n }\n return undefined;\n};\n\n/**\n * Gets the bounding box of non-empty tiles in the kingdom.\n */\nconst getBoundingBox = (\n kingdom: Kingdom,\n): { minX: number; minY: number; maxX: number; maxY: number } | undefined => {\n let minX = Number.MAX_SAFE_INTEGER;\n let minY = Number.MAX_SAFE_INTEGER;\n let maxX = -1;\n let maxY = -1;\n\n for (let y = 0; y < kingdom.length; y++) {\n const row = kingdom[y]!;\n for (let x = 0; x < row.length; x++) {\n if (row[x]!.type !== \"empty\") {\n minX = Math.min(minX, x);\n minY = Math.min(minY, y);\n maxX = Math.max(maxX, x);\n maxY = Math.max(maxY, y);\n }\n }\n }\n\n if (maxX === -1) return undefined;\n return { minX, minY, maxX, maxY };\n};\n\n/**\n * Local Trade: 5pts per matching terrain tile adjacent (8-dir) to castle.\n */\nexport const calculateLocalTradeBonus = (\n kingdom: Kingdom,\n terrain: Ground,\n pointsPerMatch: number,\n): number => {\n const castle = findCastlePosition(kingdom);\n if (!castle) return 0;\n\n const directions = [\n [-1, -1],\n [-1, 0],\n [-1, 1],\n [0, -1],\n [0, 1],\n [1, -1],\n [1, 0],\n [1, 1],\n ];\n\n let count = 0;\n for (const [dy, dx] of directions) {\n const ny = castle.y + (dy as number);\n const nx = castle.x + (dx as number);\n const tile = kingdom[ny]?.[nx];\n if (tile && tile.type === terrain) {\n count++;\n }\n }\n\n return count * pointsPerMatch;\n};\n\n/**\n * Kingdom Borders: 5pts per matching terrain tile in the 4 corners of the kingdom bounding box.\n */\nexport const calculateKingdomBordersBonus = (\n kingdom: Kingdom,\n terrain: Ground,\n pointsPerMatch: number,\n): number => {\n const box = getBoundingBox(kingdom);\n if (!box) return 0;\n\n const corners = [\n { x: box.minX, y: box.minY },\n { x: box.maxX, y: box.minY },\n { x: box.minX, y: box.maxY },\n { x: box.maxX, y: box.maxY },\n ];\n\n let count = 0;\n for (const corner of corners) {\n const tile = kingdom[corner.y]?.[corner.x];\n if (tile && tile.type === terrain) {\n count++;\n }\n }\n\n return count * pointsPerMatch;\n};\n\n/**\n * Lost Corner: 20pts if castle is in one of the 4 corners of the kingdom bounding box.\n */\nexport const calculateLostCornerBonus = (\n kingdom: Kingdom,\n points: number,\n): number => {\n const castle = findCastlePosition(kingdom);\n if (!castle) return 0;\n\n const box = getBoundingBox(kingdom);\n if (!box) return 0;\n\n const isCorner =\n (castle.x === box.minX && castle.y === box.minY) ||\n (castle.x === box.maxX && castle.y === box.minY) ||\n (castle.x === box.minX && castle.y === box.maxY) ||\n (castle.x === box.maxX && castle.y === box.maxY);\n\n return isCorner ? points : 0;\n};\n\n/**\n * Megalomania: 10pts per alignment of 3+ tiles with uncovered crowns (H/V/diagonal).\n * Giants cover crowns, so we skip positions covered by giants.\n */\nexport const calculateMegalomaniaBonus = (\n kingdom: Kingdom,\n giants: PlacedGiant[],\n points: number,\n): number => {\n const rows = kingdom.length;\n const cols = kingdom[0]!.length;\n\n // Build a boolean grid: true if tile has uncovered crown\n const hasCrown: boolean[][] = Array.from({ length: rows }, () =>\n Array.from({ length: cols }, () => false),\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 (tile.type !== \"empty\" && tile.type !== \"castle\" && tile.crowns > 0) {\n const coveredByGiant = giants.some(\n (g) => g.position.x === x && g.position.y === y,\n );\n if (!coveredByGiant) {\n hasCrown[y]![x] = true;\n }\n }\n }\n }\n\n let alignments = 0;\n\n // Directions: horizontal (1,0), vertical (0,1), diagonal (1,1), anti-diagonal (1,-1)\n const directions = [\n { dx: 1, dy: 0 }, // horizontal\n { dx: 0, dy: 1 }, // vertical\n { dx: 1, dy: 1 }, // diagonal\n { dx: 1, dy: -1 }, // anti-diagonal\n ];\n\n for (const { dx, dy } of directions) {\n // Track which cells have been counted in a run for this direction\n const counted: boolean[][] = Array.from({ length: rows }, () =>\n Array.from({ length: cols }, () => false),\n );\n\n for (let y = 0; y < rows; y++) {\n for (let x = 0; x < cols; x++) {\n if (counted[y]![x] || !hasCrown[y]![x]) continue;\n\n // Count consecutive crowns in this direction\n let length = 0;\n let cx = x;\n let cy = y;\n while (\n cx >= 0 &&\n cx < cols &&\n cy >= 0 &&\n cy < rows &&\n hasCrown[cy]![cx]\n ) {\n counted[cy]![cx] = true;\n length++;\n cx += dx;\n cy += dy;\n }\n\n if (length >= 3) {\n alignments++;\n }\n }\n }\n }\n\n return alignments * points;\n};\n\n/**\n * Austere King: 10pts per property of 5+ wheat/forest/sea/plain tiles with 0 crowns.\n */\nexport const calculateAustereKingBonus = (\n kingdom: Kingdom,\n points: number,\n): number => {\n const eligibleTerrains: Ground[] = [\"wheat\", \"forest\", \"sea\", \"plain\"];\n const rows = kingdom.length;\n const cols = kingdom[0]!.length;\n const visited: boolean[][] = Array.from({ length: rows }, () =>\n Array.from({ length: cols }, () => false),\n );\n\n const directions = [\n [-1, 0],\n [1, 0],\n [0, -1],\n [0, 1],\n ];\n\n let qualifyingProperties = 0;\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] || !eligibleTerrains.includes(tile.type as Ground))\n continue;\n if (tile.type === \"empty\" || tile.type === \"castle\") continue;\n\n // BFS for this property\n const type = tile.type;\n let size = 0;\n let hasAnyCrown = false;\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 if (current.crowns > 0) hasAnyCrown = true;\n\n for (const [dy, dx] 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 if (size >= 5 && !hasAnyCrown) {\n qualifyingProperties++;\n }\n }\n }\n\n return qualifyingProperties * points;\n};\n\n/**\n * Calculates the bonus for a single quest tile.\n * @param dominoesPerPlayer - Dominoes each player receives over the game\n * (lords per player x turns); used by the harmony quest.\n */\nexport const calculateQuestBonus = (\n quest: QuestTile,\n kingdom: Kingdom,\n giants: PlacedGiant[],\n dominoesPerPlayer: number,\n): number => {\n switch (quest.type) {\n case questTypes.localTrade:\n return calculateLocalTradeBonus(kingdom, quest.terrain!, quest.points);\n\n case questTypes.kingdomBorders:\n return calculateKingdomBordersBonus(\n kingdom,\n quest.terrain!,\n quest.points,\n );\n\n case questTypes.harmony: {\n // Complete kingdom: every received domino was placed (none discarded)\n const totalDominoes = countDominoes(kingdom);\n return totalDominoes === dominoesPerPlayer ? quest.points : 0;\n }\n\n case questTypes.middleKingdom:\n return checkCastleIsInMiddle(kingdom) ? quest.points : 0;\n\n case questTypes.lostCorner:\n return calculateLostCornerBonus(kingdom, quest.points);\n\n case questTypes.megalomania:\n return calculateMegalomaniaBonus(kingdom, giants, quest.points);\n\n case questTypes.austereKing:\n return calculateAustereKingBonus(kingdom, quest.points);\n\n default:\n return 0;\n }\n};\n","import type { Ground, Tile } from \"@core/domain/types/domino.js\";\nimport type { Position } from \"@core/domain/types/kingdom.js\";\nimport type { Resource, ResourceType } from \"@core/domain/types/origins.js\";\n\n/**\n * Maps terrain types to their corresponding resource type.\n * Returns null for terrains that don't produce resources.\n */\nexport const terrainToResource = (terrain: Ground): ResourceType | null => {\n switch (terrain) {\n case \"grassland\":\n return \"mammoth\";\n case \"lake\":\n return \"fish\";\n case \"jungle\":\n return \"mushroom\";\n case \"quarry\":\n return \"flint\";\n default:\n return null;\n }\n};\n\n/**\n * Checks whether a tile should receive a wooden resource.\n * A tile gets a resource if it has a resource-eligible terrain AND no fire symbols.\n */\nexport const shouldHaveResource = (tile: Tile): boolean => {\n const resourceType = terrainToResource(tile.type);\n return resourceType !== null && tile.crowns === 0;\n};\n\n/**\n * Creates a resource for a tile at the given position, if applicable.\n */\nexport const createResourceForTile = (\n tile: Tile,\n position: Position,\n): Resource | null => {\n const resourceType = terrainToResource(tile.type);\n if (resourceType === null || tile.crowns > 0) return null;\n return { type: resourceType, position };\n};\n\n/**\n * Destroys a resource at a given position (e.g., from fire token impact).\n * Returns the updated resources array.\n */\nexport const destroyResourceAtPosition = (\n resources: Resource[],\n position: Position,\n): Resource[] => {\n return resources.filter(\n (r) => !(r.position.x === position.x && r.position.y === position.y),\n );\n};\n\n/**\n * Counts resources by type for a player's resource list.\n */\nexport const countResourcesByType = (\n resources: Resource[],\n): Record<ResourceType, number> => {\n const counts: Record<ResourceType, number> = {\n mammoth: 0,\n fish: 0,\n mushroom: 0,\n flint: 0,\n };\n for (const r of resources) {\n counts[r.type]++;\n }\n return counts;\n};\n\n/**\n * Checks if a player has at least the required resources to spend.\n * @param resources - Player's current resources\n * @param positions - Positions of resources to spend\n * @param requiredDifferentTypes - How many different types are required\n */\nexport const canSpendResources = (\n resources: Resource[],\n positions: Position[],\n requiredDifferentTypes: number,\n): boolean => {\n const toSpend = positions.map((pos) =>\n resources.find((r) => r.position.x === pos.x && r.position.y === pos.y),\n );\n\n // All positions must have a resource\n if (toSpend.some((r) => r === undefined)) return false;\n\n // Must have the required number of different types\n const types = new Set(toSpend.map((r) => r!.type));\n return types.size >= requiredDifferentTypes;\n};\n\n/**\n * Whether `positions` is a valid payment: exactly `count` resources of the\n * player, with at least `requiredDifferentTypes` different types.\n */\nexport const isValidResourcePayment = (\n resources: Resource[],\n positions: Position[],\n count: number,\n requiredDifferentTypes: number,\n): boolean =>\n positions.length === count &&\n canSpendResources(resources, positions, requiredDifferentTypes);\n\n/**\n * Lists every valid payment (see `isValidResourcePayment`) as the positions of\n * the resources to spend, each combination listed once in `resources` order.\n *\n * Combinations are enumerated exhaustively; a branch is only cut when it can\n * no longer reach `requiredDifferentTypes` (each extra resource adds at most\n * one new type), and every combination is confirmed by `isValidResourcePayment`.\n */\nexport const getValidResourcePayments = (\n resources: Resource[],\n count: number,\n requiredDifferentTypes: number,\n): Position[][] => {\n const payments: Position[][] = [];\n const chosen: Resource[] = [];\n\n const explore = (start: number): void => {\n if (chosen.length === count) {\n const positions = chosen.map((r) => r.position);\n if (\n isValidResourcePayment(\n resources,\n positions,\n count,\n requiredDifferentTypes,\n )\n ) {\n payments.push(positions);\n }\n return;\n }\n const reachableTypes =\n new Set(chosen.map((r) => r.type)).size + (count - chosen.length);\n if (reachableTypes < requiredDifferentTypes) return;\n\n for (let i = start; i <= resources.length - (count - chosen.length); i++) {\n chosen.push(resources[i]!);\n explore(i + 1);\n chosen.pop();\n }\n };\n\n if (count > 0) explore(0);\n return payments;\n};\n\n/**\n * Removes resources at the given positions.\n */\nexport const spendResources = (\n resources: Resource[],\n positions: Position[],\n): Resource[] => {\n const posSet = new Set(positions.map((p) => `${p.x},${p.y}`));\n return resources.filter(\n (r) => !posSet.has(`${r.position.x},${r.position.y}`),\n );\n};\n","import type {\n OriginsState,\n ResourceType,\n TotemState,\n} from \"@core/domain/types/origins.js\";\nimport type { Player } from \"@core/domain/types/player.js\";\nimport { countResourcesByType } from \"./resource.js\";\n\n/**\n * Bonus points for holding each totem at end of game.\n * Values from the Kingdomino Origins rules.\n */\nexport const TOTEM_BONUSES: Record<ResourceType, number> = {\n mammoth: 3,\n fish: 3,\n mushroom: 3,\n flint: 3,\n};\n\nconst RESOURCE_TYPES: ResourceType[] = [\"mammoth\", \"fish\", \"mushroom\", \"flint\"];\n\n/**\n * Determines which player holds each totem based on resource majority.\n *\n * Official rules (Kingdomino Origins, Totem mode):\n * - a player takes a totem when they have the majority (\"the highest amount\n * only\") of the corresponding resource, i.e. strictly more than every\n * other player;\n * - when the holder loses the majority (another player collects resources,\n * or a fire destroys some), the totem goes to the new majority holder;\n * - on a tie for the majority the holder chooses who gets it: the engine\n * keeps it with the current holder when they are among the tied players,\n * otherwise gives it to the first tied player in player order.\n * A totem nobody holds stays unclaimed while the majority is tied.\n */\nexport const determineTotemHolders = (\n players: Player[],\n currentTotems: TotemState,\n): TotemState => {\n const result: TotemState = { ...currentTotems };\n\n for (const resourceType of RESOURCE_TYPES) {\n const counts = players.map(\n (player) => countResourcesByType(player.resources ?? [])[resourceType],\n );\n const maxCount = Math.max(0, ...counts);\n const leaders = players.filter((_, index) => counts[index] === maxCount);\n const holder = result[resourceType];\n\n if (maxCount === 0) {\n // No one has this resource - totem stays unclaimed\n result[resourceType] = null;\n } else if (leaders.length === 1) {\n // Strict majority\n result[resourceType] = leaders[0]!.id;\n } else if (holder !== null && leaders.some((p) => p.id === holder)) {\n // Tie including the current holder: they keep it\n result[resourceType] = holder;\n } else if (holder !== null && players.some((p) => p.id === holder)) {\n // The holder lost the majority to tied players: pass it to one of them\n result[resourceType] = leaders[0]!.id;\n } else {\n // Unclaimed totem and tied majority: nobody takes it\n result[resourceType] = null;\n }\n }\n\n return result;\n};\n\n/**\n * Re-evaluates the totem holders of an Origins state (Totem mode only).\n * States without totems are returned unchanged.\n */\nexport const refreshTotemHolders = (\n origins: OriginsState | undefined,\n players: Player[],\n): OriginsState | undefined => {\n if (!origins?.totems) return origins;\n return {\n ...origins,\n totems: determineTotemHolders(players, origins.totems),\n };\n};\n\n/**\n * Calculates totem scoring for a player in Totem mode:\n * - 1 point per remaining wooden resource\n * - Totem bonus for each totem the player holds\n */\nexport const calculateTotemScore = (\n player: Player,\n totemState: TotemState,\n): number => {\n let score = 0;\n\n // 1 point per remaining resource\n const resources = player.resources ?? [];\n score += resources.length;\n\n // Totem bonuses\n for (const resourceType of RESOURCE_TYPES) {\n if (totemState[resourceType] === player.id) {\n score += TOTEM_BONUSES[resourceType];\n }\n }\n\n return score;\n};\n","/**\n * Mode-aware score breakdown: the single source of truth of every score\n * computed by the engine (`calculatePlayerScore` during and after the game,\n * `getResults` at the end of the game).\n *\n * Live (game in progress) vs final (game over):\n * - territories, Middle Kingdom / Empire of Fire, the Queen (current holder),\n * buildings, fire tokens, resources and totems (current majority holders),\n * cavemen and every quest except Harmony are evaluated on the current state\n * during the game and flagged `provisional: true`;\n * - Harmony, Homo Habilis and the Harmony quest require the complete kingdom\n * (every received domino placed): they are only granted at the end of the\n * game and are left out of the live breakdown.\n */\nimport type { QuestTile } from \"@core/domain/types/ageOfGiants.js\";\nimport { questTypes } from \"@core/domain/types/ageOfGiants.js\";\nimport type { Game } from \"@core/domain/types/game.js\";\nimport type { Kingdom, Position } from \"@core/domain/types/kingdom.js\";\nimport { resourceTypes } from \"@core/domain/types/origins.js\";\nimport type { Player } from \"@core/domain/types/player.js\";\nimport type {\n PlayerScore,\n ScoreBonus,\n ScoreBreakdown,\n ScoreTerritory,\n} from \"@core/domain/types/score.js\";\nimport {\n hunterGathererKindToTranslationKey,\n questTypeToTranslationKey,\n TranslationKey,\n totemToTranslationKey,\n} from \"@core/i18n/translations.js\";\nimport { isAgeOfGiantsMode } from \"./ageOfGiantsHelpers.js\";\nimport {\n calculateHunterGathererScore,\n calculateWarriorGroupScore,\n} from \"./caveman.js\";\nimport { checkCastleIsInMiddle, countDominoes } from \"./kingdom.js\";\nimport { isOriginsMode, isTotemMode, isTribeMode } from \"./originsHelpers.js\";\nimport { calculateOriginsFireBonus } from \"./originsScore.js\";\nimport { calculateBuildingEndGameScore, getQueenBonus } from \"./queen.js\";\nimport { calculateQuestBonus } from \"./questScore.js\";\nimport { determineTotemHolders, TOTEM_BONUSES } from \"./totem.js\";\n\n/** Points of \"The middle Kingdom\" / \"Empire of Fire\" */\nconst MIDDLE_KINGDOM_POINTS = 10;\n/** Points of \"Harmony\" / \"Homo Habilis\" */\nconst HARMONY_POINTS = 5;\n\nconst DIRECTIONS = [\n [-1, 0],\n [1, 0],\n [0, -1],\n [0, 1],\n] as const;\n\n/**\n * Splits a kingdom into its scored territories (orthogonally connected\n * squares of the same terrain, castle excluded). A giant covering a square\n * removes one of its crowns.\n */\nexport const computeTerritories = (\n kingdom: Kingdom,\n giantPositions: Position[] = [],\n): ScoreTerritory[] => {\n const rows = kingdom.length;\n const cols = kingdom[0]?.length ?? 0;\n const visited: boolean[][] = kingdom.map((row) => row.map(() => false));\n const giantSet = new Set(giantPositions.map((p) => `${p.x},${p.y}`));\n const territories: ScoreTerritory[] = [];\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 const terrain = tile.type;\n const cells: Position[] = [];\n let crowns = 0;\n let coveredCrowns = 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 cells.push({ x: cx, y: cy });\n\n const counted = giantSet.has(`${cx},${cy}`)\n ? Math.max(0, current.crowns - 1)\n : current.crowns;\n crowns += counted;\n coveredCrowns += current.crowns - counted;\n\n for (const [dx, dy] of DIRECTIONS) {\n const nx = cx + dx;\n const ny = cy + dy;\n if (\n nx >= 0 &&\n ny >= 0 &&\n nx < cols &&\n ny < rows &&\n !visited[ny]![nx] &&\n kingdom[ny]![nx]!.type === terrain\n ) {\n visited[ny]![nx] = true;\n queue.push([nx, ny]);\n }\n }\n }\n\n cells.sort((a, b) => a.y - b.y || a.x - b.x);\n territories.push({\n terrain,\n cells,\n crowns,\n coveredCrowns,\n points: cells.length * crowns,\n });\n }\n }\n\n return territories;\n};\n\n/**\n * True once the game is over (the `result` step is reached).\n */\nexport const isGameOver = (game: Pick<Game, \"nextAction\">): boolean =>\n game.nextAction.type === \"step\" && game.nextAction.step === \"result\";\n\n/** Every domino a player receives over the game (one per lord and turn). */\nconst dominoesReceivedPerPlayer = (game: Game): number =>\n game.rules.basic.lords * game.rules.basic.maxTurns;\n\nconst queendominoBonuses = (\n game: Game,\n player: Player,\n provisional: boolean,\n): ScoreBonus[] => {\n if (!game.queendomino) return [];\n const bonuses: ScoreBonus[] = [];\n\n // The Queen: extra crown on the largest territory of her host\n if (\n game.queendomino.queenHolderId !== null &&\n game.queendomino.queenHolderId === player.id\n ) {\n bonuses.push({\n type: \"queen\",\n label: TranslationKey.SCORE_QUEEN,\n points: getQueenBonus(player.kingdom),\n provisional,\n });\n }\n\n // Buildings with an end-game scoring condition\n for (const placed of player.buildings ?? []) {\n if (!placed.building.endGameScoring) continue;\n bonuses.push({\n type: \"building\",\n label: TranslationKey.SCORE_BUILDING,\n labelParams: { name: placed.building.name },\n points: calculateBuildingEndGameScore(placed, player),\n provisional,\n buildingId: placed.building.id,\n position: placed.position,\n });\n }\n\n return bonuses;\n};\n\nconst originsBonuses = (\n game: Game,\n player: Player,\n provisional: boolean,\n): ScoreBonus[] => {\n const modeName = game.mode.name;\n if (!isOriginsMode(modeName)) return [];\n const bonuses: ScoreBonus[] = [];\n const fireTokens = player.fireTokens ?? [];\n const resources = player.resources ?? [];\n\n // Fire tokens: each region scores its size × fires of its tokens\n if (fireTokens.length > 0) {\n bonuses.push({\n type: \"fire\",\n label: TranslationKey.SCORE_FIRE,\n points: calculateOriginsFireBonus(player.kingdom, fireTokens),\n provisional,\n });\n }\n\n // Totem mode: 1 point per resource + bonus of every totem held. Holders\n // are re-evaluated from the resource majority of the current state.\n if (isTotemMode(modeName) && game.origins?.totems) {\n bonuses.push({\n type: \"resources\",\n label: TranslationKey.SCORE_RESOURCES,\n points: resources.length,\n provisional,\n });\n\n const holders = determineTotemHolders(game.players, game.origins.totems);\n for (const resource of Object.values(resourceTypes)) {\n if (holders[resource] !== player.id) continue;\n bonuses.push({\n type: \"totem\",\n label: totemToTranslationKey[resource],\n points: TOTEM_BONUSES[resource],\n provisional,\n resource,\n });\n }\n }\n\n // Tribe mode: every hunter-gatherer, then the warrior groups\n const cavemen = player.cavemen ?? [];\n if (isTribeMode(modeName) && cavemen.length > 0) {\n for (const placed of cavemen) {\n const { caveman } = placed;\n if (caveman.kind !== \"hunterGatherer\") continue;\n bonuses.push({\n type: \"hunterGatherer\",\n label: hunterGathererKindToTranslationKey[caveman.hunterType],\n points: calculateHunterGathererScore(\n placed,\n player.kingdom,\n resources,\n fireTokens,\n ),\n provisional,\n cavemanId: caveman.id,\n position: placed.position,\n });\n }\n\n if (cavemen.some((placed) => placed.caveman.kind === \"warrior\")) {\n bonuses.push({\n type: \"warriors\",\n label: TranslationKey.SCORE_WARRIORS,\n points: calculateWarriorGroupScore(cavemen),\n provisional,\n });\n }\n }\n\n return bonuses;\n};\n\nconst questBonuses = (\n game: Game,\n player: Player,\n final: boolean,\n): ScoreBonus[] => {\n if (!isAgeOfGiantsMode(game.mode.name) || !game.ageOfGiants?.questTiles) {\n return [];\n }\n const giants = player.giants ?? [];\n\n return game.ageOfGiants.questTiles\n .filter((quest: QuestTile) => final || quest.type !== questTypes.harmony)\n .map(\n (quest): ScoreBonus => ({\n type: \"quest\",\n label: questTypeToTranslationKey[quest.type],\n points: calculateQuestBonus(\n quest,\n player.kingdom,\n giants,\n dominoesReceivedPerPlayer(game),\n ),\n provisional: !final,\n questId: quest.id,\n questType: quest.type,\n ...(quest.terrain && { terrain: quest.terrain }),\n }),\n );\n};\n\nconst extraRuleBonuses = (\n game: Game,\n player: Player,\n final: boolean,\n): ScoreBonus[] => {\n const bonuses: ScoreBonus[] = [];\n const provisional = !final;\n\n for (const extraRule of game.rules.extra) {\n // Castle in the middle: \"The middle Kingdom\" (Classic/QD) or\n // \"Empire of Fire\" (Origins)\n if (\n extraRule.name === \"The middle Kingdom\" ||\n extraRule.name === \"Empire of Fire\"\n ) {\n const isMiddleKingdom = extraRule.name === \"The middle Kingdom\";\n bonuses.push({\n type: isMiddleKingdom ? \"middleKingdom\" : \"empireOfFire\",\n label: isMiddleKingdom\n ? TranslationKey.RULE_MIDDLE_KINGDOM\n : TranslationKey.RULE_EMPIRE_OF_FIRE,\n points: checkCastleIsInMiddle(player.kingdom)\n ? MIDDLE_KINGDOM_POINTS\n : 0,\n provisional,\n });\n }\n\n // Complete kingdom: \"Harmony\" (Classic/QD) or \"Homo Habilis\" (Origins).\n // Every domino the player received must be in the kingdom (none was\n // discarded): only decidable at the end of the game.\n if (\n final &&\n (extraRule.name === \"Harmony\" || extraRule.name === \"Homo Habilis\")\n ) {\n const isHarmony = extraRule.name === \"Harmony\";\n bonuses.push({\n type: isHarmony ? \"harmony\" : \"homoHabilis\",\n label: isHarmony\n ? TranslationKey.RULE_HARMONY\n : TranslationKey.RULE_HOMO_HABILIS,\n points:\n countDominoes(player.kingdom) === dominoesReceivedPerPlayer(game)\n ? HARMONY_POINTS\n : 0,\n provisional,\n });\n }\n }\n\n return bonuses;\n};\n\nconst sum = (values: { points: number }[]): number =>\n values.reduce((total, value) => total + value.points, 0);\n\n/**\n * Computes the mode-aware score breakdown of one player.\n *\n * @param final - `true` to score the end of the game (end-of-game-only\n * bonuses included, nothing provisional), `false` for a live score.\n */\nexport const computeScoreBreakdown = (\n game: Game,\n player: Player,\n final: boolean,\n): ScoreBreakdown => {\n const territories = computeTerritories(\n player.kingdom,\n player.giants?.map((g) => g.position),\n );\n const provisional = !final;\n\n const bonuses: ScoreBonus[] = [\n ...queendominoBonuses(game, player, provisional),\n ...originsBonuses(game, player, provisional),\n ...questBonuses(game, player, final),\n ...extraRuleBonuses(game, player, final),\n ];\n\n const territoryPoints = sum(territories);\n const bonusPoints = sum(bonuses);\n\n return {\n territories,\n bonuses,\n territoryPoints,\n bonusPoints,\n total: territoryPoints + bonusPoints,\n };\n};\n\n/**\n * Computes the mode-aware score of one player. The score is final when the\n * game is over (`isGameOver`), live otherwise.\n */\nexport const computePlayerScore = (\n game: Game,\n player: Player,\n final: boolean = isGameOver(game),\n): PlayerScore => {\n const breakdown = computeScoreBreakdown(game, player, final);\n const { territories } = breakdown;\n\n return {\n playerId: player.id,\n playerName: player.name,\n points: breakdown.total,\n maxPropertiesSize: territories.reduce(\n (max, territory) => Math.max(max, territory.cells.length),\n 0,\n ),\n totalCrowns: territories.reduce(\n (total, territory) => total + territory.crowns,\n 0,\n ),\n final,\n breakdown,\n };\n};\n","import { computePlayerScore } from \"@core/domain/entities/scoreBreakdown.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type { Game } from \"@core/domain/types/game.js\";\nimport type { PlayerScore } from \"@core/domain/types/score.js\";\nimport { err, ok, type Result } from \"@utils/result.js\";\n\nexport type CalculatePlayerScoreUseCase = (\n game: Game,\n playerId: string,\n) => Result<PlayerScore>;\n\n/**\n * Mode-aware score of one player, with its breakdown. Live during the game,\n * final (identical to `getResults`) once the game is over.\n */\nexport const calculatePlayerScoreUseCase: CalculatePlayerScoreUseCase = (\n game,\n playerId,\n) => {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return err(ErrorCode.PLAYER_NOT_FOUND);\n }\n\n return ok(computePlayerScore(game, player));\n};\n","import { computeTerritories } from \"@core/domain/entities/scoreBreakdown.js\";\nimport type { Kingdom, Position, Score } from \"@core/domain/types/index.js\";\nimport { ok, type Result } from \"@utils/result.js\";\n\nexport type CalculateScoreUseCase = (\n kingdom: Kingdom,\n giantPositions?: Position[],\n) => Result<Score>;\n\n/**\n * Territory score of a kingdom (no mode bonus). Uses the same territory\n * computation as the mode-aware score breakdown (`calculatePlayerScore`).\n */\nexport const calculateScoreUseCase: CalculateScoreUseCase = (\n kingdom,\n giantPositions,\n) => {\n const territories = computeTerritories(kingdom, giantPositions);\n\n let points = 0;\n let maxPropertiesSize = 0;\n let totalCrowns = 0;\n\n for (const territory of territories) {\n points += territory.points;\n maxPropertiesSize = Math.max(maxPropertiesSize, territory.cells.length);\n totalCrowns += territory.crowns;\n }\n\n return ok({\n points,\n maxPropertiesSize,\n totalCrowns,\n });\n};\n","import type {\n BuildersBoard,\n BuildingTile,\n PlacedBuilding,\n} from \"@core/domain/types/building.js\";\nimport type { Kingdom, Position } from \"@core/domain/types/kingdom.js\";\nimport type { Player } from \"@core/domain/types/player.js\";\nimport type { QueenDominoState } from \"@core/domain/types/queendomino.js\";\nimport type { ShuffleMethod } from \"@core/portServerside/shuffleMethod.js\";\nimport {\n addBonusKnights,\n addCoins,\n addTowers,\n canAfford,\n removeCoins,\n} from \"./economy.js\";\n\n/** Number of visible building slots on the Builders Board */\nconst BOARD_SLOTS = 4;\n\nexport const createBuildersBoard = (\n tiles: BuildingTile[],\n shuffle: ShuffleMethod,\n): BuildersBoard => {\n const shuffled = shuffle([...tiles]);\n const slots = shuffled.slice(0, BOARD_SLOTS);\n const drawPile = shuffled.slice(BOARD_SLOTS);\n\n return {\n slots,\n drawPile,\n };\n};\n\n/**\n * Fill every empty slot of the Builders Board from the draw pile (in slot\n * order), as long as the draw pile is not empty.\n */\nexport const refillBuildersBoard = (board: BuildersBoard): BuildersBoard => {\n const newSlots = [...board.slots];\n const newDrawPile = [...board.drawPile];\n\n for (let i = 0; i < newSlots.length; i++) {\n if (newSlots[i] === null && newDrawPile.length > 0) {\n newSlots[i] = newDrawPile.shift()!;\n }\n }\n\n return { slots: newSlots, drawPile: newDrawPile };\n};\n\n/**\n * Prepare the Queendomino state for a new round.\n *\n * Official rule (\"Starting a New Round\"): send the Dragon back to its cave and\n * fill the empty spots of the Builders' Board from the draw pile. Spots emptied\n * by a construction or by the Dragon stay empty for the rest of the round.\n */\nexport const startNewQueenDominoRound = (\n state: QueenDominoState,\n): QueenDominoState => ({\n ...state,\n buildersBoard: refillBuildersBoard(state.buildersBoard),\n dragonUsedThisRound: false,\n});\n\nexport const findBuildingOnBoard = (\n board: BuildersBoard,\n buildingId: number,\n): { building: BuildingTile; slotIndex: number } | null => {\n for (let i = 0; i < board.slots.length; i++) {\n const slot = board.slots[i];\n if (slot && slot.id === buildingId) {\n return { building: slot, slotIndex: i };\n }\n }\n return null;\n};\n\nexport const removeBuildingFromBoard = (\n board: BuildersBoard,\n slotIndex: number,\n): BuildersBoard => {\n const newSlots = [...board.slots];\n newSlots[slotIndex] = null;\n return { ...board, slots: newSlots };\n};\n\nexport const purchaseBuilding = (\n board: BuildersBoard,\n player: Player,\n buildingId: number,\n): {\n updatedBoard: BuildersBoard;\n updatedPlayer: Player;\n building: BuildingTile;\n} | null => {\n const found = findBuildingOnBoard(board, buildingId);\n if (!found) return null;\n\n const { building, slotIndex } = found;\n if (!canAfford(player, building.cost)) return null;\n\n let updatedPlayer = removeCoins(player, building.cost);\n\n // Apply immediate bonus\n if (building.immediateBonus) {\n switch (building.immediateBonus.type) {\n case \"coins\":\n updatedPlayer = addCoins(updatedPlayer, building.immediateBonus.amount);\n break;\n case \"tower\":\n updatedPlayer = addTowers(\n updatedPlayer,\n building.immediateBonus.amount,\n );\n break;\n case \"knight\":\n updatedPlayer = addBonusKnights(\n updatedPlayer,\n building.immediateBonus.amount,\n );\n break;\n }\n }\n\n // Add towers from the building itself\n if (building.towers > 0) {\n updatedPlayer = addTowers(updatedPlayer, building.towers);\n }\n\n const updatedBoard = removeBuildingFromBoard(board, slotIndex);\n\n return { updatedBoard, updatedPlayer, building };\n};\n\nexport const hasOpenConstructionSquare = (\n kingdom: Kingdom,\n placedBuildings: PlacedBuilding[],\n): boolean => {\n const occupiedPositions = new Set(\n placedBuildings.map((b) => `${b.position.x},${b.position.y}`),\n );\n\n for (let y = 0; y < kingdom.length; y++) {\n const row = kingdom[y]!;\n for (let x = 0; x < row.length; x++) {\n const tile = row[x]!;\n if (\n tile.type !== \"empty\" &&\n tile.type !== \"castle\" &&\n \"hasConstructionSquare\" in tile &&\n tile.hasConstructionSquare &&\n !occupiedPositions.has(`${x},${y}`)\n ) {\n return true;\n }\n }\n }\n return false;\n};\n\nexport const isValidConstructionPosition = (\n kingdom: Kingdom,\n placedBuildings: PlacedBuilding[],\n position: Position,\n): boolean => {\n const tile = kingdom[position.y]?.[position.x];\n if (!tile || tile.type === \"empty\" || tile.type === \"castle\") return false;\n if (!(\"hasConstructionSquare\" in tile) || !tile.hasConstructionSquare)\n return false;\n\n const occupied = placedBuildings.some(\n (b) => b.position.x === position.x && b.position.y === position.y,\n );\n return !occupied;\n};\n\nexport const placeBuildingOnKingdom = (\n kingdom: Kingdom,\n building: BuildingTile,\n position: Position,\n): Kingdom => {\n // Add building crowns to the tile\n const newKingdom = kingdom.map((row) => [...row]);\n const tile = newKingdom[position.y]![position.x]!;\n\n if (tile.type !== \"empty\" && tile.type !== \"castle\") {\n newKingdom[position.y]![position.x] = {\n ...tile,\n crowns: tile.crowns + building.crowns,\n };\n }\n\n return newKingdom;\n};\n\nexport const destroyWithDragon = (\n board: BuildersBoard,\n buildingId: number,\n player: Player,\n): {\n updatedBoard: BuildersBoard;\n updatedPlayer: Player;\n} | null => {\n const found = findBuildingOnBoard(board, buildingId);\n if (!found) return null;\n\n const { building, slotIndex } = found;\n if (!canAfford(player, building.cost)) return null;\n\n const updatedPlayer = removeCoins(player, building.cost);\n const updatedBoard = removeBuildingFromBoard(board, slotIndex);\n\n return { updatedBoard, updatedPlayer };\n};\n","import {\n type Game,\n type GameState,\n gameSteps,\n type NextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Lord } from \"@core/domain/types/lord.js\";\nimport {\n type PlayerActions,\n playerActions,\n} 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\n/**\n * Moves the game on once the current lord has finished its actions:\n * to the `result` step when every lord has finished the last turn,\n * otherwise to the next lord's action.\n */\nexport const advanceToNextLordOrResult = (\n game: Game,\n lords: Lord[],\n): GameState => {\n if (game.turn === game.rules.basic.maxTurns && allLordsHavePlayed(lords)) {\n return {\n ...game,\n lords,\n nextAction: { type: \"step\", step: gameSteps.result },\n };\n }\n return { ...game, lords, nextAction: nextLordWithAction(lords) };\n};\n\n/**\n * Queendomino optional action sequence after placeDomino:\n * placeKnight → constructBuilding → useDragon → pickDomino\n *\n * Given the current optional action, returns the next one in the sequence.\n */\nconst QUEENDOMINO_ACTION_SEQUENCE: PlayerActions[] = [\n playerActions.placeKnight,\n playerActions.constructBuilding,\n playerActions.useDragon,\n playerActions.pickDomino,\n];\n\nexport const nextQueenDominoAction = (\n currentAction: PlayerActions,\n): PlayerActions => {\n const index = QUEENDOMINO_ACTION_SEQUENCE.indexOf(currentAction);\n if (index === -1 || index >= QUEENDOMINO_ACTION_SEQUENCE.length - 1) {\n return playerActions.pickDomino;\n }\n return QUEENDOMINO_ACTION_SEQUENCE[index + 1]!;\n};\n\n/**\n * Age of Giants action sequence after placeDomino (when placeGiant/sendGiant is triggered):\n * placeGiant or sendGiant → pickDomino\n *\n * When combined with QueenDomino:\n * placeGiant or sendGiant → placeKnight → constructBuilding → useDragon → pickDomino\n */\nconst AOG_QD_ACTION_SEQUENCE: PlayerActions[] = [\n playerActions.placeGiant, // or sendGiant (handled dynamically)\n playerActions.placeKnight,\n playerActions.constructBuilding,\n playerActions.useDragon,\n playerActions.pickDomino,\n];\n\n/**\n * Returns the next action after an AoG action.\n * @param currentAction - The current AoG action being completed or skipped\n * @param isQueenDomino - Whether the game combines AoG with QueenDomino\n */\nexport const nextAgeOfGiantsAction = (\n currentAction: PlayerActions,\n isQueenDomino: boolean,\n): PlayerActions => {\n if (!isQueenDomino) {\n // Simple AoG: after giant action, go to pickDomino\n return playerActions.pickDomino;\n }\n\n // AoG + QueenDomino: use the combined sequence\n const sequence = AOG_QD_ACTION_SEQUENCE;\n // Map sendGiant to the same position as placeGiant in the sequence\n const normalizedAction =\n currentAction === playerActions.sendGiant\n ? playerActions.placeGiant\n : currentAction;\n\n const index = sequence.indexOf(normalizedAction);\n if (index === -1 || index >= sequence.length - 1) {\n return playerActions.pickDomino;\n }\n return sequence[index + 1]!;\n};\n\n/**\n * Origins Discovery/Totem action sequence after placeDomino:\n * placeFireToken → pickDomino\n *\n * In Origins, placing a fire token is optional (only after placing a volcano domino).\n */\nconst ORIGINS_DISCOVERY_SEQUENCE: PlayerActions[] = [\n playerActions.placeFireToken,\n playerActions.pickDomino,\n];\n\n/**\n * Origins Tribe action sequence after placeDomino:\n * placeFireToken → pickDomino → recruitCaveman\n *\n * recruitCaveman happens after picking a new domino (unique to Tribe mode).\n */\nconst ORIGINS_TRIBE_SEQUENCE: PlayerActions[] = [\n playerActions.placeFireToken,\n playerActions.pickDomino,\n playerActions.recruitCaveman,\n];\n\n/**\n * Returns the next Origins action in the sequence.\n * @param currentAction - The current action being completed or skipped\n * @param isTribe - Whether the game is in Tribe mode\n */\nexport const nextOriginsAction = (\n currentAction: PlayerActions,\n isTribe: boolean,\n): PlayerActions => {\n const sequence = isTribe\n ? ORIGINS_TRIBE_SEQUENCE\n : ORIGINS_DISCOVERY_SEQUENCE;\n const index = sequence.indexOf(currentAction);\n if (index === -1 || index >= sequence.length - 1) {\n // Fallback: if we're past the end, signal turn done\n return playerActions.pickDomino;\n }\n return sequence[index + 1]!;\n};\n","import { discardFromAgeOfGiantsLine } from \"@core/domain/entities/ageOfGiantsHelpers.js\";\nimport { startNewQueenDominoRound } from \"@core/domain/entities/building.js\";\nimport {\n allLordsHavePlayed,\n canPick,\n nextLordWithAction,\n resetLordsActions,\n updateLordOrder,\n} from \"@core/domain/entities/lord.js\";\nimport { isTribeMode } from \"@core/domain/entities/originsHelpers.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type { GameWithNextAction } from \"@core/domain/types/game.js\";\nimport { playerActions } from \"@core/domain/types/player.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 const isTribe = isTribeMode(game.mode.name);\n\n // update lords - always mark turn ended\n const updatedLords = game.lords.map((lord) =>\n lord.id === currentLord.id\n ? {\n ...lord,\n hasPick: true,\n turnEnded: true,\n dominoPicked: selectedDomino.domino,\n }\n : lord,\n );\n\n const turnEnded = allLordsHavePlayed(updatedLords);\n\n if (turnEnded) {\n // All lords have picked - perform turn transition\n const lords = resetLordsActions(updateLordOrder(updatedLords));\n const updatedTurn = game.turn + 1;\n const dominoesCopy = [...game.dominoes];\n const sortedLine = dominoesCopy.splice(0, game.rules.basic.dominoesPerTurn);\n sortedLine.sort((a, b) => a.number - b.number);\n\n // Age of Giants: discard the dominos at the official positions of the\n // sorted line (middle one at 2/4 players, 2nd and 4th at 3 players)\n const dominoesDrawn = discardFromAgeOfGiantsLine(\n sortedLine,\n game.rules.basic.dominoesDiscardedPerTurn ?? 0,\n );\n\n const newCurrentDominoes = dominoesDrawn.map((domino, index) => ({\n domino,\n picked: false,\n lordId: null,\n position: index + 1,\n }));\n\n if (isTribe) {\n // In Tribe mode, route to recruitCaveman before advancing to new turn\n return ok({\n ...game,\n currentDominoes: newCurrentDominoes,\n dominoes: dominoesCopy,\n lords,\n turn: updatedTurn,\n nextAction: {\n type: \"action\",\n nextLord: currentLord.id,\n nextAction: playerActions.recruitCaveman,\n },\n });\n }\n\n // Queendomino (incl. AoG-QD): new round, refill the Builders Board and\n // send the Dragon back to its cave\n const queendomino =\n game.queendomino && startNewQueenDominoRound(game.queendomino);\n\n const next = nextLordWithAction(lords);\n return ok({\n ...game,\n currentDominoes: newCurrentDominoes,\n dominoes: dominoesCopy,\n lords,\n turn: updatedTurn,\n nextAction: next,\n ...(queendomino && { queendomino }),\n });\n }\n\n if (isTribe) {\n // In Tribe mode, route to recruitCaveman before next lord picks\n return ok({\n ...game,\n currentDominoes: updatedCurrentDominoes,\n lords: updatedLords,\n nextAction: {\n type: \"action\",\n nextLord: currentLord.id,\n nextAction: playerActions.recruitCaveman,\n },\n });\n }\n\n const next = nextLordWithAction(updatedLords);\n\n return ok({\n ...game,\n currentDominoes: updatedCurrentDominoes,\n lords: updatedLords,\n nextAction: next,\n });\n};\n","import {\n isValidConstructionPosition,\n placeBuildingOnKingdom,\n purchaseBuilding,\n} from \"@core/domain/entities/building.js\";\nimport { nextQueenDominoAction } from \"@core/domain/entities/lord.js\";\nimport { determineQueenHolder } from \"@core/domain/entities/queen.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type { PlacedBuilding } from \"@core/domain/types/building.js\";\nimport type {\n GameStateResult,\n GameWithNextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Position } from \"@core/domain/types/kingdom.js\";\nimport { type Player, playerActions } from \"@core/domain/types/player.js\";\nimport type { QueenDominoState } from \"@core/domain/types/queendomino.js\";\nimport { err, isErr, ok, type Result } from \"@utils/result.js\";\n\nexport type ConstructBuildingUseCase = (\n game: GameWithNextAction,\n lordId: string,\n buildingId: number,\n position: Position,\n) => GameStateResult;\n\n/**\n * Everything `constructBuilding` needs before checking the construction square\n * and the purchase: the current player and the Queendomino state.\n * Shared with `getValidBuildingPositions` / `getAffordableBuildings`.\n */\nexport type ConstructionContext = {\n player: Player;\n queendomino: QueenDominoState;\n};\n\nexport const resolveConstruction = (\n game: GameWithNextAction,\n lordId: string,\n): Result<ConstructionContext> => {\n const currentAction = game.nextAction;\n\n if (currentAction.nextLord !== lordId) {\n return err(ErrorCode.NOT_YOUR_TURN);\n }\n\n if (currentAction.nextAction !== playerActions.constructBuilding) {\n return err(ErrorCode.INVALID_OPTIONAL_ACTION);\n }\n\n if (!game.queendomino) {\n return err(ErrorCode.INVALID_OPTIONAL_ACTION);\n }\n\n const currentLord = game.lords.find((l) => l.id === lordId);\n if (!currentLord) return err(ErrorCode.LORD_NOT_FOUND);\n\n const currentPlayer = game.players.find((p) => p.id === currentLord.playerId);\n if (!currentPlayer) return err(ErrorCode.PLAYER_NOT_FOUND);\n\n return ok({ player: currentPlayer, queendomino: game.queendomino });\n};\n\nexport const constructBuildingUseCase: ConstructBuildingUseCase = (\n game,\n lordId,\n buildingId,\n position,\n) => {\n const context = resolveConstruction(game, lordId);\n if (isErr(context)) {\n return context;\n }\n\n const { player: currentPlayer, queendomino } = context.value;\n\n // Validate construction position\n if (\n !isValidConstructionPosition(\n currentPlayer.kingdom,\n currentPlayer.buildings ?? [],\n position,\n )\n ) {\n return err(ErrorCode.NO_CONSTRUCTION_SQUARE);\n }\n\n // Purchase the building\n const purchaseResult = purchaseBuilding(\n queendomino.buildersBoard,\n currentPlayer,\n buildingId,\n );\n\n if (!purchaseResult) {\n return err(ErrorCode.CANNOT_AFFORD_BUILDING);\n }\n\n const { updatedBoard, updatedPlayer, building } = purchaseResult;\n\n // Place building on kingdom (adds crowns)\n const updatedKingdom = placeBuildingOnKingdom(\n updatedPlayer.kingdom,\n building,\n position,\n );\n\n const placedBuilding: PlacedBuilding = { building, position };\n const finalPlayer = {\n ...updatedPlayer,\n kingdom: updatedKingdom,\n buildings: [...(updatedPlayer.buildings ?? []), placedBuilding],\n };\n\n const updatedPlayers = game.players.map((p) =>\n p.id === currentPlayer.id ? finalPlayer : p,\n );\n\n // Recalculate Queen holder\n const newQueenHolder = determineQueenHolder(\n updatedPlayers,\n queendomino.queenHolderId,\n );\n\n const nextAction = nextQueenDominoAction(playerActions.constructBuilding);\n\n return ok({\n ...game,\n players: updatedPlayers,\n queendomino: {\n ...queendomino,\n buildersBoard: updatedBoard,\n queenHolderId: newQueenHolder,\n },\n nextAction: {\n type: \"action\",\n nextLord: lordId,\n nextAction: nextAction,\n },\n });\n};\n","import { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type { Kingdom, Position } from \"@core/domain/types/index.js\";\nimport type {\n FireTokenPool,\n PlacedFireToken,\n} from \"@core/domain/types/origins.js\";\nimport { err, ok, type Result } from \"@utils/result.js\";\n\n// ─── Fire Token Pool ─────────────────────────────────────────────────\n\n/**\n * Creates the initial fire token pool for an Origins game.\n * 10 tokens total: 5×1-fire, 4×2-fire, 1×3-fire.\n */\nexport const createFireTokenPool = (): FireTokenPool => ({\n ones: 5,\n twos: 4,\n threes: 1,\n});\n\n/**\n * Takes a fire token from the pool matching the given crater count.\n * Returns the updated pool, or an error if none available.\n */\nexport const takeFireToken = (\n pool: FireTokenPool,\n craters: number,\n): Result<{ fires: 1 | 2 | 3; updatedPool: FireTokenPool }> => {\n if (craters === 1 && pool.ones > 0) {\n return ok({ fires: 1, updatedPool: { ...pool, ones: pool.ones - 1 } });\n }\n if (craters === 2 && pool.twos > 0) {\n return ok({ fires: 2, updatedPool: { ...pool, twos: pool.twos - 1 } });\n }\n if (craters === 3 && pool.threes > 0) {\n return ok({ fires: 3, updatedPool: { ...pool, threes: pool.threes - 1 } });\n }\n return err(ErrorCode.FIRE_TOKEN_POOL_EMPTY);\n};\n\n/**\n * Checks whether a fire token of the given crater type is available.\n */\nexport const hasFireToken = (pool: FireTokenPool, craters: number): boolean => {\n if (craters === 1) return pool.ones > 0;\n if (craters === 2) return pool.twos > 0;\n if (craters === 3) return pool.threes > 0;\n return false;\n};\n\n// ─── Fire Token Placement ────────────────────────────────────────────\n\n/**\n * Computes all positions reachable in exactly N steps from a starting position,\n * using 8-directional movement (including diagonal) with direction changes allowed.\n */\nconst getReachablePositions = (\n from: Position,\n steps: number,\n gridSize: number,\n): Position[] => {\n if (steps === 0) return [from];\n\n // BFS: track positions reachable at each step count\n let current = new Set<string>();\n current.add(`${from.x},${from.y}`);\n\n for (let step = 0; step < steps; step++) {\n const next = new Set<string>();\n for (const key of current) {\n const [cx, cy] = key.split(\",\").map(Number) as [number, number];\n for (let dx = -1; dx <= 1; dx++) {\n for (let dy = -1; dy <= 1; dy++) {\n if (dx === 0 && dy === 0) continue;\n const nx = cx + dx;\n const ny = cy + dy;\n if (nx >= 0 && nx < gridSize && ny >= 0 && ny < gridSize) {\n next.add(`${nx},${ny}`);\n }\n }\n }\n }\n current = next;\n }\n\n return [...current].map((key) => {\n const [x, y] = key.split(\",\").map(Number) as [number, number];\n return { x, y };\n });\n};\n\n/**\n * Returns all valid positions where a fire token can be placed.\n * A fire token is launched from the volcano and travels exactly N squares\n * (8-directional, direction changes allowed).\n *\n * Landing position constraints:\n * - Must be on the grid and contain a placed tile (not empty)\n * - Must NOT be a volcano or castle tile\n * - Must NOT have a fire symbol (crowns > 0)\n * - Must NOT already have a fire token\n */\nexport const getValidFireTokenPositions = (\n kingdom: Kingdom,\n volcanoPosition: Position,\n fires: 1 | 2 | 3,\n existingFireTokens: PlacedFireToken[],\n): Position[] => {\n const gridSize = kingdom.length;\n const reachable = getReachablePositions(volcanoPosition, fires, gridSize);\n\n const fireTokenPositions = new Set(\n existingFireTokens.map((ft) => `${ft.position.x},${ft.position.y}`),\n );\n\n return reachable.filter((pos) => {\n const tile = kingdom[pos.y]?.[pos.x];\n if (!tile) return false;\n if (tile.type === \"empty\") return false;\n if (tile.type === \"volcano\") return false;\n if (tile.type === \"castle\") return false;\n if (tile.crowns > 0) return false;\n if (fireTokenPositions.has(`${pos.x},${pos.y}`)) return false;\n return true;\n });\n};\n\n/**\n * Checks whether a specific position is valid for fire token placement.\n */\nexport const isValidFireTokenPosition = (\n kingdom: Kingdom,\n position: Position,\n volcanoPosition: Position,\n fires: 1 | 2 | 3,\n existingFireTokens: PlacedFireToken[],\n): boolean => {\n const validPositions = getValidFireTokenPositions(\n kingdom,\n volcanoPosition,\n fires,\n existingFireTokens,\n );\n return validPositions.some((p) => p.x === position.x && p.y === position.y);\n};\n","import { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type { PlacedGiant } from \"@core/domain/types/ageOfGiants.js\";\nimport type { Kingdom, Position } from \"@core/domain/types/kingdom.js\";\nimport type { Player } from \"@core/domain/types/player.js\";\nimport { err, ok, type Result } from \"@utils/result.js\";\n\nconst INITIAL_GIANT_POOL = 6;\n\n/**\n * Creates the initial giant pool (6 giants).\n */\nexport const createGiantPool = (): number => INITIAL_GIANT_POOL;\n\n/**\n * Takes a giant from the pool.\n * Returns the updated pool count, or an error if pool is empty.\n */\nexport const takeFromGiantPool = (pool: number): Result<number> => {\n if (pool <= 0) {\n return err(ErrorCode.GIANT_POOL_EMPTY);\n }\n return ok(pool - 1);\n};\n\n/**\n * Finds all positions in a kingdom that have at least 1 crown.\n */\nexport const findCrownsInKingdom = (kingdom: Kingdom): Position[] => {\n const crowns: Position[] = [];\n for (let y = 0; y < kingdom.length; y++) {\n const row = kingdom[y]!;\n for (let x = 0; x < row.length; x++) {\n const tile = row[x]!;\n if (tile.type !== \"empty\" && tile.type !== \"castle\" && tile.crowns > 0) {\n crowns.push({ x, y });\n }\n }\n }\n return crowns;\n};\n\n/**\n * Finds all crown positions not already covered by a giant.\n */\nexport const findCrownsNotCoveredByGiants = (\n kingdom: Kingdom,\n giants: PlacedGiant[],\n): Position[] => {\n const allCrowns = findCrownsInKingdom(kingdom);\n return allCrowns.filter(\n (crown) =>\n !giants.some((g) => g.position.x === crown.x && g.position.y === crown.y),\n );\n};\n\n/**\n * Checks whether a player has at least one giant on their kingdom.\n */\nexport const playerHasGiant = (player: Player): boolean =>\n (player.giants?.length ?? 0) > 0;\n\n/**\n * Places a giant on a crown in the player's kingdom.\n * Validates that the position has an uncovered crown.\n */\nexport const placeGiantOnCrown = (\n player: Player,\n position: Position,\n): Result<Player> => {\n const kingdom = player.kingdom;\n const tile = kingdom[position.y]?.[position.x];\n\n if (!tile || tile.type === \"empty\" || tile.type === \"castle\") {\n return err(ErrorCode.INVALID_GIANT_PLACEMENT);\n }\n\n if (tile.crowns <= 0) {\n return err(ErrorCode.INVALID_GIANT_PLACEMENT);\n }\n\n const giants = player.giants ?? [];\n\n // Check crown isn't already covered\n const alreadyCovered = giants.some(\n (g) => g.position.x === position.x && g.position.y === position.y,\n );\n if (alreadyCovered) {\n return err(ErrorCode.INVALID_GIANT_PLACEMENT);\n }\n\n const newGiant: PlacedGiant = { position };\n return ok({\n ...player,\n giants: [...giants, newGiant],\n });\n};\n\n/**\n * Whether the player has a giant at `giantIndex` in its giants array.\n */\nexport const hasGiantAtIndex = (player: Player, giantIndex: number): boolean =>\n giantIndex >= 0 && giantIndex < (player.giants ?? []).length;\n\n/**\n * Removes one giant (by index) from a player's kingdom.\n */\nexport const removeGiantFromPlayer = (\n player: Player,\n giantIndex: number,\n): Result<Player> => {\n const giants = player.giants ?? [];\n if (!hasGiantAtIndex(player, giantIndex)) {\n return err(ErrorCode.GIANT_NOT_FOUND);\n }\n return ok({ ...player, giants: giants.filter((_, i) => i !== giantIndex) });\n};\n\n/**\n * Sends a giant from the source player to the target player.\n * Removes the giant from the source and places it on a crown of the target.\n */\nexport const sendGiantToOpponent = (\n sourcePlayer: Player,\n targetPlayer: Player,\n giantIndex: number,\n targetCrownPosition: Position,\n): Result<{ source: Player; target: Player }> => {\n const sourceGiants = sourcePlayer.giants ?? [];\n\n if (!hasGiantAtIndex(sourcePlayer, giantIndex)) {\n return err(ErrorCode.GIANT_NOT_FOUND);\n }\n\n // Validate target position has a crown\n const targetTile =\n targetPlayer.kingdom[targetCrownPosition.y]?.[targetCrownPosition.x];\n if (\n !targetTile ||\n targetTile.type === \"empty\" ||\n targetTile.type === \"castle\" ||\n targetTile.crowns <= 0\n ) {\n return err(ErrorCode.INVALID_GIANT_PLACEMENT);\n }\n\n // Check target crown isn't already covered\n const targetGiants = targetPlayer.giants ?? [];\n const alreadyCovered = targetGiants.some(\n (g) =>\n g.position.x === targetCrownPosition.x &&\n g.position.y === targetCrownPosition.y,\n );\n if (alreadyCovered) {\n return err(ErrorCode.INVALID_GIANT_PLACEMENT);\n }\n\n // Remove giant from source\n const updatedSourceGiants = sourceGiants.filter((_, i) => i !== giantIndex);\n\n // Place giant on target\n const newGiant: PlacedGiant = { position: targetCrownPosition };\n\n return ok({\n source: { ...sourcePlayer, giants: updatedSourceGiants },\n target: { ...targetPlayer, giants: [...targetGiants, newGiant] },\n });\n};\n","import type {\n AgeOfGiantsState,\n QuestTile,\n} from \"@core/domain/types/ageOfGiants.js\";\nimport type { BuildingTile } from \"@core/domain/types/building.js\";\nimport {\n type Domino,\n type GameMode,\n type GameWithNextStep,\n gameSteps,\n} from \"@core/domain/types/index.js\";\nimport type { CavemanTile, OriginsState } from \"@core/domain/types/origins.js\";\nimport type { QueenDominoState } from \"@core/domain/types/queendomino.js\";\nimport { isAgeOfGiantsMode } from \"./ageOfGiantsHelpers.js\";\nimport { createFireTokenPool } from \"./fireToken.js\";\nimport { createGiantPool } from \"./giant.js\";\nimport {\n getOriginsSubMode,\n isOriginsMode,\n isTotemMode,\n isTribeMode,\n} from \"./originsHelpers.js\";\n\nexport const create = (payload: {\n id: string;\n mode: GameMode;\n dominoes: Domino[];\n seed?: string;\n buildings?: BuildingTile[];\n cavemen?: CavemanTile[];\n questTiles?: QuestTile[];\n}): GameWithNextStep => {\n const { id, mode, dominoes, seed, buildings, cavemen, questTiles } = payload;\n\n let queendomino: QueenDominoState | undefined;\n if (\n (mode.name === \"QueenDomino\" || mode.name === \"AgeOfGiants-QueenDomino\") &&\n buildings\n ) {\n queendomino = {\n buildersBoard: {\n slots: [],\n drawPile: buildings,\n },\n queenHolderId: null,\n dragonAvailable: true,\n dragonUsedThisRound: false,\n };\n }\n\n let origins: OriginsState | undefined;\n if (isOriginsMode(mode.name)) {\n const subMode = getOriginsSubMode(mode.name)!;\n origins = {\n subMode,\n fireTokenPool: createFireTokenPool(),\n ...(isTotemMode(mode.name) && {\n totems: {\n mammoth: null,\n fish: null,\n mushroom: null,\n flint: null,\n },\n }),\n ...(isTribeMode(mode.name) &&\n cavemen && {\n caveBoard: {\n visible: [],\n drawPile: cavemen,\n },\n }),\n };\n }\n\n let ageOfGiants: AgeOfGiantsState | undefined;\n if (isAgeOfGiantsMode(mode.name) && questTiles) {\n ageOfGiants = {\n giantPool: createGiantPool(),\n questTiles,\n };\n }\n\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 ...(queendomino !== undefined && { queendomino }),\n ...(origins !== undefined && { origins }),\n ...(ageOfGiants !== undefined && { ageOfGiants }),\n };\n};\n","import { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type { GameMode } from \"@core/domain/types/mode.js\";\nimport { err, ok, type Result } from \"@utils/result.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 {\n isAgeOfGiantsMode,\n isAgeOfGiantsQueenDominoMode,\n} from \"@core/domain/entities/ageOfGiantsHelpers.js\";\nimport { create } from \"@core/domain/entities/game.js\";\nimport { createMode } from \"@core/domain/entities/mode.js\";\nimport { isTribeMode } from \"@core/domain/entities/originsHelpers.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type { QuestTile } from \"@core/domain/types/ageOfGiants.js\";\nimport type { BuildingTile } from \"@core/domain/types/building.js\";\nimport type { GameWithNextStep } from \"@core/domain/types/game.js\";\nimport type { CavemanTile } from \"@core/domain/types/origins.js\";\nimport type { BuildingsRepository } from \"@core/portServerside/buildingsRepository.js\";\nimport type { CavemenRepository } from \"@core/portServerside/cavemenRepository.js\";\nimport type { DominoesRepository } from \"@core/portServerside/dominoesRepository.js\";\nimport type { ModeRepository } from \"@core/portServerside/modeRepository.js\";\nimport type { QuestTilesRepository } from \"@core/portServerside/questTilesRepository.js\";\nimport type { ShuffleMethod } from \"@core/portServerside/shuffleMethod.js\";\nimport type { UuidMethod } from \"@core/portServerside/uuidMethod.js\";\nimport { err, isErr, ok, type Result } from \"@utils/result.js\";\nimport { createSeededShuffle } from \"@utils/seededShuffle.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 shuffleMethod: ShuffleMethod;\n buildingsRepository?: BuildingsRepository;\n cavemenRepository?: CavemenRepository;\n questTilesRepository?: QuestTilesRepository;\n }): CreateGameUseCase =>\n (mode, seed) => {\n const {\n modeRepository,\n dominoesRepository,\n uuidMethod,\n shuffleMethod,\n buildingsRepository,\n cavemenRepository,\n questTilesRepository,\n } = 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 isQueenDomino =\n newMode.value.name === \"QueenDomino\" ||\n isAgeOfGiantsQueenDominoMode(newMode.value.name);\n let buildings: BuildingTile[] | undefined;\n\n if (isQueenDomino && buildingsRepository) {\n buildings = buildingsRepository.getAll();\n }\n\n let cavemen: CavemanTile[] | undefined;\n if (isTribeMode(newMode.value.name) && cavemenRepository) {\n cavemen = cavemenRepository.getAll();\n }\n\n let questTiles: QuestTile[] | undefined;\n if (isAgeOfGiantsMode(newMode.value.name) && questTilesRepository) {\n const allQuests = questTilesRepository.getAll();\n // Draw 2 random quest tiles\n const questShuffle = gameSeed\n ? createSeededShuffle(gameSeed, \"quests\")\n : shuffleMethod;\n const shuffledQuests = questShuffle(allQuests);\n questTiles = shuffledQuests.slice(0, 2);\n }\n\n const payload = {\n id,\n mode: newMode.value,\n dominoes,\n seed: gameSeed,\n buildings,\n cavemen,\n questTiles,\n };\n\n const newGame = create(payload);\n\n return ok(newGame);\n };\n","import { placeDomino } from \"@core/domain/entities/kingdom.js\";\nimport type {\n Domino,\n Kingdom,\n Position,\n Rotation,\n} from \"@core/domain/types/index.js\";\nimport { GRIDSIZE, MAX_KINGDOM_SIZE } from \"@core/domain/types/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(\n kingdom,\n position,\n rotation,\n domino,\n maxKingdomSize,\n );\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(\n kingdom,\n position,\n rotation,\n domino,\n maxKingdomSize,\n );\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 { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameState,\n type GameStateResult,\n type GameWithNextAction,\n gameSteps,\n type NextAction,\n type NextStep,\n} from \"@core/domain/types/game.js\";\nimport { playerActions } from \"@core/domain/types/player.js\";\nimport { err, ok } from \"@utils/result.js\";\nimport { canPlaceDominoUseCase } from \"./getValidPlacements.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 (\n currentPlayer &&\n canPlaceDominoUseCase(\n currentPlayer.kingdom,\n currentLord.dominoPicked,\n game.rules.basic.maxKingdomSize,\n )\n ) {\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 // Queendomino (incl. AoG-QD): discarding only replaces action A. The player\n // still may construct a building and bribe the Dragon (actions C and D), but\n // cannot tax with a knight since no domino was just placed (action B).\n if (game.queendomino) {\n return ok({\n ...game,\n lords: updatedLord,\n queendomino: { ...game.queendomino, lastPlacedPositions: [] },\n nextAction: {\n type: \"action\",\n nextLord: currentLord.id,\n nextAction: playerActions.constructBuilding,\n },\n });\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 { DynastyGroupBy } from \"@application/commands/getDynastyResultCommand.js\";\nimport type { GameWithResults } from \"@core/domain/types/index.js\";\n\nexport type DynastyResult = {\n /**\n * Player id. With `groupBy: \"playerName\"`, the id the player had in the\n * first game where that name appears.\n */\n playerId: string;\n playerName: string;\n totalPoints: number;\n gamesPoints: number[];\n position: number;\n};\n\nexport type GetDynastyResultUseCase = (\n games: GameWithResults[],\n groupBy?: DynastyGroupBy,\n) => DynastyResult[];\n\nexport const getDynastyResultUseCase: GetDynastyResultUseCase = (\n games,\n groupBy = \"playerId\",\n) => {\n // Collect all unique players\n const playerMap = new Map<\n string,\n { playerId: string; name: string; points: number[] }\n >();\n\n for (const game of games) {\n for (const result of game.result) {\n const key =\n groupBy === \"playerName\" ? result.playerName : result.playerId;\n const existing = playerMap.get(key);\n if (existing) {\n existing.points.push(result.details.points);\n } else {\n playerMap.set(key, {\n playerId: 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 data of playerMap.values()) {\n results.push({\n playerId: data.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 { ErrorCode } from \"@core/domain/errors/domainErrors.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 { 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 { computePlayerScore } from \"@core/domain/entities/scoreBreakdown.js\";\nimport type {\n FinalResult,\n GameWithNextStep,\n GameWithResults,\n ScoreResult,\n} from \"@core/domain/types/index.js\";\nimport { ok, type Result } from \"@utils/result.js\";\n\nexport type GetResultUseCase = (\n game: GameWithNextStep,\n) => Result<GameWithResults>;\n\n/**\n * Ranks scored players: by points, then by largest territory (per official\n * rules, no further tiebreaker). Players equal on both share the position.\n */\nexport const rankScoreResults = (scoreResult: ScoreResult[]): FinalResult[] => {\n const sorted = [...scoreResult].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 if (sorted.length === 0) return result;\n\n result.push({ ...sorted[0]!, position: 1 });\n\n for (let i = 1; i < sorted.length; i++) {\n const currentScore = sorted[i]!;\n const previousScore = sorted[i - 1]!;\n const isTie =\n currentScore.details.points === previousScore.details.points &&\n currentScore.details.maxPropertiesSize ===\n previousScore.details.maxPropertiesSize;\n\n result.push({\n ...currentScore,\n position: isTie ? result[i - 1]!.position : i + 1,\n });\n }\n\n return result;\n};\n\n/**\n * Final results: every player is scored with the mode-aware score breakdown\n * (the same computation as `calculatePlayerScore`), then ranked.\n */\nexport const getResultUseCase: GetResultUseCase = (game) => {\n const scoreResult = game.players.map((player): ScoreResult => {\n const score = computePlayerScore(game, player, true);\n return {\n playerId: score.playerId,\n playerName: score.playerName,\n details: {\n points: score.points,\n maxPropertiesSize: score.maxPropertiesSize,\n totalCrowns: score.totalCrowns,\n },\n breakdown: score.breakdown,\n };\n });\n\n return ok({\n ...game,\n result: rankScoreResults(scoreResult),\n });\n};\n","import type { Kingdom, Position } from \"@core/domain/types/kingdom.js\";\nimport type { Knight, Player } from \"@core/domain/types/player.js\";\nimport { addCoins, getMaxKnights } from \"./economy.js\";\n\n/**\n * Count construction squares in the contiguous territory containing the given position.\n * Uses BFS flood-fill on same terrain type.\n */\nexport const countConstructionSquaresInTerritory = (\n kingdom: Kingdom,\n position: Position,\n): number => {\n const rows = kingdom.length;\n const cols = kingdom[0]?.length ?? 0;\n const startTile = kingdom[position.y]?.[position.x];\n\n if (!startTile || startTile.type === \"empty\" || startTile.type === \"castle\") {\n return 0;\n }\n\n const terrainType = startTile.type;\n const visited: boolean[][] = kingdom.map((row) => row.map(() => false));\n const queue: [number, number][] = [[position.x, position.y]];\n visited[position.y]![position.x] = true;\n let count = 0;\n\n const directions = [\n [-1, 0],\n [1, 0],\n [0, -1],\n [0, 1],\n ];\n\n while (queue.length > 0) {\n const [cx, cy] = queue.pop()!;\n const tile = kingdom[cy]![cx]!;\n\n if (\n tile.type !== \"empty\" &&\n tile.type !== \"castle\" &&\n \"hasConstructionSquare\" in tile &&\n tile.hasConstructionSquare\n ) {\n count++;\n }\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 === terrainType\n ) {\n visited[ny]![nx] = true;\n queue.push([nx, ny]);\n }\n }\n }\n\n return count;\n};\n\n/**\n * Get the terrain type at a position to identify the territory.\n */\nconst getTerritoryTerrain = (\n kingdom: Kingdom,\n position: Position,\n): string | null => {\n const tile = kingdom[position.y]?.[position.x];\n if (!tile || tile.type === \"empty\" || tile.type === \"castle\") return null;\n return tile.type;\n};\n\n/**\n * Check if a territory (identified by BFS from position) already has a knight.\n */\nconst territoryHasKnight = (\n kingdom: Kingdom,\n position: Position,\n knights: Knight[],\n): boolean => {\n const terrain = getTerritoryTerrain(kingdom, position);\n if (!terrain) return false;\n\n // BFS to find all positions in this territory\n const rows = kingdom.length;\n const cols = kingdom[0]?.length ?? 0;\n const visited: boolean[][] = kingdom.map((row) => row.map(() => false));\n const queue: [number, number][] = [[position.x, position.y]];\n visited[position.y]![position.x] = true;\n const territoryPositions = new Set<string>();\n\n const directions = [\n [-1, 0],\n [1, 0],\n [0, -1],\n [0, 1],\n ];\n\n while (queue.length > 0) {\n const [cx, cy] = queue.pop()!;\n territoryPositions.add(`${cx},${cy}`);\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 === terrain\n ) {\n visited[ny]![nx] = true;\n queue.push([nx, ny]);\n }\n }\n }\n\n return knights.some((k) =>\n territoryPositions.has(`${k.position.x},${k.position.y}`),\n );\n};\n\n/**\n * Whether a knight can be placed at `position`.\n *\n * Official Queendomino rule (action B): the knight must be placed on the\n * domino the player has just added to their kingdom. When `allowedPositions`\n * is given (the squares of that domino), the position must be one of them.\n */\nexport const canPlaceKnight = (\n player: Player,\n kingdom: Kingdom,\n position: Position,\n allowedPositions?: Position[],\n): boolean => {\n const knights = player.knights ?? [];\n if (knights.length >= getMaxKnights(player)) return false;\n\n if (\n allowedPositions !== undefined &&\n !allowedPositions.some((p) => p.x === position.x && p.y === position.y)\n ) {\n return false;\n }\n\n const tile = kingdom[position.y]?.[position.x];\n if (!tile || tile.type === \"empty\" || tile.type === \"castle\") return false;\n\n if (territoryHasKnight(kingdom, position, knights)) return false;\n\n return true;\n};\n\nexport const placeKnight = (\n player: Player,\n kingdom: Kingdom,\n position: Position,\n): Player => {\n const knight: Knight = { playerId: player.id, position };\n const knights = [...(player.knights ?? []), knight];\n const taxAmount = countConstructionSquaresInTerritory(kingdom, position);\n const updatedPlayer = addCoins({ ...player, knights }, taxAmount);\n\n return updatedPlayer;\n};\n","import { isValidFireTokenPosition } from \"@core/domain/entities/fireToken.js\";\nimport { advanceToNextLordOrResult } from \"@core/domain/entities/lord.js\";\nimport { refreshTotemHolders } from \"@core/domain/entities/totem.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type {\n GameState,\n GameStateResult,\n GameWithNextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Position } from \"@core/domain/types/kingdom.js\";\nimport type {\n PendingFireToken,\n PlacedFireToken,\n} from \"@core/domain/types/origins.js\";\nimport type { Player } from \"@core/domain/types/player.js\";\nimport { err, isErr, ok, type Result } from \"@utils/result.js\";\n\nexport type PlaceFireTokenUseCase = (\n game: GameWithNextAction,\n lordId: string,\n position: Position,\n) => GameStateResult;\n\n/**\n * Everything `placeFireToken` needs before checking the target square: the\n * current player, the pending fire token and the fire tokens already placed.\n * Shared with `getValidFireTokenPositions` so both apply the same checks.\n */\nexport type FireTokenPlacementContext = {\n player: Player;\n pending: PendingFireToken;\n existingTokens: PlacedFireToken[];\n};\n\nexport const resolveFireTokenPlacement = (\n game: GameWithNextAction,\n lordId: string,\n): Result<FireTokenPlacementContext> => {\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 (!game.origins?.pendingFireToken) {\n return err(ErrorCode.NO_PENDING_FIRE_TOKEN);\n }\n\n const pending = game.origins.pendingFireToken;\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 return ok({\n player: currentPlayer,\n pending,\n existingTokens: currentPlayer.fireTokens ?? [],\n });\n};\n\nexport const placeFireTokenUseCase: PlaceFireTokenUseCase = (\n game,\n lordId,\n position,\n) => {\n const context = resolveFireTokenPlacement(game, lordId);\n if (isErr(context)) {\n return context;\n }\n\n const { player: currentPlayer, pending, existingTokens } = context.value;\n const { fires, volcanoPosition } = pending;\n\n if (\n !isValidFireTokenPosition(\n currentPlayer.kingdom,\n position,\n volcanoPosition,\n fires,\n existingTokens,\n )\n ) {\n return err(ErrorCode.FIRE_TOKEN_INVALID_POSITION);\n }\n\n // Place the fire token\n const newToken: PlacedFireToken = { fires, position };\n const updatedFireTokens = [...existingTokens, newToken];\n\n // Destroy resource at position if any (Totem/Tribe modes)\n let updatedResources = currentPlayer.resources;\n if (updatedResources) {\n updatedResources = updatedResources.filter(\n (r) => !(r.position.x === position.x && r.position.y === position.y),\n );\n }\n\n // Destroy caveman at position if any (Tribe mode)\n let updatedCavemen = currentPlayer.cavemen;\n if (updatedCavemen) {\n updatedCavemen = updatedCavemen.filter(\n (c) => !(c.position.x === position.x && c.position.y === position.y),\n );\n }\n\n const updatedPlayers = game.players.map((player) => {\n if (player.id === currentPlayer.id) {\n return {\n ...player,\n fireTokens: updatedFireTokens,\n ...(updatedResources !== undefined && { resources: updatedResources }),\n ...(updatedCavemen !== undefined && { cavemen: updatedCavemen }),\n };\n }\n return player;\n });\n\n // Clear pending fire token and re-evaluate totems (a destroyed resource\n // may cost the majority in Totem mode)\n const updatedOrigins = refreshTotemHolders(\n game.origins && { ...game.origins, pendingFireToken: undefined },\n updatedPlayers,\n );\n\n // Determine next action: the game only ends once every lord has\n // finished the last turn\n const nextGameAction: GameState = advanceToNextLordOrResult(\n {\n ...game,\n players: updatedPlayers,\n ...(updatedOrigins !== undefined && { origins: updatedOrigins }),\n },\n game.lords,\n );\n\n return ok(nextGameAction);\n};\n","import { isAgeOfGiantsQueenDominoMode } from \"@core/domain/entities/ageOfGiantsHelpers.js\";\nimport {\n findCrownsNotCoveredByGiants,\n removeGiantFromPlayer,\n sendGiantToOpponent,\n} from \"@core/domain/entities/giant.js\";\nimport {\n advanceToNextLordOrResult,\n nextAgeOfGiantsAction,\n} from \"@core/domain/entities/lord.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type {\n GameStateResult,\n GameWithNextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Position } from \"@core/domain/types/kingdom.js\";\nimport { type Player, playerActions } from \"@core/domain/types/player.js\";\nimport { err, isErr, ok, type Result } from \"@utils/result.js\";\n\nexport type SendGiantUseCase = (\n game: GameWithNextAction,\n lordId: string,\n giantIndex: number,\n targetPlayerId: string,\n targetCrownPosition?: Position,\n) => GameStateResult;\n\n/**\n * Continues the sender's turn once the sent giant is on the opponent's\n * kingdom: next AoG-QD optional action, next lord, or the result step.\n */\nexport const continueAfterSendGiant = (\n game: GameWithNextAction,\n senderLordId: string,\n): GameStateResult => {\n const isAoGQD = isAgeOfGiantsQueenDominoMode(game.mode.name);\n const nextAction = nextAgeOfGiantsAction(playerActions.sendGiant, isAoGQD);\n\n if (nextAction === playerActions.pickDomino) {\n return ok(advanceToNextLordOrResult(game, game.lords));\n }\n\n return ok({\n ...game,\n nextAction: {\n type: \"action\",\n nextLord: senderLordId,\n nextAction: nextAction,\n },\n });\n};\n\n/**\n * Checks that `lordId` may send a giant now and returns the sending player.\n * Shared with `getValidGiantTargets` so both apply the same checks.\n */\nexport const resolveGiantSender = (\n game: GameWithNextAction,\n lordId: string,\n): Result<Player> => {\n const currentAction = game.nextAction;\n\n if (currentAction.nextAction !== playerActions.sendGiant) {\n return err(ErrorCode.INVALID_OPTIONAL_ACTION);\n }\n\n if (currentAction.nextLord !== lordId) {\n return err(ErrorCode.NOT_YOUR_TURN);\n }\n\n if (!game.ageOfGiants) {\n return err(ErrorCode.NOT_AOG_MODE);\n }\n\n const currentLord = game.lords.find((l) => l.id === lordId);\n if (!currentLord) {\n return err(ErrorCode.LORD_NOT_FOUND);\n }\n\n const sourcePlayer = game.players.find((p) => p.id === currentLord.playerId);\n if (!sourcePlayer) {\n return err(ErrorCode.PLAYER_NOT_FOUND);\n }\n\n return ok(sourcePlayer);\n};\n\n/**\n * A player who can receive a giant from `sourcePlayer`, with its crowns not\n * yet covered by a giant.\n */\nexport type GiantTarget = {\n targetPlayer: Player;\n freeCrowns: Position[];\n};\n\n/**\n * Checks that `targetPlayerId` is an opponent of `sourcePlayer` with at least\n * one free crown. Shared with `getValidGiantTargets`.\n */\nexport const resolveGiantTarget = (\n game: GameWithNextAction,\n sourcePlayer: Player,\n targetPlayerId: string,\n): Result<GiantTarget> => {\n const targetPlayer = game.players.find((p) => p.id === targetPlayerId);\n if (!targetPlayer) {\n return err(ErrorCode.PLAYER_NOT_FOUND);\n }\n\n if (sourcePlayer.id === targetPlayer.id) {\n return err(ErrorCode.INVALID_GIANT_PLACEMENT);\n }\n\n const freeCrowns = findCrownsNotCoveredByGiants(\n targetPlayer.kingdom,\n targetPlayer.giants ?? [],\n );\n if (freeCrowns.length === 0) {\n return err(ErrorCode.INVALID_GIANT_PLACEMENT);\n }\n\n return ok({ targetPlayer, freeCrowns });\n};\n\nexport const sendGiantUseCase: SendGiantUseCase = (\n game,\n lordId,\n giantIndex,\n targetPlayerId,\n targetCrownPosition,\n) => {\n const sender = resolveGiantSender(game, lordId);\n if (isErr(sender)) {\n return sender;\n }\n const sourcePlayer = sender.value;\n\n const target = resolveGiantTarget(game, sourcePlayer, targetPlayerId);\n if (isErr(target)) {\n return target;\n }\n const { targetPlayer, freeCrowns } = target.value;\n\n // Official rule: the targeted opponent chooses the crown. With a single\n // free crown there is no choice; with several, the opponent is asked\n // through a `placeGiant` action (unless the caller already passes the\n // crown the opponent chose, which is kept for backward compatibility).\n const crown =\n targetCrownPosition ?? (freeCrowns.length === 1 ? freeCrowns[0] : null);\n\n if (!crown) {\n const removed = removeGiantFromPlayer(sourcePlayer, giantIndex);\n if (isErr(removed)) {\n return removed;\n }\n\n const targetLord = game.lords.find((l) => l.playerId === targetPlayer.id);\n if (!targetLord) {\n return err(ErrorCode.LORD_NOT_FOUND);\n }\n\n return ok({\n ...game,\n players: game.players.map((p) =>\n p.id === sourcePlayer.id ? removed.value : p,\n ),\n ageOfGiants: game.ageOfGiants && {\n ...game.ageOfGiants,\n pendingGiant: { fromLordId: lordId, targetPlayerId: targetPlayer.id },\n },\n nextAction: {\n type: \"action\",\n nextLord: targetLord.id,\n nextAction: playerActions.placeGiant,\n },\n });\n }\n\n const result = sendGiantToOpponent(\n sourcePlayer,\n targetPlayer,\n giantIndex,\n crown,\n );\n if (isErr(result)) {\n return result;\n }\n\n const updatedPlayers = game.players.map((p) => {\n if (p.id === result.value.source.id) return result.value.source;\n if (p.id === result.value.target.id) return result.value.target;\n return p;\n });\n\n return continueAfterSendGiant({ ...game, players: updatedPlayers }, lordId);\n};\n","import { isAgeOfGiantsQueenDominoMode } from \"@core/domain/entities/ageOfGiantsHelpers.js\";\nimport {\n placeGiantOnCrown,\n takeFromGiantPool,\n} from \"@core/domain/entities/giant.js\";\nimport {\n allLordsHavePlayed,\n nextAgeOfGiantsAction,\n nextLordWithAction,\n} from \"@core/domain/entities/lord.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type {\n AgeOfGiantsState,\n PendingGiant,\n} from \"@core/domain/types/ageOfGiants.js\";\nimport {\n type GameStateResult,\n type GameWithNextAction,\n gameSteps,\n type NextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Position } from \"@core/domain/types/kingdom.js\";\nimport { type Player, playerActions } from \"@core/domain/types/player.js\";\nimport { err, isErr, ok, type Result } from \"@utils/result.js\";\nimport { continueAfterSendGiant } from \"./sendGiant.js\";\n\nexport type PlaceGiantUseCase = (\n game: GameWithNextAction,\n lordId: string,\n position: Position,\n) => GameStateResult;\n\n/**\n * Everything `placeGiant` needs before checking the crown: the player whose\n * kingdom receives the giant (the current player, or the targeted player of a\n * giant sent by an opponent) and, in that case, the pending giant.\n * Shared with `getValidGiantPositions` so both apply the same checks.\n */\nexport type GiantPlacementContext = {\n player: Player;\n /** Set when the giant was sent by an opponent (not taken from the pool) */\n pendingGiant?: PendingGiant;\n /**\n * Age of Giants state once the giant is taken: one giant less in the pool,\n * or the pending giant resolved.\n */\n updatedAgeOfGiants: AgeOfGiantsState;\n};\n\nexport const resolveGiantPlacement = (\n game: GameWithNextAction,\n lordId: string,\n): Result<GiantPlacementContext> => {\n const currentAction = game.nextAction;\n\n if (currentAction.nextAction !== playerActions.placeGiant) {\n return err(ErrorCode.INVALID_OPTIONAL_ACTION);\n }\n\n if (currentAction.nextLord !== lordId) {\n return err(ErrorCode.NOT_YOUR_TURN);\n }\n\n if (!game.ageOfGiants) {\n return err(ErrorCode.NOT_AOG_MODE);\n }\n\n // A giant sent by an opponent: the targeted player chooses the crown, the\n // giant does not come from the pool, then the sender's turn resumes.\n const pendingGiant = game.ageOfGiants.pendingGiant;\n if (pendingGiant) {\n const lord = game.lords.find((l) => l.id === lordId);\n if (!lord || lord.playerId !== pendingGiant.targetPlayerId) {\n return err(ErrorCode.NOT_YOUR_TURN);\n }\n const target = game.players.find((p) => p.id === lord.playerId);\n if (!target) {\n return err(ErrorCode.PLAYER_NOT_FOUND);\n }\n const { pendingGiant: _resolved, ...updatedAgeOfGiants } = game.ageOfGiants;\n return ok({ player: target, pendingGiant, updatedAgeOfGiants });\n }\n\n // Take from giant pool\n const poolResult = takeFromGiantPool(game.ageOfGiants.giantPool);\n if (isErr(poolResult)) {\n return poolResult;\n }\n\n const currentLord = game.lords.find((l) => l.id === lordId);\n if (!currentLord) {\n return err(ErrorCode.LORD_NOT_FOUND);\n }\n\n const currentPlayer = game.players.find((p) => p.id === currentLord.playerId);\n if (!currentPlayer) {\n return err(ErrorCode.PLAYER_NOT_FOUND);\n }\n\n return ok({\n player: currentPlayer,\n updatedAgeOfGiants: { ...game.ageOfGiants, giantPool: poolResult.value },\n });\n};\n\nexport const placeGiantUseCase: PlaceGiantUseCase = (\n game,\n lordId,\n position,\n) => {\n const context = resolveGiantPlacement(game, lordId);\n if (isErr(context)) {\n return context;\n }\n\n const {\n player: currentPlayer,\n pendingGiant,\n updatedAgeOfGiants: updatedAoG,\n } = context.value;\n\n // Place giant on the chosen crown\n const placeResult = placeGiantOnCrown(currentPlayer, position);\n if (isErr(placeResult)) {\n return placeResult;\n }\n\n // A giant sent by an opponent: the targeted player chose the crown, then\n // the sender's turn resumes.\n if (pendingGiant) {\n return continueAfterSendGiant(\n {\n ...game,\n players: game.players.map((p) =>\n p.id === currentPlayer.id ? placeResult.value : p,\n ),\n ageOfGiants: updatedAoG,\n },\n pendingGiant.fromLordId,\n );\n }\n\n const updatedPlayers = game.players.map((p) =>\n p.id === currentPlayer.id ? placeResult.value : p,\n );\n\n // Determine next action\n const isAoGQD = isAgeOfGiantsQueenDominoMode(game.mode.name);\n const nextAction = nextAgeOfGiantsAction(playerActions.placeGiant, isAoGQD);\n\n if (nextAction === playerActions.pickDomino) {\n // No more optional actions — advance to next lord or result\n const isLastTurn = game.turn === game.rules.basic.maxTurns;\n if (isLastTurn && allLordsHavePlayed(game.lords)) {\n return ok({\n ...game,\n players: updatedPlayers,\n ageOfGiants: updatedAoG,\n nextAction: { type: \"step\", step: gameSteps.result },\n });\n }\n return ok({\n ...game,\n players: updatedPlayers,\n ageOfGiants: updatedAoG,\n nextAction: nextLordWithAction(game.lords) as NextAction,\n });\n }\n\n // More optional actions (e.g., placeKnight in AoG-QD)\n return ok({\n ...game,\n players: updatedPlayers,\n ageOfGiants: updatedAoG,\n nextAction: {\n type: \"action\",\n nextLord: lordId,\n nextAction: nextAction,\n },\n });\n};\n","import { canPlaceKnight, placeKnight } from \"@core/domain/entities/knight.js\";\nimport { nextQueenDominoAction } from \"@core/domain/entities/lord.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type {\n GameStateResult,\n GameWithNextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Position } from \"@core/domain/types/kingdom.js\";\nimport { type Player, playerActions } from \"@core/domain/types/player.js\";\nimport { err, isErr, ok, type Result } from \"@utils/result.js\";\n\nexport type PlaceKnightUseCase = (\n game: GameWithNextAction,\n lordId: string,\n position: Position,\n) => GameStateResult;\n\n/**\n * Everything `placeKnight` needs before checking the target square: the\n * current player and the squares a knight may go on (the domino just placed).\n * Shared with `getValidKnightPositions` so both apply the same checks.\n */\nexport type KnightPlacementContext = {\n player: Player;\n allowedPositions: Position[];\n};\n\nexport const resolveKnightPlacement = (\n game: GameWithNextAction,\n lordId: string,\n): Result<KnightPlacementContext> => {\n const currentAction = game.nextAction;\n\n if (currentAction.nextLord !== lordId) {\n return err(ErrorCode.NOT_YOUR_TURN);\n }\n\n if (currentAction.nextAction !== playerActions.placeKnight) {\n return err(ErrorCode.INVALID_OPTIONAL_ACTION);\n }\n\n const currentLord = game.lords.find((l) => l.id === lordId);\n if (!currentLord) return err(ErrorCode.LORD_NOT_FOUND);\n\n const currentPlayer = game.players.find((p) => p.id === currentLord.playerId);\n if (!currentPlayer) return err(ErrorCode.PLAYER_NOT_FOUND);\n\n // Knights may only be placed on the domino the lord has just placed\n const allowedPositions = game.queendomino?.lastPlacedPositions ?? [];\n\n return ok({ player: currentPlayer, allowedPositions });\n};\n\nexport const placeKnightUseCase: PlaceKnightUseCase = (\n game,\n lordId,\n position,\n) => {\n const context = resolveKnightPlacement(game, lordId);\n if (isErr(context)) {\n return context;\n }\n\n const { player: currentPlayer, allowedPositions } = context.value;\n\n if (\n !canPlaceKnight(\n currentPlayer,\n currentPlayer.kingdom,\n position,\n allowedPositions,\n )\n ) {\n return err(ErrorCode.CANNOT_PLACE_KNIGHT);\n }\n\n const updatedPlayer = placeKnight(\n currentPlayer,\n currentPlayer.kingdom,\n position,\n );\n\n const updatedPlayers = game.players.map((p) =>\n p.id === currentPlayer.id ? updatedPlayer : p,\n );\n\n const nextAction = nextQueenDominoAction(playerActions.placeKnight);\n\n return ok({\n ...game,\n players: updatedPlayers,\n nextAction: {\n type: \"action\",\n nextLord: lordId,\n nextAction: nextAction,\n },\n });\n};\n","import {\n getRecruitmentCost,\n isValidCavemanPosition,\n takeCavemanFromDrawPile,\n takeCavemanFromVisible,\n} from \"@core/domain/entities/caveman.js\";\nimport { advanceToNextLordOrResult } from \"@core/domain/entities/lord.js\";\nimport {\n isValidResourcePayment,\n spendResources,\n} from \"@core/domain/entities/resource.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport type {\n GameState,\n GameStateResult,\n GameWithNextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Position } from \"@core/domain/types/kingdom.js\";\nimport type {\n CaveBoard,\n OriginsState,\n PlacedCaveman,\n PlacedFireToken,\n Resource,\n} from \"@core/domain/types/origins.js\";\nimport type { Player } from \"@core/domain/types/player.js\";\nimport { err, isErr, ok, type Result } from \"@utils/result.js\";\n\nexport type RecruitCavemanUseCase = (\n game: GameWithNextAction,\n lordId: string,\n cavemanId: number,\n position: Position,\n resourcePositions: Position[],\n) => GameStateResult;\n\n/**\n * Everything `recruitCaveman` needs before checking the recruited caveman, the\n * payment and the square: the current player, its Origins pieces and the cave\n * board. Shared with `getValidCavemanPlacements` so both apply the same checks.\n */\nexport type RecruitmentContext = {\n player: Player;\n origins: OriginsState;\n caveBoard: CaveBoard;\n resources: Resource[];\n fireTokens: PlacedFireToken[];\n cavemen: PlacedCaveman[];\n};\n\nexport const resolveRecruitment = (\n game: GameWithNextAction,\n lordId: string,\n): Result<RecruitmentContext> => {\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 (!game.origins?.caveBoard) {\n return err(ErrorCode.NOT_TRIBE_MODE);\n }\n\n const currentPlayer = game.players.find((p) => p.id === currentLord.playerId);\n\n if (!currentPlayer) {\n return err(ErrorCode.PLAYER_NOT_FOUND);\n }\n\n return ok({\n player: currentPlayer,\n origins: game.origins,\n caveBoard: game.origins.caveBoard,\n resources: currentPlayer.resources ?? [],\n fireTokens: currentPlayer.fireTokens ?? [],\n cavemen: currentPlayer.cavemen ?? [],\n });\n};\n\nexport const recruitCavemanUseCase: RecruitCavemanUseCase = (\n game,\n lordId,\n cavemanId,\n position,\n resourcePositions,\n) => {\n const context = resolveRecruitment(game, lordId);\n if (isErr(context)) {\n return context;\n }\n\n const {\n player: currentPlayer,\n origins,\n caveBoard,\n resources,\n fireTokens,\n cavemen,\n } = context.value;\n\n // Taking a visible caveman costs 2 different resources, one from the draw\n // pile costs 4 different resources\n const cost = getRecruitmentCost(caveBoard, cavemanId);\n\n if (!cost) {\n return err(ErrorCode.CAVEMAN_NOT_FOUND);\n }\n\n if (\n !isValidResourcePayment(\n resources,\n resourcePositions,\n cost.resourceCount,\n cost.differentTypes,\n )\n ) {\n return err(ErrorCode.INSUFFICIENT_RESOURCES);\n }\n\n // Validate caveman placement position\n if (\n !isValidCavemanPosition(\n currentPlayer.kingdom,\n position,\n fireTokens,\n resources,\n cavemen,\n )\n ) {\n return err(ErrorCode.INVALID_CAVEMAN_PLACEMENT);\n }\n\n // Take caveman from board\n const cavemanResult =\n cost.source === \"visible\"\n ? takeCavemanFromVisible(caveBoard, cavemanId)\n : takeCavemanFromDrawPile(caveBoard, cavemanId);\n\n if (!cavemanResult) {\n return err(ErrorCode.CAVEMAN_NOT_FOUND);\n }\n\n // Spend resources\n const updatedResources = spendResources(resources, resourcePositions);\n\n // Place caveman\n const updatedCavemen = [\n ...cavemen,\n { caveman: cavemanResult.caveman, position },\n ];\n\n const updatedPlayers = game.players.map((player) => {\n if (player.id === currentPlayer.id) {\n return {\n ...player,\n resources: updatedResources,\n cavemen: updatedCavemen,\n };\n }\n return player;\n });\n\n const updatedOrigins = {\n ...origins,\n caveBoard: cavemanResult.updatedBoard,\n };\n\n // Recruitment happens after the lord picked its new domino: chooseDomino\n // already ended this lord's turn. When that pick completed the round, the\n // lords have been reset for the next turn and must stay untouched, otherwise\n // this lord would lose its next placement and pick.\n const nextGameAction: GameState = advanceToNextLordOrResult(\n { ...game, players: updatedPlayers, origins: updatedOrigins },\n game.lords,\n );\n\n return ok(nextGameAction);\n};\n","import { isAgeOfGiantsQueenDominoMode } from \"@core/domain/entities/ageOfGiantsHelpers.js\";\nimport {\n allLordsHavePlayed,\n nextAgeOfGiantsAction,\n nextLordWithAction,\n nextOriginsAction,\n nextQueenDominoAction,\n} from \"@core/domain/entities/lord.js\";\nimport { isTribeMode } from \"@core/domain/entities/originsHelpers.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameStateResult,\n type GameWithNextAction,\n gameSteps,\n type NextAction,\n} from \"@core/domain/types/game.js\";\nimport {\n type PlayerActions,\n playerActions,\n} from \"@core/domain/types/player.js\";\nimport { err, isErr, ok, type Result } from \"@utils/result.js\";\n\nexport type SkipOptionalActionUseCase = (\n game: GameWithNextAction,\n lordId: string,\n) => GameStateResult;\n\n// Queendomino optional actions\nconst isQueenDominoOptional = (action: PlayerActions): boolean =>\n action === playerActions.placeKnight ||\n action === playerActions.constructBuilding ||\n action === playerActions.useDragon;\n\n// Origins optional actions\nconst isOriginsOptional = (action: PlayerActions): boolean =>\n action === playerActions.placeFireToken ||\n action === playerActions.recruitCaveman;\n\n// Age of Giants optional action: only sendGiant. placeGiant is mandatory and\n// cannot be skipped (placeDomino never asks for it when no crown is free).\nconst isAoGOptional = (action: PlayerActions): boolean =>\n action === playerActions.sendGiant;\n\n/**\n * Whether `action` is an optional action that `skipOptionalAction` accepts.\n * `placeDomino`, `pickDomino`, `pass` and `placeGiant` cannot be skipped.\n */\nexport const isSkippableAction = (action: PlayerActions): boolean =>\n isQueenDominoOptional(action) ||\n isOriginsOptional(action) ||\n isAoGOptional(action);\n\n/**\n * Checks that `lordId` may skip the current action and returns that action.\n * Shared with `canSkipOptionalAction` so both apply the same checks.\n */\nexport const resolveSkip = (\n game: GameWithNextAction,\n lordId: string,\n): Result<PlayerActions> => {\n const currentAction = game.nextAction;\n\n if (currentAction.nextLord !== lordId) {\n return err(ErrorCode.NOT_YOUR_TURN);\n }\n\n if (!isSkippableAction(currentAction.nextAction)) {\n return err(ErrorCode.INVALID_OPTIONAL_ACTION);\n }\n\n return ok(currentAction.nextAction);\n};\n\nexport const skipOptionalActionUseCase: SkipOptionalActionUseCase = (\n game,\n lordId,\n) => {\n const skip = resolveSkip(game, lordId);\n if (isErr(skip)) {\n return skip;\n }\n\n const action = skip.value;\n\n if (isAoGOptional(action)) {\n return handleAoGSkip(game, lordId, action);\n }\n\n if (isOriginsOptional(action)) {\n return handleOriginsSkip(game, lordId, action);\n }\n\n // Queendomino skip logic\n const nextAction = nextQueenDominoAction(action);\n\n if (nextAction === playerActions.pickDomino) {\n return advanceToNextLordOrResult(game);\n }\n\n return ok({\n ...game,\n nextAction: {\n type: \"action\",\n nextLord: lordId,\n nextAction: nextAction,\n },\n });\n};\n\nconst handleOriginsSkip = (\n game: GameWithNextAction,\n lordId: string,\n action: string,\n): GameStateResult => {\n // Clear pending fire token if skipping fire token placement\n let updatedOrigins = game.origins;\n if (\n action === playerActions.placeFireToken &&\n updatedOrigins?.pendingFireToken\n ) {\n updatedOrigins = {\n ...updatedOrigins,\n pendingFireToken: undefined,\n };\n }\n\n const tribe = isTribeMode(game.mode.name);\n const nextAction = nextOriginsAction(\n action as typeof playerActions.placeFireToken,\n tribe,\n );\n\n const updatedGame = {\n ...game,\n ...(updatedOrigins !== undefined && { origins: updatedOrigins }),\n };\n\n // pickDomino means we're done with pre-pick optional actions\n if (nextAction === playerActions.pickDomino) {\n return advanceToNextLordOrResult(updatedGame);\n }\n\n // recruitCaveman is the final optional action in Tribe mode\n // The turn transition already happened in chooseDomino, just advance\n if (action === playerActions.recruitCaveman) {\n return advanceToNextLordOrResult(updatedGame);\n }\n\n return ok({\n ...updatedGame,\n nextAction: {\n type: \"action\",\n nextLord: lordId,\n nextAction: nextAction,\n },\n });\n};\n\nconst handleAoGSkip = (\n game: GameWithNextAction,\n lordId: string,\n action: string,\n): GameStateResult => {\n const isAoGQD = isAgeOfGiantsQueenDominoMode(game.mode.name);\n const nextAction = nextAgeOfGiantsAction(\n action as typeof playerActions.sendGiant,\n isAoGQD,\n );\n\n if (nextAction === playerActions.pickDomino) {\n return advanceToNextLordOrResult(game);\n }\n\n // More optional actions (e.g., QD actions in AoG-QD mode)\n return ok({\n ...game,\n nextAction: {\n type: \"action\",\n nextLord: lordId,\n nextAction: nextAction,\n },\n });\n};\n\nconst advanceToNextLordOrResult = (\n game: GameWithNextAction,\n): GameStateResult => {\n const maxTurns = game.rules.basic.maxTurns;\n const isLastTurn = game.turn === maxTurns;\n\n if (isLastTurn && allLordsHavePlayed(game.lords)) {\n return ok({\n ...game,\n nextAction: { type: \"step\", step: gameSteps.result },\n });\n }\n\n return ok({\n ...game,\n nextAction: nextLordWithAction(game.lords) as NextAction,\n });\n};\n","import {\n isValidConstructionPosition,\n purchaseBuilding,\n} from \"@core/domain/entities/building.js\";\nimport {\n getRecruitmentCost,\n isValidCavemanPosition,\n type RecruitmentCost,\n} from \"@core/domain/entities/caveman.js\";\nimport { getValidFireTokenPositions } from \"@core/domain/entities/fireToken.js\";\nimport {\n hasGiantAtIndex,\n placeGiantOnCrown,\n} from \"@core/domain/entities/giant.js\";\nimport { canPlaceKnight } from \"@core/domain/entities/knight.js\";\nimport { getValidResourcePayments } from \"@core/domain/entities/resource.js\";\nimport type { BuildingTile } from \"@core/domain/types/building.js\";\nimport {\n type GameState,\n type GameWithNextAction,\n isGameWithNextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Kingdom, Position } from \"@core/domain/types/kingdom.js\";\nimport {\n type PlayerActions,\n playerActions,\n} from \"@core/domain/types/player.js\";\nimport { isErr, isOk } from \"@utils/result.js\";\nimport { resolveConstruction } from \"./constructBuilding.js\";\nimport { resolveFireTokenPlacement } from \"./placeFireToken.js\";\nimport { resolveGiantPlacement } from \"./placeGiant.js\";\nimport { resolveKnightPlacement } from \"./placeKnight.js\";\nimport { resolveRecruitment } from \"./recruitCaveman.js\";\nimport { resolveGiantSender, resolveGiantTarget } from \"./sendGiant.js\";\nimport { resolveSkip } from \"./skipOptionalAction.js\";\n\n/*\n * Valid targets of the extension actions (Queendomino, Origins, Age of Giants).\n *\n * Each query reuses the checks of the matching use case (its `resolve*`\n * function) and the very predicate that use case applies to its target, then\n * keeps every candidate that predicate accepts. A target returned here is\n * therefore accepted by the action, and a target left out is refused by it.\n *\n * Every query takes any game state and an optional lord (default: the lord who\n * must play) and answers empty (`[]`, `false`) when the action does not apply.\n */\n\n/**\n * A caveman of the cave board that can be recruited now, with every valid way\n * to pay for it (Origins Tribe).\n */\nexport type CavemanRecruitmentOption = {\n /** Caveman to pass as `cavemanId` to `recruitCaveman` */\n cavemanId: number;\n /** Visible caveman (2 different resources) or draw pile (4 different) */\n source: RecruitmentCost[\"source\"];\n /** Every valid `resourcePositions` payment for this caveman */\n resourceCombinations: Position[][];\n};\n\n/**\n * Valid `recruitCaveman` arguments: any option, any of its resource\n * combinations and any position can be combined. Both lists are empty when\n * no recruitment is possible.\n */\nexport type ValidCavemanPlacements = {\n /** Recruitable cavemen with their valid payments */\n options: CavemanRecruitmentOption[];\n /** Squares where the recruited caveman can be placed */\n positions: Position[];\n};\n\n/**\n * Valid `sendGiant` arguments: any giant index can be sent to any target\n * player. Both lists are empty when no giant can be sent. The crown covered is\n * chosen by the targeted opponent (see `getValidGiantPositions`).\n */\nexport type ValidGiantTargets = {\n /** Indexes in the sender's `giants` array that can be sent */\n giantIndexes: number[];\n /** Opponents that can receive a giant */\n targetPlayerIds: string[];\n};\n\n/** Signature shared by the valid-target queries. */\nexport type ValidActionTargetsUseCase<T> = (\n game: GameState,\n lordId?: string,\n) => T;\n\ntype LordTurn = { game: GameWithNextAction; lordId: string };\n\n/**\n * The game and lord to check when `action` is the action the game waits for\n * (the same gate as the action's handler), or null otherwise.\n */\nconst turnFor = (\n game: GameState,\n action: PlayerActions,\n lordId: string | undefined,\n): LordTurn | null => {\n if (!isGameWithNextAction(game) || game.nextAction.nextAction !== action) {\n return null;\n }\n return { game, lordId: lordId ?? game.nextAction.nextLord };\n};\n\n/** Every square of a kingdom grid, row by row. */\nconst kingdomPositions = (kingdom: Kingdom): Position[] =>\n kingdom.flatMap((row, y) => row.map((_, x) => ({ x, y })));\n\n/**\n * Squares where `placeFireToken` accepts the pending fire token (Origins).\n */\nexport const getValidFireTokenPositionsUseCase: ValidActionTargetsUseCase<\n Position[]\n> = (game, lordId) => {\n const turn = turnFor(game, playerActions.placeFireToken, lordId);\n if (!turn) return [];\n\n const context = resolveFireTokenPlacement(turn.game, turn.lordId);\n if (isErr(context)) return [];\n\n const { player, pending, existingTokens } = context.value;\n return getValidFireTokenPositions(\n player.kingdom,\n pending.volcanoPosition,\n pending.fires,\n existingTokens,\n );\n};\n\n/**\n * Squares where `placeKnight` accepts a knight: squares of the domino just\n * placed, within the knight limit, one knight per territory (Queendomino).\n */\nexport const getValidKnightPositionsUseCase: ValidActionTargetsUseCase<\n Position[]\n> = (game, lordId) => {\n const turn = turnFor(game, playerActions.placeKnight, lordId);\n if (!turn) return [];\n\n const context = resolveKnightPlacement(turn.game, turn.lordId);\n if (isErr(context)) return [];\n\n const { player, allowedPositions } = context.value;\n return kingdomPositions(player.kingdom).filter((position) =>\n canPlaceKnight(player, player.kingdom, position, allowedPositions),\n );\n};\n\ntype ConstructionOptions = { positions: Position[]; buildings: BuildingTile[] };\n\nconst noConstruction = (): ConstructionOptions => ({\n positions: [],\n buildings: [],\n});\n\nconst getConstructionOptions = (\n game: GameState,\n lordId: string | undefined,\n): ConstructionOptions => {\n const turn = turnFor(game, playerActions.constructBuilding, lordId);\n if (!turn) return noConstruction();\n\n const context = resolveConstruction(turn.game, turn.lordId);\n if (isErr(context)) return noConstruction();\n\n const { player, queendomino } = context.value;\n const board = queendomino.buildersBoard;\n\n const positions = kingdomPositions(player.kingdom).filter((position) =>\n isValidConstructionPosition(\n player.kingdom,\n player.buildings ?? [],\n position,\n ),\n );\n const buildings = board.slots.filter(\n (slot): slot is BuildingTile =>\n slot !== null && purchaseBuilding(board, player, slot.id) !== null,\n );\n\n // A construction needs both a free construction square and a building\n if (positions.length === 0 || buildings.length === 0) return noConstruction();\n return { positions, buildings };\n};\n\n/**\n * Construction squares where `constructBuilding` succeeds with any building of\n * `getAffordableBuildings` (Queendomino). Empty when no building can be bought.\n */\nexport const getValidBuildingPositionsUseCase: ValidActionTargetsUseCase<\n Position[]\n> = (game, lordId) => getConstructionOptions(game, lordId).positions;\n\n/**\n * Buildings of the Builders Board that `constructBuilding` accepts (the player\n * can pay for them), on any square of `getValidBuildingPositions`\n * (Queendomino). Empty when no construction square is free.\n */\nexport const getAffordableBuildingsUseCase: ValidActionTargetsUseCase<\n BuildingTile[]\n> = (game, lordId) => getConstructionOptions(game, lordId).buildings;\n\nconst noRecruitment = (): ValidCavemanPlacements => ({\n options: [],\n positions: [],\n});\n\n/**\n * Valid `recruitCaveman` arguments: recruitable cavemen with every valid\n * payment, and the squares where the caveman can be placed (Origins Tribe).\n */\nexport const getValidCavemanPlacementsUseCase: ValidActionTargetsUseCase<\n ValidCavemanPlacements\n> = (game, lordId) => {\n const turn = turnFor(game, playerActions.recruitCaveman, lordId);\n if (!turn) return noRecruitment();\n\n const context = resolveRecruitment(turn.game, turn.lordId);\n if (isErr(context)) return noRecruitment();\n\n const { player, caveBoard, resources, fireTokens, cavemen } = context.value;\n\n const positions = kingdomPositions(player.kingdom).filter((position) =>\n isValidCavemanPosition(\n player.kingdom,\n position,\n fireTokens,\n resources,\n cavemen,\n ),\n );\n if (positions.length === 0) return noRecruitment();\n\n // Payments only depend on the cost, shared by every caveman of a source\n const paymentsByCost = new Map<string, Position[][]>();\n const paymentsFor = (cost: RecruitmentCost): Position[][] => {\n const key = `${cost.resourceCount}/${cost.differentTypes}`;\n let payments = paymentsByCost.get(key);\n if (!payments) {\n payments = getValidResourcePayments(\n resources,\n cost.resourceCount,\n cost.differentTypes,\n );\n paymentsByCost.set(key, payments);\n }\n return payments;\n };\n\n const options: CavemanRecruitmentOption[] = [];\n for (const caveman of [...caveBoard.visible, ...caveBoard.drawPile]) {\n const cost = getRecruitmentCost(caveBoard, caveman.id);\n if (!cost) continue;\n const resourceCombinations = paymentsFor(cost);\n if (resourceCombinations.length > 0) {\n options.push({\n cavemanId: caveman.id,\n source: cost.source,\n resourceCombinations,\n });\n }\n }\n\n if (options.length === 0) return noRecruitment();\n return { options, positions };\n};\n\n/**\n * Crowns where `placeGiant` accepts the giant (Age of Giants). When a giant\n * was sent by an opponent (`ageOfGiants.pendingGiant`), these are the crowns\n * of the targeted player, who is the lord to play.\n */\nexport const getValidGiantPositionsUseCase: ValidActionTargetsUseCase<\n Position[]\n> = (game, lordId) => {\n const turn = turnFor(game, playerActions.placeGiant, lordId);\n if (!turn) return [];\n\n const context = resolveGiantPlacement(turn.game, turn.lordId);\n if (isErr(context)) return [];\n\n const { player } = context.value;\n return kingdomPositions(player.kingdom).filter((position) =>\n isOk(placeGiantOnCrown(player, position)),\n );\n};\n\nconst noGiantTarget = (): ValidGiantTargets => ({\n giantIndexes: [],\n targetPlayerIds: [],\n});\n\n/**\n * Valid `sendGiant` arguments: the giants the lord can send and the opponents\n * that can receive one (Age of Giants).\n */\nexport const getValidGiantTargetsUseCase: ValidActionTargetsUseCase<\n ValidGiantTargets\n> = (game, lordId) => {\n const turn = turnFor(game, playerActions.sendGiant, lordId);\n if (!turn) return noGiantTarget();\n\n const sender = resolveGiantSender(turn.game, turn.lordId);\n if (isErr(sender)) return noGiantTarget();\n\n const source = sender.value;\n const giantIndexes = (source.giants ?? [])\n .map((_, index) => index)\n .filter((index) => hasGiantAtIndex(source, index));\n const targetPlayerIds = turn.game.players\n .filter((player) => isOk(resolveGiantTarget(turn.game, source, player.id)))\n .map((player) => player.id);\n\n if (giantIndexes.length === 0 || targetPlayerIds.length === 0) {\n return noGiantTarget();\n }\n return { giantIndexes, targetPlayerIds };\n};\n\n/**\n * Whether `skipOptionalAction` accepts to skip the current action for the lord\n * (false for `placeGiant`, which is mandatory, and for non-optional actions).\n */\nexport const canSkipOptionalActionUseCase: ValidActionTargetsUseCase<\n boolean\n> = (game, lordId) =>\n isGameWithNextAction(game) &&\n isOk(resolveSkip(game, lordId ?? game.nextAction.nextLord));\n","import {\n isAgeOfGiantsMode,\n isAgeOfGiantsQueenDominoMode,\n isFootprintDomino,\n isGiantDomino,\n} from \"@core/domain/entities/ageOfGiantsHelpers.js\";\nimport { takeFireToken } from \"@core/domain/entities/fireToken.js\";\nimport {\n findCrownsNotCoveredByGiants,\n playerHasGiant,\n} from \"@core/domain/entities/giant.js\";\nimport {\n calculateDominoPosition,\n placeDomino,\n} from \"@core/domain/entities/kingdom.js\";\nimport {\n advanceToNextLordOrResult,\n allLordsHavePlayed,\n canPlaceAndDominoPickedIsDefined,\n nextLordWithAction,\n} from \"@core/domain/entities/lord.js\";\nimport {\n isOriginsMode,\n isResourceMode,\n} from \"@core/domain/entities/originsHelpers.js\";\nimport { createResourceForTile } from \"@core/domain/entities/resource.js\";\nimport { refreshTotemHolders } from \"@core/domain/entities/totem.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameState,\n type GameStateResult,\n type GameWithNextAction,\n gameSteps,\n type NextAction,\n type NextStep,\n} from \"@core/domain/types/game.js\";\nimport type { Position, Rotation } from \"@core/domain/types/kingdom.js\";\nimport type { PendingFireToken, Resource } from \"@core/domain/types/origins.js\";\nimport {\n type PlayerActions,\n playerActions,\n} from \"@core/domain/types/player.js\";\nimport { err, isErr, isOk, ok } from \"@utils/result.js\";\n\nexport type PlaceDominoUseCase = (\n game: GameWithNextAction,\n lordId: string,\n position: Position,\n rotation: Rotation,\n) => GameStateResult;\n\n/**\n * Finds the volcano tile position(s) in a just-placed domino.\n * Returns the first volcano tile with craters, or undefined.\n */\nconst findVolcanoInDomino = (\n game: GameWithNextAction,\n position: Position,\n rotation: Rotation,\n): { craters: number; volcanoPosition: Position } | undefined => {\n const lord = game.lords.find((l) => l.id === game.nextAction.nextLord);\n if (!lord?.dominoPicked) return undefined;\n\n const [first, second] = calculateDominoPosition(\n position,\n rotation,\n lord.dominoPicked,\n );\n\n for (const placed of [first, second]) {\n if (\n placed.tile.type === \"volcano\" &&\n placed.tile.volcanoCraters &&\n placed.tile.volcanoCraters > 0\n ) {\n return {\n craters: placed.tile.volcanoCraters,\n volcanoPosition: placed.position,\n };\n }\n }\n return undefined;\n};\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 // Collect resources from placed tiles (Totem/Tribe modes)\n const newResources: Resource[] = [];\n if (isResourceMode(game.mode.name)) {\n const [first, second] = calculateDominoPosition(position, rotation, domino);\n for (const placed of [first, second]) {\n const resource = createResourceForTile(placed.tile, placed.position);\n if (resource) {\n newResources.push(resource);\n }\n }\n }\n\n const updatedPlayers = game.players.map((player) => {\n if (player.id === currentPlayer.id) {\n const updated = { ...player, kingdom: updatedKingdom.value };\n if (newResources.length > 0 && updated.resources) {\n updated.resources = [...updated.resources, ...newResources];\n }\n return updated;\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 const isQueenDomino = game.mode.name === \"QueenDomino\";\n const isOrigins = isOriginsMode(game.mode.name);\n const isAoG = isAgeOfGiantsMode(game.mode.name);\n const isAoGQD = isAgeOfGiantsQueenDominoMode(game.mode.name);\n\n if (\n isLastTurn &&\n allLordsHavePlayed(updatedLords) &&\n !isQueenDomino &&\n !isOrigins &&\n !isAoG\n ) {\n updatedGame = {\n ...game,\n lords: updatedLords,\n nextAction: resultStep,\n players: updatedPlayers,\n };\n } else if (isQueenDomino && !isLastTurn) {\n // In QueenDomino, after placing a domino, the same lord gets optional actions\n updatedGame = {\n ...game,\n lords: updatedLords,\n nextAction: {\n type: \"action\",\n nextLord: currentLord.id,\n nextAction: playerActions.placeKnight,\n },\n players: updatedPlayers,\n };\n } else if (isQueenDomino && isLastTurn) {\n // Last turn in QueenDomino: optional actions before checking if all lords done\n const queenDominoAction: NextAction = {\n type: \"action\",\n nextLord: currentLord.id,\n nextAction: playerActions.placeKnight,\n };\n updatedGame = {\n ...game,\n lords: updatedLords,\n nextAction: queenDominoAction,\n players: updatedPlayers,\n };\n } else if (isOrigins) {\n // Origins: Totem mode re-evaluates totem holders as soon as resources change\n let updatedOrigins = refreshTotemHolders(game.origins, updatedPlayers);\n\n // Origins: check for volcano to grant fire token\n const volcano = findVolcanoInDomino(game, position, rotation);\n const tokenResult =\n volcano && updatedOrigins\n ? takeFireToken(updatedOrigins.fireTokenPool, volcano.craters)\n : undefined;\n\n if (volcano && updatedOrigins && tokenResult && isOk(tokenResult)) {\n // Grant fire token and set pending for placement\n const pendingFireToken: PendingFireToken = {\n fires: tokenResult.value.fires,\n volcanoPosition: volcano.volcanoPosition,\n };\n updatedOrigins = {\n ...updatedOrigins,\n fireTokenPool: tokenResult.value.updatedPool,\n pendingFireToken,\n };\n\n // Route to placeFireToken action\n updatedGame = {\n ...game,\n lords: updatedLords,\n players: updatedPlayers,\n origins: updatedOrigins,\n nextAction: {\n type: \"action\",\n nextLord: currentLord.id,\n nextAction: playerActions.placeFireToken,\n },\n };\n } else {\n // No volcano, or pool empty for this crater type: the game only ends\n // once every lord has finished the last turn\n updatedGame = advanceToNextLordOrResult(\n {\n ...game,\n players: updatedPlayers,\n ...(updatedOrigins !== undefined && { origins: updatedOrigins }),\n },\n updatedLords,\n );\n }\n } else if (isAoG) {\n // Age of Giants: check for giant/footprint domino effects\n const currentPlayer = updatedPlayers.find(\n (p) => p.id === currentLord.playerId,\n );\n const isGiant = isGiantDomino(domino);\n const isFootprint = isFootprintDomino(domino);\n\n let aogAction: PlayerActions | null = null;\n\n if (isGiant) {\n // Giant domino: must place giant on a crown (mandatory)\n // But auto-skip if player has no uncovered crowns or pool is empty\n const hasUncoveredCrowns =\n currentPlayer &&\n findCrownsNotCoveredByGiants(\n currentPlayer.kingdom,\n currentPlayer.giants ?? [],\n ).length > 0;\n const poolAvailable = (game.ageOfGiants?.giantPool ?? 0) > 0;\n\n if (hasUncoveredCrowns && poolAvailable) {\n aogAction = playerActions.placeGiant;\n }\n } else if (isFootprint) {\n // Footprint domino: may send a giant to opponent (optional)\n // But only if player has a giant in their kingdom\n if (currentPlayer && playerHasGiant(currentPlayer)) {\n aogAction = playerActions.sendGiant;\n }\n }\n\n if (aogAction) {\n updatedGame = {\n ...game,\n lords: updatedLords,\n players: updatedPlayers,\n nextAction: {\n type: \"action\",\n nextLord: currentLord.id,\n nextAction: aogAction,\n },\n };\n } else if (isAoGQD) {\n // No AoG action but still need QueenDomino actions\n updatedGame = {\n ...game,\n lords: updatedLords,\n players: updatedPlayers,\n nextAction: {\n type: \"action\",\n nextLord: currentLord.id,\n nextAction: playerActions.placeKnight,\n },\n };\n } else 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: nextLordWithAction(updatedLords) as NextAction,\n players: updatedPlayers,\n };\n }\n } else {\n updatedGame = {\n ...game,\n lords: updatedLords,\n nextAction: nextLordWithAction(updatedLords) as NextAction,\n players: updatedPlayers,\n };\n }\n\n // Queendomino (incl. AoG-QD): remember the squares of the domino just\n // placed, since knights may only be placed on them.\n if (updatedGame.queendomino) {\n const [first, second] = calculateDominoPosition(position, rotation, domino);\n updatedGame = {\n ...updatedGame,\n queendomino: {\n ...updatedGame.queendomino,\n lastPlacedPositions: [first.position, second.position],\n },\n };\n }\n\n return ok(updatedGame);\n};\n","import {\n discardFromAgeOfGiantsLine,\n isAgeOfGiantsQueenDominoMode,\n} from \"@core/domain/entities/ageOfGiantsHelpers.js\";\nimport { createBuildersBoard } from \"@core/domain/entities/building.js\";\nimport { createCaveBoard } from \"@core/domain/entities/caveman.js\";\nimport { createLord } from \"@core/domain/entities/lord\";\nimport { isTribeMode } from \"@core/domain/entities/originsHelpers.js\";\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 sortedLine = dominoesCopy.splice(0, dominoesPerTurn);\n sortedLine.sort((a, b) => a.number - b.number);\n\n // Age of Giants: discard the dominos at the official positions of the\n // sorted line (middle one at 2/4 players, 2nd and 4th at 3 players)\n const dominoesDrawn = discardFromAgeOfGiantsLine(\n sortedLine,\n game.rules.basic.dominoesDiscardedPerTurn ?? 0,\n );\n\n const nextAction: NextAction = {\n type: \"action\",\n nextLord: shuffledLords[0]!.id,\n nextAction: playerActions.pickDomino,\n };\n\n // Setup Builders Board for QueenDomino mode (including AoG-QD)\n let queendomino = game.queendomino;\n if (\n queendomino &&\n (game.mode.name === \"QueenDomino\" ||\n isAgeOfGiantsQueenDominoMode(game.mode.name))\n ) {\n const buildingShuffle = game.seed\n ? createSeededShuffle(game.seed, \"buildings\")\n : shuffleMethod;\n const board = createBuildersBoard(\n queendomino.buildersBoard.drawPile,\n buildingShuffle,\n );\n queendomino = { ...queendomino, buildersBoard: board };\n }\n\n // Setup Cave Board for Tribe mode\n let origins = game.origins;\n if (origins?.caveBoard && isTribeMode(game.mode.name)) {\n const caveShuffle = game.seed\n ? createSeededShuffle(game.seed, \"cavemen\")\n : shuffleMethod;\n const board = createCaveBoard(origins.caveBoard.drawPile, caveShuffle);\n origins = { ...origins, caveBoard: board };\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 ...(queendomino !== undefined && { queendomino }),\n ...(origins !== undefined && { origins }),\n };\n\n return ok(newState);\n };\n","import { destroyWithDragon } from \"@core/domain/entities/building.js\";\nimport {\n allLordsHavePlayed,\n nextLordWithAction,\n} from \"@core/domain/entities/lord.js\";\nimport { ErrorCode } from \"@core/domain/errors/domainErrors.js\";\nimport {\n type GameStateResult,\n type GameWithNextAction,\n gameSteps,\n type NextAction,\n} from \"@core/domain/types/game.js\";\nimport { playerActions } from \"@core/domain/types/player.js\";\nimport { err, ok } from \"@utils/result.js\";\n\nexport type UseDragonUseCase = (\n game: GameWithNextAction,\n lordId: string,\n buildingId: number,\n) => GameStateResult;\n\nexport const useDragonUseCase: UseDragonUseCase = (\n game,\n lordId,\n buildingId,\n) => {\n const currentAction = game.nextAction;\n\n if (currentAction.nextLord !== lordId) {\n return err(ErrorCode.NOT_YOUR_TURN);\n }\n\n if (currentAction.nextAction !== playerActions.useDragon) {\n return err(ErrorCode.INVALID_OPTIONAL_ACTION);\n }\n\n if (!game.queendomino) {\n return err(ErrorCode.INVALID_OPTIONAL_ACTION);\n }\n\n if (\n !game.queendomino.dragonAvailable ||\n game.queendomino.dragonUsedThisRound\n ) {\n return err(ErrorCode.DRAGON_UNAVAILABLE);\n }\n\n const currentLord = game.lords.find((l) => l.id === lordId);\n if (!currentLord) return err(ErrorCode.LORD_NOT_FOUND);\n\n const currentPlayer = game.players.find((p) => p.id === currentLord.playerId);\n if (!currentPlayer) return err(ErrorCode.PLAYER_NOT_FOUND);\n\n // Queen holder cannot use dragon\n if (game.queendomino.queenHolderId === currentPlayer.id) {\n return err(ErrorCode.QUEEN_HOLDER_CANNOT_USE_DRAGON);\n }\n\n const result = destroyWithDragon(\n game.queendomino.buildersBoard,\n buildingId,\n currentPlayer,\n );\n\n if (!result) {\n return err(ErrorCode.BUILDING_NOT_FOUND);\n }\n\n const { updatedBoard, updatedPlayer } = result;\n\n const updatedPlayers = game.players.map((p) =>\n p.id === currentPlayer.id ? updatedPlayer : p,\n );\n\n // After dragon, advance to pickDomino (or result)\n const maxTurns = game.rules.basic.maxTurns;\n const isLastTurn = game.turn === maxTurns;\n\n if (isLastTurn && allLordsHavePlayed(game.lords)) {\n return ok({\n ...game,\n players: updatedPlayers,\n queendomino: {\n ...game.queendomino,\n buildersBoard: updatedBoard,\n dragonUsedThisRound: true,\n },\n nextAction: { type: \"step\", step: gameSteps.result },\n });\n }\n\n return ok({\n ...game,\n players: updatedPlayers,\n queendomino: {\n ...game.queendomino,\n buildersBoard: updatedBoard,\n dragonUsedThisRound: true,\n },\n nextAction: <NextAction>nextLordWithAction(game.lords),\n });\n};\n","import { consoleLogger, silentLogger } from \"@adapter/consoleLogger.js\";\nimport jsonBuildings from \"@adapter/jsonBuildings.js\";\nimport jsonCavemen from \"@adapter/jsonCavemen.js\";\nimport jsonDominoes from \"@adapter/jsonDominoes.js\";\nimport jsonModes from \"@adapter/jsonModes.js\";\nimport jsonQuestTiles from \"@adapter/jsonQuestTiles.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 { calculatePlayerScoreHandler } from \"@application/handlers/calculatePlayerScoreHandler.js\";\nimport { calculateScoreHandler } from \"@application/handlers/calculateScoreHandler.js\";\nimport { canPlaceDominoHandler } from \"@application/handlers/canPlaceDominoHandler.js\";\nimport { chooseDominoHandler } from \"@application/handlers/chooseDominoHandler.js\";\nimport { constructBuildingHandler } from \"@application/handlers/constructBuildingHandler.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 { getValidActionTargetsHandler } from \"@application/handlers/getValidActionTargetsHandler.js\";\nimport { getValidPlacementsHandler } from \"@application/handlers/getValidPlacementsHandler.js\";\nimport { placeDominoHandler } from \"@application/handlers/placeDominoHandler.js\";\nimport { placeFireTokenHandler } from \"@application/handlers/placeFireTokenHandler.js\";\nimport { placeGiantHandler } from \"@application/handlers/placeGiantHandler.js\";\nimport { placeKnightHandler } from \"@application/handlers/placeKnightHandler.js\";\nimport { recruitCavemanHandler } from \"@application/handlers/recruitCavemanHandler.js\";\nimport { sendGiantHandler } from \"@application/handlers/sendGiantHandler.js\";\nimport {\n deserializeGameHandler,\n serializeGameHandler,\n} from \"@application/handlers/serializeGameHandler.js\";\nimport { skipOptionalActionHandler } from \"@application/handlers/skipOptionalActionHandler.js\";\nimport { startGameHandler } from \"@application/handlers/startGameHandler.js\";\nimport { useDragonHandler } from \"@application/handlers/useDragonHandler.js\";\nimport type { Translator } from \"@core/i18n/translations.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 type { GameEngine } from \"@core/portUserside/engine.js\";\nimport { addExtraRulesUseCase } from \"@core/useCases/addExtraRules.js\";\nimport { addPlayersUseCase } from \"@core/useCases/addPlayers.js\";\nimport { calculatePlayerScoreUseCase } from \"@core/useCases/calculatePlayerScore.js\";\nimport { calculateScoreUseCase } from \"@core/useCases/calculateScore.js\";\nimport { chooseDominoUseCase } from \"@core/useCases/chooseDomino.js\";\nimport { constructBuildingUseCase } from \"@core/useCases/constructBuilding.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 canSkipOptionalActionUseCase,\n getAffordableBuildingsUseCase,\n getValidBuildingPositionsUseCase,\n getValidCavemanPlacementsUseCase,\n getValidFireTokenPositionsUseCase,\n getValidGiantPositionsUseCase,\n getValidGiantTargetsUseCase,\n getValidKnightPositionsUseCase,\n} from \"@core/useCases/getValidActionTargets.js\";\nimport {\n canPlaceDominoUseCase,\n getValidPlacementsUseCase,\n} from \"@core/useCases/getValidPlacements.js\";\nimport { placeDominoUseCase } from \"@core/useCases/placeDomino.js\";\nimport { placeFireTokenUseCase } from \"@core/useCases/placeFireToken.js\";\nimport { placeGiantUseCase } from \"@core/useCases/placeGiant.js\";\nimport { placeKnightUseCase } from \"@core/useCases/placeKnight.js\";\nimport { recruitCavemanUseCase } from \"@core/useCases/recruitCaveman.js\";\nimport { sendGiantUseCase } from \"@core/useCases/sendGiant.js\";\nimport { skipOptionalActionUseCase } from \"@core/useCases/skipOptionalAction.js\";\nimport { startGameUseCase } from \"@core/useCases/startGame.js\";\nimport { useDragonUseCase } from \"@core/useCases/useDragon.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 placeGiantHandler: GameEngine[\"placeGiant\"];\n sendGiantHandler: GameEngine[\"sendGiant\"];\n placeKnightHandler: GameEngine[\"placeKnight\"];\n constructBuildingHandler: GameEngine[\"constructBuilding\"];\n useDragonHandler: GameEngine[\"useDragon\"];\n placeFireTokenHandler: GameEngine[\"placeFireToken\"];\n recruitCavemanHandler: GameEngine[\"recruitCaveman\"];\n skipOptionalActionHandler: GameEngine[\"skipOptionalAction\"];\n getValidFireTokenPositionsHandler: GameEngine[\"getValidFireTokenPositions\"];\n getValidKnightPositionsHandler: GameEngine[\"getValidKnightPositions\"];\n getValidBuildingPositionsHandler: GameEngine[\"getValidBuildingPositions\"];\n getAffordableBuildingsHandler: GameEngine[\"getAffordableBuildings\"];\n getValidCavemanPlacementsHandler: GameEngine[\"getValidCavemanPlacements\"];\n getValidGiantPositionsHandler: GameEngine[\"getValidGiantPositions\"];\n getValidGiantTargetsHandler: GameEngine[\"getValidGiantTargets\"];\n canSkipOptionalActionHandler: GameEngine[\"canSkipOptionalAction\"];\n calculatePlayerScoreHandler: GameEngine[\"calculatePlayerScore\"];\n};\n\nexport const configureEngine = (\n config: Partial<EngineConfig>,\n): ConfiguredHandlers => {\n const modeRepository = jsonModes();\n const dominoesRepository = jsonDominoes();\n const buildingsRepository = jsonBuildings();\n const cavemenRepository = jsonCavemen();\n const questTilesRepository = jsonQuestTiles();\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 shuffleMethod: shuffle,\n buildingsRepository,\n cavemenRepository,\n questTilesRepository,\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 }),\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 placeGiantHandler: placeGiantHandler(logger, translator, placeGiantUseCase),\n sendGiantHandler: sendGiantHandler(logger, translator, sendGiantUseCase),\n placeKnightHandler: placeKnightHandler(\n logger,\n translator,\n placeKnightUseCase,\n ),\n constructBuildingHandler: constructBuildingHandler(\n logger,\n translator,\n constructBuildingUseCase,\n ),\n useDragonHandler: useDragonHandler(logger, translator, useDragonUseCase),\n placeFireTokenHandler: placeFireTokenHandler(\n logger,\n translator,\n placeFireTokenUseCase,\n ),\n recruitCavemanHandler: recruitCavemanHandler(\n logger,\n translator,\n recruitCavemanUseCase,\n ),\n skipOptionalActionHandler: skipOptionalActionHandler(\n logger,\n translator,\n skipOptionalActionUseCase,\n ),\n getValidFireTokenPositionsHandler: getValidActionTargetsHandler(\n logger,\n translator,\n \"getValidFireTokenPositions\",\n getValidFireTokenPositionsUseCase,\n (positions) => `${positions.length} positions`,\n ),\n getValidKnightPositionsHandler: getValidActionTargetsHandler(\n logger,\n translator,\n \"getValidKnightPositions\",\n getValidKnightPositionsUseCase,\n (positions) => `${positions.length} positions`,\n ),\n getValidBuildingPositionsHandler: getValidActionTargetsHandler(\n logger,\n translator,\n \"getValidBuildingPositions\",\n getValidBuildingPositionsUseCase,\n (positions) => `${positions.length} positions`,\n ),\n getAffordableBuildingsHandler: getValidActionTargetsHandler(\n logger,\n translator,\n \"getAffordableBuildings\",\n getAffordableBuildingsUseCase,\n (buildings) => `${buildings.length} buildings`,\n ),\n getValidCavemanPlacementsHandler: getValidActionTargetsHandler(\n logger,\n translator,\n \"getValidCavemanPlacements\",\n getValidCavemanPlacementsUseCase,\n ({ options, positions }) =>\n `${options.length} cavemen, ${positions.length} positions`,\n ),\n getValidGiantPositionsHandler: getValidActionTargetsHandler(\n logger,\n translator,\n \"getValidGiantPositions\",\n getValidGiantPositionsUseCase,\n (positions) => `${positions.length} positions`,\n ),\n getValidGiantTargetsHandler: getValidActionTargetsHandler(\n logger,\n translator,\n \"getValidGiantTargets\",\n getValidGiantTargetsUseCase,\n ({ giantIndexes, targetPlayerIds }) =>\n `${giantIndexes.length} giants, ${targetPlayerIds.length} targets`,\n ),\n canSkipOptionalActionHandler: getValidActionTargetsHandler(\n logger,\n translator,\n \"canSkipOptionalAction\",\n canSkipOptionalActionUseCase,\n (canSkip) => `${canSkip}`,\n ),\n calculatePlayerScoreHandler: calculatePlayerScoreHandler(\n logger,\n translator,\n calculatePlayerScoreUseCase,\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 {\n ValidationIssue,\n ValidationSeverity,\n} 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(\n issue(\"id\", \"INVALID_ID\", \"Game id must be a non-empty string\"),\n );\n }\n if (!isNonNegativeInteger(game.turn)) {\n issues.push(\n issue(\"turn\", \"INVALID_TURN\", \"Turn must be a non-negative integer\"),\n );\n }\n if (!Array.isArray(game.dominoes)) {\n issues.push(\n issue(\"dominoes\", \"INVALID_DOMINOES\", \"Dominoes must be an array\"),\n );\n }\n if (!Array.isArray(game.currentDominoes)) {\n issues.push(\n issue(\n \"currentDominoes\",\n \"INVALID_CURRENT_DOMINOES\",\n \"CurrentDominoes must be an array\",\n ),\n );\n }\n if (!Array.isArray(game.players)) {\n issues.push(\n issue(\"players\", \"INVALID_PLAYERS\", \"Players must be an array\"),\n );\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(\n issue(\n \"rules.basic\",\n \"INVALID_BASIC_RULES\",\n \"Rules.basic must be an object\",\n ),\n );\n }\n if (!Array.isArray(game.rules.extra)) {\n issues.push(\n issue(\n \"rules.extra\",\n \"INVALID_EXTRA_RULES\",\n \"Rules.extra must be an array\",\n ),\n );\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(\n issue(\n \"mode.name\",\n \"INVALID_MODE_NAME\",\n \"Mode name must be a non-empty string\",\n ),\n );\n }\n }\n if (!game.nextAction || typeof game.nextAction !== \"object\") {\n issues.push(\n issue(\n \"nextAction\",\n \"INVALID_NEXT_ACTION\",\n \"NextAction must be an object\",\n ),\n );\n } else if (\n game.nextAction.type !== \"action\" &&\n game.nextAction.type !== \"step\"\n ) {\n issues.push(\n issue(\n \"nextAction.type\",\n \"INVALID_NEXT_ACTION_TYPE\",\n \"NextAction.type must be 'action' or 'step'\",\n ),\n );\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(\n issue(path, \"INVALID_TILE\", `Tile at ${path} must be an object`),\n );\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(\n issue(\n `${path}.type`,\n \"INVALID_TILE_TYPE\",\n `Invalid terrain type at ${path}`,\n ),\n );\n }\n if (typeof t.crowns !== \"number\" || t.crowns < 0) {\n issues.push(\n issue(\n `${path}.crowns`,\n \"INVALID_TILE_CROWNS\",\n `Invalid crowns at ${path}`,\n ),\n );\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(\n issue(\n `${path}.id`,\n \"INVALID_PLAYER_ID\",\n `Player id must be a non-empty string`,\n ),\n );\n } else if (playerIds.has(player.id)) {\n issues.push(\n issue(\n `${path}.id`,\n \"DUPLICATE_PLAYER_ID\",\n `Duplicate player id: ${player.id}`,\n ),\n );\n } else {\n playerIds.add(player.id);\n }\n\n if (typeof player.name !== \"string\" || player.name.length < 3) {\n issues.push(\n issue(\n `${path}.name`,\n \"INVALID_PLAYER_NAME\",\n `Player name must be at least 3 characters`,\n ),\n );\n }\n\n // Kingdom validation\n if (!Array.isArray(player.kingdom)) {\n issues.push(\n issue(\n `${path}.kingdom`,\n \"INVALID_KINGDOM\",\n `Kingdom must be a 2D array`,\n ),\n );\n continue;\n }\n if (player.kingdom.length !== GRIDSIZE) {\n issues.push(\n issue(\n `${path}.kingdom`,\n \"INVALID_KINGDOM_GRID\",\n `Kingdom must have ${GRIDSIZE} rows, got ${player.kingdom.length}`,\n ),\n );\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(\n issue(\n `${path}.kingdom[${y}]`,\n \"INVALID_KINGDOM_ROW\",\n `Kingdom row ${y} must have ${GRIDSIZE} columns`,\n ),\n );\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 (\n cell &&\n typeof cell === \"object\" &&\n (cell as Record<string, unknown>).type === \"castle\"\n ) {\n castleCount++;\n }\n }\n }\n if (castleCount === 0) {\n issues.push(\n issue(\n `${path}.kingdom`,\n \"MISSING_CASTLE\",\n `Kingdom must have exactly one castle tile`,\n \"warning\",\n ),\n );\n } else if (castleCount > 1) {\n issues.push(\n issue(\n `${path}.kingdom`,\n \"MULTIPLE_CASTLES\",\n `Kingdom has ${castleCount} castle tiles, expected 1`,\n ),\n );\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(\n issue(\n `${path}.number`,\n \"INVALID_DOMINO_NUMBER\",\n `Domino number must be a positive integer`,\n ),\n );\n } else if (allNumbers.has(domino.number)) {\n issues.push(\n issue(\n `${path}.number`,\n \"DUPLICATE_DOMINO_NUMBER\",\n `Duplicate domino number: ${domino.number}`,\n ),\n );\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(\n issue(\n `${path}.domino`,\n \"INVALID_REVEALED_DOMINO\",\n `Revealed domino must be an object`,\n ),\n );\n continue;\n }\n\n const domino = revealed.domino;\n if (!isPositiveInteger(domino.number)) {\n issues.push(\n issue(\n `${path}.domino.number`,\n \"INVALID_DOMINO_NUMBER\",\n `Domino number must be a positive integer`,\n ),\n );\n } else if (allNumbers.has(domino.number)) {\n issues.push(\n issue(\n `${path}.domino.number`,\n \"DUPLICATE_DOMINO_NUMBER\",\n `Duplicate domino number: ${domino.number}`,\n ),\n );\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(\n issue(\n `${path}`,\n \"PICKED_WITHOUT_LORD\",\n `Domino is marked as picked but has no lordId`,\n ),\n );\n }\n if (!revealed.picked && revealed.lordId !== null) {\n issues.push(\n issue(\n `${path}`,\n \"UNPICKED_WITH_LORD\",\n `Domino is not picked but has a lordId`,\n ),\n );\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(\n issue(\n `${path}.number`,\n \"INVALID_DOMINO_NUMBER\",\n `Domino number must be a positive integer`,\n ),\n );\n } else if (lordPickedNumbers.has(domino.number)) {\n issues.push(\n issue(\n `${path}.number`,\n \"DUPLICATE_DOMINO_NUMBER\",\n `Duplicate domino number among lords: ${domino.number}`,\n ),\n );\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(\n issue(\n `${path}.id`,\n \"INVALID_LORD_ID\",\n `Lord id must be a non-empty string`,\n ),\n );\n } else if (lordIds.has(lord.id)) {\n issues.push(\n issue(\n `${path}.id`,\n \"DUPLICATE_LORD_ID\",\n `Duplicate lord id: ${lord.id}`,\n ),\n );\n } else {\n lordIds.add(lord.id);\n }\n\n if (!isNonEmptyString(lord.playerId)) {\n issues.push(\n issue(\n `${path}.playerId`,\n \"INVALID_LORD_PLAYER_ID\",\n `Lord playerId must be a non-empty string`,\n ),\n );\n } else if (playerIds.size > 0 && !playerIds.has(lord.playerId)) {\n issues.push(\n issue(\n `${path}.playerId`,\n \"LORD_PLAYER_NOT_FOUND\",\n `Lord references non-existent player: ${lord.playerId}`,\n ),\n );\n }\n\n if (lord.turnEnded && (!lord.hasPick || !lord.hasPlace)) {\n issues.push(\n issue(\n path,\n \"INCONSISTENT_LORD_FLAGS\",\n `Lord has turnEnded=true but hasPick=${lord.hasPick}, hasPlace=${lord.hasPlace}`,\n \"warning\",\n ),\n );\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 {\n type: \"action\";\n nextLord?: unknown;\n nextAction?: unknown;\n };\n\n if (!isNonEmptyString(action.nextLord)) {\n issues.push(\n issue(\n \"nextAction.nextLord\",\n \"INVALID_NEXT_LORD\",\n \"nextLord must be a non-empty string\",\n ),\n );\n } else if (\n Array.isArray(game.lords) &&\n !game.lords.some((l) => l.id === action.nextLord)\n ) {\n issues.push(\n issue(\n \"nextAction.nextLord\",\n \"NEXT_LORD_NOT_FOUND\",\n `nextLord references non-existent lord: ${action.nextLord as string}`,\n ),\n );\n }\n\n if (\n typeof action.nextAction !== \"string\" ||\n !validPlayerActions.has(action.nextAction as string)\n ) {\n issues.push(\n issue(\n \"nextAction.nextAction\",\n \"INVALID_PLAYER_ACTION\",\n `nextAction must be one of: ${[...validPlayerActions].join(\", \")}`,\n ),\n );\n }\n } else if (nextAction.type === \"step\") {\n const step = nextAction as { type: \"step\"; step?: unknown };\n\n if (\n typeof step.step !== \"string\" ||\n !validGameSteps.has(step.step as string)\n ) {\n issues.push(\n issue(\n \"nextAction.step\",\n \"INVALID_GAME_STEP\",\n `step must be one of: ${[...validGameSteps].join(\", \")}`,\n ),\n );\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 = [\n \"lords\",\n \"maxDominoes\",\n \"dominoesPerTurn\",\n \"maxTurns\",\n \"maxKingdomSize\",\n ] as const;\n for (const field of fields) {\n const check = allowZero ? isNonNegativeInteger : isPositiveInteger;\n if (!check(basic[field])) {\n issues.push(\n issue(\n `rules.basic.${field}`,\n \"INVALID_BASIC_RULE_VALUE\",\n `rules.basic.${field} must be a positive integer`,\n ),\n );\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(\n issue(\n `rules.extra[${i}].name`,\n \"INVALID_EXTRA_RULE_NAME\",\n `Extra rule name must be a non-empty string`,\n ),\n );\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","/**\n * Mode-aware evaluation and extension-action decisions of the built-in bots\n * (Queendomino, Kingdomino Origins, Age of Giants).\n *\n * Every decision follows the same recipe, without re-implementing any rule:\n * 1. enumerate the valid targets of the action (`getValidActionTargets`, whose\n * targets are guaranteed to be accepted by the action), plus \"skip\" when\n * `canSkipOptionalAction` allows it;\n * 2. simulate each target with the pure use case of the action;\n * 3. evaluate the resulting state with the mode-aware live score\n * (`computePlayerScore`) of the deciding player, plus a small value for the\n * assets the score does not count yet (coins, knights left, Tribe\n * resources), optionally minus the score of the best opponent;\n * 4. keep the best target (the first one on ties, \"skip\" coming first).\n */\n\nimport { getMaxKnights } from \"@core/domain/entities/economy.js\";\nimport {\n calculateDominoPosition,\n placeDomino,\n} from \"@core/domain/entities/kingdom.js\";\nimport {\n isResourceMode,\n isTotemMode,\n isTribeMode,\n} from \"@core/domain/entities/originsHelpers.js\";\nimport { createResourceForTile } from \"@core/domain/entities/resource.js\";\nimport { computePlayerScore } from \"@core/domain/entities/scoreBreakdown.js\";\nimport type { BuildingTile } from \"@core/domain/types/building.js\";\nimport type { Domino } from \"@core/domain/types/domino.js\";\nimport {\n type Game,\n type GameState,\n type GameStateResult,\n type GameWithNextAction,\n isGameWithNextAction,\n} from \"@core/domain/types/game.js\";\nimport type { Position } from \"@core/domain/types/kingdom.js\";\nimport type { Resource } from \"@core/domain/types/origins.js\";\nimport { type Player, playerActions } from \"@core/domain/types/player.js\";\nimport { isOk } from \"@utils/result.js\";\nimport { createSeededRandom } from \"@utils/seededShuffle.js\";\nimport { constructBuildingUseCase } from \"./constructBuilding.js\";\nimport {\n type CavemanRecruitmentOption,\n canSkipOptionalActionUseCase,\n getAffordableBuildingsUseCase,\n getValidBuildingPositionsUseCase,\n getValidCavemanPlacementsUseCase,\n getValidFireTokenPositionsUseCase,\n getValidGiantPositionsUseCase,\n getValidGiantTargetsUseCase,\n getValidKnightPositionsUseCase,\n type ValidCavemanPlacements,\n type ValidGiantTargets,\n} from \"./getValidActionTargets.js\";\nimport type { ValidPlacement } from \"./getValidPlacements.js\";\nimport { placeFireTokenUseCase } from \"./placeFireToken.js\";\nimport { placeGiantUseCase } from \"./placeGiant.js\";\nimport { placeKnightUseCase } from \"./placeKnight.js\";\nimport { recruitCavemanUseCase } from \"./recruitCaveman.js\";\nimport { sendGiantUseCase } from \"./sendGiant.js\";\nimport { useDragonUseCase } from \"./useDragon.js\";\n\n// ─── Contexts and choices (public) ──────────────────────────────────\n\n/**\n * Common part of the context given to a bot strategy for an extension action.\n */\nexport type ExtensionContext = {\n game: GameWithNextAction;\n /** Lord whose action it is (`game.nextAction.nextLord`) */\n lordId: string;\n /**\n * Player who decides: the owner of the lord. For a giant sent by an\n * opponent (`ageOfGiants.pendingGiant`), the targeted player.\n */\n playerId: string;\n /** Whether returning `null` (skipping the action) is allowed */\n canSkip: boolean;\n};\n\n/** `placeKnight` (Queendomino): squares where a knight can go. */\nexport type KnightContext = ExtensionContext & { validPositions: Position[] };\n\n/** `constructBuilding` (Queendomino): any building on any square. */\nexport type BuildingContext = ExtensionContext & {\n validPositions: Position[];\n affordableBuildings: BuildingTile[];\n};\n\n/** A building to construct and its construction square. */\nexport type BuildingChoice = { buildingId: number; position: Position };\n\n/** `useDragon` (Queendomino): buildings of the board the dragon can burn. */\nexport type DragonContext = ExtensionContext & {\n targetBuildings: BuildingTile[];\n};\n\n/** `placeFireToken` (Origins): squares where the pending token can go. */\nexport type FireTokenContext = ExtensionContext & {\n validPositions: Position[];\n};\n\n/** `recruitCaveman` (Origins Tribe): recruitable cavemen and squares. */\nexport type CavemanContext = ExtensionContext & {\n recruitment: ValidCavemanPlacements;\n};\n\n/** A caveman to recruit, where to place it and how to pay for it. */\nexport type CavemanChoice = {\n cavemanId: number;\n position: Position;\n resourcePositions: Position[];\n};\n\n/**\n * `placeGiant` (Age of Giants, mandatory): crowns of the deciding player's\n * kingdom the giant can cover.\n */\nexport type GiantPositionContext = ExtensionContext & {\n validPositions: Position[];\n /** True when the giant was sent by an opponent (`pendingGiant`) */\n sentByOpponent: boolean;\n};\n\n/** `sendGiant` (Age of Giants): giants that can be sent and their targets. */\nexport type SendGiantContext = ExtensionContext & {\n targets: ValidGiantTargets;\n};\n\n/** A giant to send and the opponent receiving it. */\nexport type SendGiantChoice = { giantIndex: number; targetPlayerId: string };\n\n// ─── Context builders ───────────────────────────────────────────────\n\nconst lordOwner = (game: Game, lordId: string): Player | undefined => {\n const lord = game.lords.find((l) => l.id === lordId);\n return lord ? game.players.find((p) => p.id === lord.playerId) : undefined;\n};\n\nconst baseContext = (\n game: GameWithNextAction,\n lordId: string,\n): ExtensionContext => ({\n game,\n lordId,\n playerId: lordOwner(game, lordId)?.id ?? \"\",\n canSkip: canSkipOptionalActionUseCase(game, lordId),\n});\n\nexport const knightContext = (\n game: GameWithNextAction,\n lordId: string,\n): KnightContext => ({\n ...baseContext(game, lordId),\n validPositions: getValidKnightPositionsUseCase(game, lordId),\n});\n\nexport const buildingContext = (\n game: GameWithNextAction,\n lordId: string,\n): BuildingContext => ({\n ...baseContext(game, lordId),\n validPositions: getValidBuildingPositionsUseCase(game, lordId),\n affordableBuildings: getAffordableBuildingsUseCase(game, lordId),\n});\n\n/**\n * Buildings the dragon can burn: there is no valid-target query for the\n * dragon, so every building of the board is tried with the use case itself.\n */\nexport const dragonContext = (\n game: GameWithNextAction,\n lordId: string,\n): DragonContext => {\n const slots = game.queendomino?.buildersBoard.slots ?? [];\n return {\n ...baseContext(game, lordId),\n targetBuildings: slots.filter(\n (slot): slot is BuildingTile =>\n slot !== null && isOk(useDragonUseCase(game, lordId, slot.id)),\n ),\n };\n};\n\nexport const fireTokenContext = (\n game: GameWithNextAction,\n lordId: string,\n): FireTokenContext => ({\n ...baseContext(game, lordId),\n validPositions: getValidFireTokenPositionsUseCase(game, lordId),\n});\n\nexport const cavemanContext = (\n game: GameWithNextAction,\n lordId: string,\n): CavemanContext => ({\n ...baseContext(game, lordId),\n recruitment: getValidCavemanPlacementsUseCase(game, lordId),\n});\n\nexport const giantPositionContext = (\n game: GameWithNextAction,\n lordId: string,\n): GiantPositionContext => ({\n ...baseContext(game, lordId),\n validPositions: getValidGiantPositionsUseCase(game, lordId),\n sentByOpponent: !!game.ageOfGiants?.pendingGiant,\n});\n\nexport const sendGiantContext = (\n game: GameWithNextAction,\n lordId: string,\n): SendGiantContext => ({\n ...baseContext(game, lordId),\n targets: getValidGiantTargetsUseCase(game, lordId),\n});\n\n// ─── Evaluation ─────────────────────────────────────────────────────\n\n/** Value of one coin while coins can still be spent (Queendomino). */\nexport const COIN_VALUE = 0.5;\n/**\n * Value of one knight not placed yet while it can still collect taxes (one\n * coin per construction square of the territory): with `COIN_VALUE` 0.5, a\n * knight is placed for 2 coins of tax or more, kept for a better territory\n * otherwise.\n */\nexport const KNIGHT_VALUE = 0.75;\n/** Value of one resource while it can still pay a caveman (Tribe). */\nexport const TRIBE_RESOURCE_VALUE = 0.5;\n/** Weight of the opponents' total, to break ties (e.g. which opponent to hit). */\nconst OPPONENT_TIE_BREAK = 1e-3;\n\n/**\n * Evaluation settings of a strategy: `opponentWeight` 0 maximizes the own\n * score, 1 maximizes the lead over the best opponent.\n */\nexport type EvaluationProfile = { opponentWeight: number };\n\n/**\n * Share of the game still to be played: assets that only pay off later\n * (coins, knights, Tribe resources) lose their value as the end approaches.\n */\nconst remainingShare = (game: Game): number => {\n const { maxTurns } = game.rules.basic;\n return maxTurns > 0 ? Math.max(0, (maxTurns - game.turn) / maxTurns) : 0;\n};\n\n/**\n * Heuristic value of what the score does not count yet: coins and knights\n * left (Queendomino), resources (Tribe, where they pay cavemen; in Totem they\n * already score one point each).\n */\nconst assetValue = (game: Game, player: Player): number => {\n const share = remainingShare(game);\n if (share === 0) return 0;\n let value = 0;\n if (game.queendomino) {\n value += COIN_VALUE * share * (player.coins ?? 0);\n const knightsLeft = getMaxKnights(player) - (player.knights ?? []).length;\n value += KNIGHT_VALUE * share * Math.max(0, knightsLeft);\n }\n if (isTribeMode(game.mode.name)) {\n value += TRIBE_RESOURCE_VALUE * share * (player.resources ?? []).length;\n }\n return value;\n};\n\n/**\n * Mode-aware live value of a player: score (territories and every bonus of\n * the mode, provisional ones included) plus the asset heuristic.\n */\nexport const playerValue = (game: Game, player: Player): number =>\n computePlayerScore(game, player, false).points + assetValue(game, player);\n\n/**\n * Objective of `playerId` on a game state: own value minus `opponentWeight`\n * times the best opponent's value (and a tiny share of all opponents' values\n * to break ties).\n */\nexport const evaluateState = (\n game: Game,\n playerId: string,\n profile: EvaluationProfile,\n): number => {\n let self = 0;\n let best = 0;\n let total = 0;\n let hasOpponent = false;\n for (const player of game.players) {\n const value = playerValue(game, player);\n if (player.id === playerId) {\n self = value;\n } else {\n total += value;\n best = hasOpponent ? Math.max(best, value) : value;\n hasOpponent = true;\n }\n }\n return self - profile.opponentWeight * best - OPPONENT_TIE_BREAK * total;\n};\n\n/**\n * Evaluator of hypothetical versions of one player (e.g. after a domino\n * placement), used by the domino searches. Opponents are only re-evaluated\n * when the player's kingdom changes their score (Totem majorities).\n */\nexport type PlayerEvaluator = (player: Player) => number;\n\nexport const createPlayerEvaluator = (\n game: Game,\n playerId: string,\n profile: EvaluationProfile,\n): PlayerEvaluator => {\n const withPlayer = (player: Player): Game => ({\n ...game,\n players: game.players.map((p) => (p.id === playerId ? player : p)),\n });\n\n if (isTotemMode(game.mode.name)) {\n return (player) => evaluateState(withPlayer(player), playerId, profile);\n }\n\n // Opponents do not depend on the player's kingdom: compute them once\n const self = game.players.find((p) => p.id === playerId);\n const constant = self\n ? evaluateState(game, playerId, profile) - playerValue(game, self)\n : 0;\n return (player) => playerValue(game, player) + constant;\n};\n\n/**\n * Hypothetical player after placing a domino: kingdom updated and, in the\n * resource modes (Totem, Tribe), the resources of the placed squares collected\n * the way `placeDomino` collects them.\n */\nexport const simulateDominoPlacement = (\n game: Game,\n player: Player,\n domino: Domino,\n placement: ValidPlacement,\n): Player | null => {\n const kingdom = placeDomino(\n player.kingdom,\n placement.position,\n placement.rotation,\n domino,\n game.rules.basic.maxKingdomSize,\n );\n if (!isOk(kingdom)) return null;\n if (!isResourceMode(game.mode.name) || !player.resources) {\n return { ...player, kingdom: kingdom.value };\n }\n\n const added = calculateDominoPosition(\n placement.position,\n placement.rotation,\n domino,\n )\n .map((placed) => createResourceForTile(placed.tile, placed.position))\n .filter((resource): resource is Resource => resource !== null);\n return {\n ...player,\n kingdom: kingdom.value,\n resources: [...player.resources, ...added],\n };\n};\n\n// ─── Best choice (simulate and evaluate) ────────────────────────────\n\nconst simulated = (result: GameStateResult): GameState | null =>\n isOk(result) ? result.value : null;\n\n/**\n * Keeps the choice with the best evaluation of the state it leads to.\n * \"Skip\" (the current state) comes first when allowed, so a choice must be\n * strictly better than doing nothing; on ties the first choice wins.\n */\nconst pickBest = <T>(\n context: ExtensionContext,\n choices: T[],\n apply: (choice: T) => GameState | null,\n profile: EvaluationProfile,\n): T | null => {\n let best: T | null = null;\n let bestValue = context.canSkip\n ? evaluateState(context.game, context.playerId, profile)\n : Number.NEGATIVE_INFINITY;\n\n for (const choice of choices) {\n const state = apply(choice);\n if (!state) continue;\n const value = evaluateState(state, context.playerId, profile);\n if (value > bestValue) {\n bestValue = value;\n best = choice;\n }\n }\n\n // A mandatory action always gets a target\n if (best === null && !context.canSkip) return choices[0] ?? null;\n return best;\n};\n\n/** Best knight square (most taxes, when worth spending a knight). */\nexport const bestKnightPosition = (\n context: KnightContext,\n profile: EvaluationProfile,\n): Position | null =>\n pickBest(\n context,\n context.validPositions,\n (position) =>\n simulated(placeKnightUseCase(context.game, context.lordId, position)),\n profile,\n );\n\n/** Best building and construction square (crowns, end-game points, Queen). */\nexport const bestBuilding = (\n context: BuildingContext,\n profile: EvaluationProfile,\n): BuildingChoice | null =>\n pickBest(\n context,\n context.affordableBuildings.flatMap((building) =>\n context.validPositions.map((position) => ({\n buildingId: building.id,\n position,\n })),\n ),\n (choice) =>\n simulated(\n constructBuildingUseCase(\n context.game,\n context.lordId,\n choice.buildingId,\n choice.position,\n ),\n ),\n profile,\n );\n\n/** Best fire token square (largest region multiplied). */\nexport const bestFireTokenPosition = (\n context: FireTokenContext,\n profile: EvaluationProfile,\n): Position | null =>\n pickBest(\n context,\n context.validPositions,\n (position) =>\n simulated(placeFireTokenUseCase(context.game, context.lordId, position)),\n profile,\n );\n\n/**\n * Maximum payments tried per caveman (Tribe). A player with many resources\n * has many valid payments (combinations of 2 or 4 resources of different\n * types): the bots try the first ones only, which bounds the search.\n */\nexport const MAX_RESOURCE_COMBINATIONS = 8;\n\n/**\n * Best caveman recruitment (Tribe). Only the visible cavemen are considered:\n * the draw pile is face-down, and simulating one of its cavemen would reveal\n * it. The search is done in two bounded steps: the best square with the first\n * payment of each caveman, then the best payment (among the first\n * `MAX_RESOURCE_COMBINATIONS`) for that caveman and square.\n */\nexport const bestCavemanRecruitment = (\n context: CavemanContext,\n profile: EvaluationProfile,\n): CavemanChoice | null => {\n const { options, positions } = context.recruitment;\n const recruit = (choice: CavemanChoice) =>\n simulated(\n recruitCavemanUseCase(\n context.game,\n context.lordId,\n choice.cavemanId,\n choice.position,\n choice.resourcePositions,\n ),\n );\n\n const visible = options.filter(\n (option: CavemanRecruitmentOption) => option.source === \"visible\",\n );\n const placed = pickBest(\n context,\n visible.flatMap((option) =>\n positions.map(\n (position): CavemanChoice => ({\n cavemanId: option.cavemanId,\n position,\n resourcePositions: option.resourceCombinations[0] ?? [],\n }),\n ),\n ),\n recruit,\n profile,\n );\n if (!placed) return null;\n\n const option = visible.find((o) => o.cavemanId === placed.cavemanId);\n const payments = (option?.resourceCombinations ?? []).slice(\n 0,\n MAX_RESOURCE_COMBINATIONS,\n );\n return (\n pickBest(\n { ...context, canSkip: false },\n payments.map((resourcePositions) => ({ ...placed, resourcePositions })),\n recruit,\n profile,\n ) ?? placed\n );\n};\n\n/**\n * Crown that costs the deciding player the least (mandatory placement, own\n * giant or giant sent by an opponent).\n */\nexport const bestGiantPosition = (\n context: GiantPositionContext,\n profile: EvaluationProfile,\n): Position | null =>\n pickBest(\n { ...context, canSkip: false },\n context.validPositions,\n (position) =>\n simulated(placeGiantUseCase(context.game, context.lordId, position)),\n profile,\n );\n\n/**\n * Resolves a giant sent to an opponent who must choose the crown: the\n * opponent is assumed to cover the crown that costs them the least.\n */\nconst resolvePendingGiant = (state: GameState): GameState => {\n if (\n !isGameWithNextAction(state) ||\n state.nextAction.nextAction !== playerActions.placeGiant ||\n !state.ageOfGiants?.pendingGiant\n ) {\n return state;\n }\n const targetLordId = state.nextAction.nextLord;\n const targetId = lordOwner(state, targetLordId)?.id ?? \"\";\n let best: GameState = state;\n let bestValue = Number.NEGATIVE_INFINITY;\n for (const position of getValidGiantPositionsUseCase(state, targetLordId)) {\n const next = simulated(placeGiantUseCase(state, targetLordId, position));\n if (!next) continue;\n const value = evaluateState(next, targetId, { opponentWeight: 0 });\n if (value > bestValue) {\n bestValue = value;\n best = next;\n }\n }\n return best;\n};\n\n/**\n * Best giant to send and opponent to receive it: the crown freed in the own\n * kingdom against the crown the opponent will have to cover.\n */\nexport const bestGiantToSend = (\n context: SendGiantContext,\n profile: EvaluationProfile,\n): SendGiantChoice | null =>\n pickBest(\n context,\n context.targets.giantIndexes.flatMap((giantIndex) =>\n context.targets.targetPlayerIds.map((targetPlayerId) => ({\n giantIndex,\n targetPlayerId,\n })),\n ),\n (choice) => {\n const state = simulated(\n sendGiantUseCase(\n context.game,\n context.lordId,\n choice.giantIndex,\n choice.targetPlayerId,\n ),\n );\n return state ? resolvePendingGiant(state) : null;\n },\n profile,\n );\n\n// ─── Seeded random choices ──────────────────────────────────────────\n\n/**\n * Deterministic random generator for one decision: derived from the game seed\n * (or id) and the decision point, so a game replayed with the same seed gets\n * the same \"random\" bot decisions.\n */\nexport const decisionRandom = (\n game: GameWithNextAction,\n salt: string,\n): (() => number) =>\n createSeededRandom(\n game.seed ?? game.id,\n [\n \"bot\",\n game.turn,\n game.nextAction.nextLord,\n game.nextAction.nextAction,\n game.dominoes.length,\n game.currentDominoes.filter((d) => d.picked).length,\n game.ageOfGiants?.pendingGiant?.fromLordId ?? \"\",\n salt,\n ].join(\"|\"),\n );\n\n/** Uniform pick, or undefined for an empty list. */\nexport const randomItem = <T>(\n random: () => number,\n items: readonly T[],\n): T | undefined => items[Math.floor(random() * items.length)];\n\n/**\n * Seeded uniform choice among the valid targets, \"skip\" (null) counting as\n * one more option when allowed.\n */\nexport const randomChoice = <T>(\n context: ExtensionContext,\n choices: T[],\n salt: string,\n): T | null => {\n const random = decisionRandom(context.game, salt);\n const options: (T | null)[] = context.canSkip ? [null, ...choices] : choices;\n return randomItem(random, options) ?? null;\n};\n","import type { BotStrategy } from \"./bot.js\";\nimport {\n advancedStrategy,\n expertStrategy,\n greedyStrategy,\n randomStrategy,\n} from \"./bot.js\";\n\n/**\n * Built-in strategy names.\n */\nexport type StrategyName = \"random\" | \"greedy\" | \"advanced\" | \"expert\";\n\n// Use a getter function to avoid circular dependency issues with bot.ts.\n// When biome sorts imports, bot.ts may not be fully initialized when this\n// module-level code runs. Deferring access to the strategies ensures they\n// are resolved at call time, not at module evaluation time.\nconst getDefaultStrategies = (): 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] ?? getDefaultStrategies()[name];\n};\n\n/**\n * Returns the list of built-in strategy names.\n */\nexport const getStrategyNames = (): string[] =>\n Object.keys(getDefaultStrategies());\n","import { isGameWithNextAction } from \"@core/domain/types/game.js\";\nimport type {\n Domino,\n Game,\n GameState,\n GameWithNextAction,\n Kingdom,\n Player,\n Position,\n RevealsDomino,\n} from \"@core/domain/types/index.js\";\nimport type { GameEngine } from \"@core/portUserside/engine.js\";\nimport {\n type BuildingChoice,\n type BuildingContext,\n bestBuilding,\n bestCavemanRecruitment,\n bestFireTokenPosition,\n bestGiantPosition,\n bestGiantToSend,\n bestKnightPosition,\n buildingContext,\n type CavemanChoice,\n type CavemanContext,\n cavemanContext,\n createPlayerEvaluator,\n type DragonContext,\n decisionRandom,\n dragonContext,\n type EvaluationProfile,\n type FireTokenContext,\n fireTokenContext,\n type GiantPositionContext,\n giantPositionContext,\n type KnightContext,\n knightContext,\n type PlayerEvaluator,\n randomChoice,\n randomItem,\n type SendGiantChoice,\n type SendGiantContext,\n sendGiantContext,\n simulateDominoPlacement,\n} from \"./botExtensions.js\";\nimport { getStrategy } from \"./botRegistry.js\";\nimport type { ValidPlacement } from \"./getValidPlacements.js\";\nimport { getValidPlacementsUseCase } from \"./getValidPlacements.js\";\n\nexport type {\n BuildingChoice,\n BuildingContext,\n CavemanChoice,\n CavemanContext,\n DragonContext,\n EvaluationProfile,\n ExtensionContext,\n FireTokenContext,\n GiantPositionContext,\n KnightContext,\n SendGiantChoice,\n SendGiantContext,\n} from \"./botExtensions.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 * and optionally how to play the extension actions (Queendomino, Origins,\n * Age of Giants). Strategies are stateless — all information comes from the\n * context.\n *\n * Every extension method is optional: when a strategy does not define one,\n * `playBotTurn` uses the choice of `greedyStrategy` (best immediate\n * mode-aware score). An extension method is only called when the action has\n * at least one valid target, and every target of its context is accepted by\n * the action. Returning `null` skips the action (for the mandatory\n * `placeGiant`, `null` falls back to the greedy choice).\n */\nexport type BotStrategy = {\n chooseDomino: (context: PickContext) => number;\n choosePlacement: (context: PlaceContext) => ValidPlacement | null;\n /** `placeKnight` (Queendomino): a square, or null to skip */\n chooseKnightPosition?: (context: KnightContext) => Position | null;\n /** `constructBuilding` (Queendomino): a building and square, or null */\n chooseBuilding?: (context: BuildingContext) => BuildingChoice | null;\n /** `useDragon` (Queendomino): id of the building to burn, or null */\n chooseDragonTarget?: (context: DragonContext) => number | null;\n /** `placeFireToken` (Origins): a square, or null to skip */\n chooseFireTokenPosition?: (context: FireTokenContext) => Position | null;\n /** `recruitCaveman` (Origins Tribe): a recruitment, or null to skip */\n chooseCavemanRecruitment?: (context: CavemanContext) => CavemanChoice | null;\n /** `placeGiant` (Age of Giants, mandatory): the crown to cover */\n chooseGiantPosition?: (context: GiantPositionContext) => Position | null;\n /** `sendGiant` (Age of Giants): a giant and its target, or null to skip */\n chooseGiantToSend?: (context: SendGiantContext) => SendGiantChoice | null;\n};\n\n/** The extension-action methods of a strategy. */\nexport type BotExtensionChoices = Required<\n Omit<BotStrategy, \"chooseDomino\" | \"choosePlacement\">\n>;\n\n// ─── Helpers ─────────────────────────────────────────────────────────\n\n/** Search state shared by the domino decisions of one strategy call. */\ntype Search = {\n game: Game;\n evaluate: PlayerEvaluator;\n maxSize: number;\n};\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 createSearch = (\n game: GameWithNextAction,\n player: Player,\n profile: EvaluationProfile,\n): Search => ({\n game,\n evaluate: createPlayerEvaluator(game, player.id, profile),\n maxSize: game.rules.basic.maxKingdomSize,\n});\n\nconst bestPlacementScore = (\n search: Search,\n player: Player,\n domino: Domino,\n placements: ValidPlacement[],\n): { placement: ValidPlacement; score: number; player: Player } | null => {\n let best: {\n placement: ValidPlacement;\n score: number;\n player: Player;\n } | null = null;\n\n for (const placement of placements) {\n const next = simulateDominoPlacement(\n search.game,\n player,\n domino,\n placement,\n );\n if (!next) continue;\n const score = search.evaluate(next);\n if (!best || score > best.score) {\n best = { placement, score, player: next };\n }\n }\n\n return best;\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/**\n * Extension choices that simulate every valid target and keep the one with\n * the best mode-aware evaluation (see `botExtensions`). The dragon is never\n * used: burning a building only costs coins and brings no points to the\n * player, a benefit the evaluation cannot measure.\n */\nconst modeAwareExtensions = (\n profile: EvaluationProfile,\n): BotExtensionChoices => ({\n chooseKnightPosition: (context) => bestKnightPosition(context, profile),\n chooseBuilding: (context) => bestBuilding(context, profile),\n chooseDragonTarget: () => null,\n chooseFireTokenPosition: (context) => bestFireTokenPosition(context, profile),\n chooseCavemanRecruitment: (context) =>\n bestCavemanRecruitment(context, profile),\n chooseGiantPosition: (context) => bestGiantPosition(context, profile),\n chooseGiantToSend: (context) => bestGiantToSend(context, profile),\n});\n\n// ─── Random Strategy ─────────────────────────────────────────────────\n\n/**\n * Bot strategy that makes random choices, seeded by the game seed and the\n * decision point (the same game replayed with the same seed gets the same\n * decisions). Picks a random available domino, places it at a random valid\n * position, and plays every extension action on a random valid target, or\n * skips it (\"skip\" being one more option when the action is optional).\n */\nexport const randomStrategy: BotStrategy = {\n chooseDomino: (context) => {\n const { game, availableDominoes } = context;\n const pick = randomItem(decisionRandom(game, \"pick\"), availableDominoes);\n return (pick ?? availableDominoes[0]!).domino.number;\n },\n\n choosePlacement: (context) => {\n const { game, validPlacements } = context;\n return randomItem(decisionRandom(game, \"place\"), validPlacements) ?? null;\n },\n\n chooseKnightPosition: (context) =>\n randomChoice(context, context.validPositions, \"knight\"),\n\n chooseBuilding: (context) => {\n const building = randomChoice(\n context,\n context.affordableBuildings,\n \"building\",\n );\n const position = randomItem(\n decisionRandom(context.game, \"building-position\"),\n context.validPositions,\n );\n return building && position ? { buildingId: building.id, position } : null;\n },\n\n chooseDragonTarget: (context) =>\n randomChoice(context, context.targetBuildings, \"dragon\")?.id ?? null,\n\n chooseFireTokenPosition: (context) =>\n randomChoice(context, context.validPositions, \"fire\"),\n\n chooseCavemanRecruitment: (context) => {\n const { options, positions } = context.recruitment;\n const option = randomChoice(context, options, \"caveman\");\n const random = decisionRandom(context.game, \"caveman-details\");\n const position = randomItem(random, positions);\n const payment = option && randomItem(random, option.resourceCombinations);\n return option && position && payment\n ? { cavemanId: option.cavemanId, position, resourcePositions: payment }\n : null;\n },\n\n chooseGiantPosition: (context) =>\n randomChoice(\n { ...context, canSkip: false },\n context.validPositions,\n \"giant\",\n ),\n\n chooseGiantToSend: (context) => {\n const { giantIndexes, targetPlayerIds } = context.targets;\n const giantIndex = randomChoice(context, giantIndexes, \"send\");\n const targetPlayerId = randomItem(\n decisionRandom(context.game, \"send-target\"),\n targetPlayerIds,\n );\n return giantIndex !== null && targetPlayerId !== undefined\n ? { giantIndex, targetPlayerId }\n : null;\n },\n};\n\n// ─── Greedy Strategy ─────────────────────────────────────────────────\n\nconst GREEDY_PROFILE: EvaluationProfile = { opponentWeight: 0 };\n\n/**\n * Bot strategy that maximizes the immediate mode-aware score.\n * Evaluates every valid placement and picks the one yielding the highest\n * score (territories plus every bonus of the mode). When picking a domino,\n * simulates the best placement for each option. Extension actions: the\n * target with the best own score (taxes, buildings, fire tokens, cavemen,\n * least costly crown for a giant), or skip when nothing improves it.\n */\nexport const greedyStrategy: BotStrategy & BotExtensionChoices = {\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 search = createSearch(game, player, GREEDY_PROFILE);\n let bestScore = Number.NEGATIVE_INFINITY;\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 search.maxSize,\n );\n const result = bestPlacementScore(search, player, rd.domino, placements);\n const score = result ? result.score : search.evaluate(player);\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, lordId, domino, validPlacements } = context;\n if (validPlacements.length === 0) return null;\n const { player } = getLordAndPlayer(game, lordId);\n if (!player) return validPlacements[0]!;\n\n const search = createSearch(game, player, GREEDY_PROFILE);\n const result = bestPlacementScore(search, player, domino, validPlacements);\n return result ? result.placement : validPlacements[0]!;\n },\n\n ...modeAwareExtensions(GREEDY_PROFILE),\n};\n\n// ─── Advanced Strategy ───────────────────────────────────────────────\n\nconst ADVANCED_PROFILE: EvaluationProfile = { opponentWeight: 0.5 };\n\nconst evaluateWithLookahead = (\n search: Search,\n player: Player,\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(\n player.kingdom,\n nextDomino,\n search.maxSize,\n );\n const result = bestPlacementScore(\n search,\n player,\n nextDomino,\n nextPlacements,\n );\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 mode-aware score\n * but also the best possible score achievable in the next turn by peeking at\n * the upcoming domino batch from the draw pile. Extension actions: the target\n * with the best own score minus half the best opponent's score (e.g. sending\n * a giant to the leader, taking a Totem majority from them).\n */\nexport const advancedStrategy: BotStrategy & BotExtensionChoices = {\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 search = createSearch(game, player, ADVANCED_PROFILE);\n const nextBatch = getNextBatchDominoes(game);\n\n let bestCombinedScore = Number.NEGATIVE_INFINITY;\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 search.maxSize,\n );\n const result = bestPlacementScore(search, player, rd.domino, placements);\n\n const immediateScore = result ? result.score : search.evaluate(player);\n const playerAfter = result ? result.player : player;\n const futureScore = evaluateWithLookahead(search, playerAfter, 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, lordId, domino, validPlacements } = context;\n if (validPlacements.length === 0) return null;\n const { player } = getLordAndPlayer(game, lordId);\n if (!player) return validPlacements[0]!;\n\n const search = createSearch(game, player, ADVANCED_PROFILE);\n const nextBatch = getNextBatchDominoes(game);\n\n let bestCombinedScore = Number.NEGATIVE_INFINITY;\n let bestPlacement: ValidPlacement = validPlacements[0]!;\n\n for (const placement of validPlacements) {\n const next = simulateDominoPlacement(game, player, domino, placement);\n if (!next) continue;\n\n const immediateScore = search.evaluate(next);\n const futureScore = evaluateWithLookahead(search, next, 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 ...modeAwareExtensions(ADVANCED_PROFILE),\n};\n\n// ─── Expert Strategy ─────────────────────────────────────────────────\n\nconst EXPERT_PROFILE: EvaluationProfile = { opponentWeight: 1 };\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 search: Search,\n player: Player,\n domino: Domino,\n placements: ValidPlacement[],\n limit: number,\n): { placement: ValidPlacement; player: Player }[] => {\n const simulatedPlacements = placements.flatMap((placement) => {\n const next = simulateDominoPlacement(\n search.game,\n player,\n domino,\n placement,\n );\n return next ? [{ placement, player: next }] : [];\n });\n if (simulatedPlacements.length <= limit) return simulatedPlacements;\n\n return simulatedPlacements\n .map((s) => ({ ...s, score: search.evaluate(s.player) }))\n .sort((a, b) => b.score - a.score)\n .slice(0, limit);\n};\n\nconst expertEvaluate = (\n search: Search,\n player: Player,\n remainingDominoes: Domino[],\n dominoesPerTurn: number,\n depth: number,\n): number => {\n if (depth <= 0 || remainingDominoes.length === 0) {\n return search.evaluate(player);\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 = search.evaluate(player);\n\n for (const domino of batch) {\n const allPlacements = getValidPlacementsUseCase(\n player.kingdom,\n domino,\n search.maxSize,\n );\n\n if (allPlacements.length === 0) {\n const score = expertEvaluate(\n search,\n player,\n afterBatch,\n dominoesPerTurn,\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 search,\n player,\n domino,\n allPlacements,\n EXPERT_BEAM_WIDTH,\n );\n\n for (const candidate of candidates) {\n const score = expertEvaluate(\n search,\n candidate.player,\n afterBatch,\n dominoesPerTurn,\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 the next turns, but limits the number of placements evaluated per\n * domino to the top candidates (by greedy mode-aware score). Since kingdoms\n * are independent, the domino search is a solo optimization. Extension\n * actions: the target that maximizes the lead over the best opponent.\n */\nexport const expertStrategy: BotStrategy & BotExtensionChoices = {\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 search = createSearch(game, player, EXPERT_PROFILE);\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 = Number.NEGATIVE_INFINITY;\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 search.maxSize,\n );\n\n if (allPlacements.length === 0) {\n const score = expertEvaluate(\n search,\n player,\n game.dominoes,\n perTurn,\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 search,\n player,\n rd.domino,\n allPlacements,\n EXPERT_BEAM_WIDTH,\n );\n\n for (const candidate of candidates) {\n const score = expertEvaluate(\n search,\n candidate.player,\n game.dominoes,\n perTurn,\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, lordId, domino, validPlacements } = context;\n if (validPlacements.length === 0) return null;\n const { player } = getLordAndPlayer(game, lordId);\n if (!player) return validPlacements[0]!;\n\n const search = createSearch(game, player, EXPERT_PROFILE);\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 = Number.NEGATIVE_INFINITY;\n let bestPlacement: ValidPlacement = validPlacements[0]!;\n\n for (const placement of validPlacements) {\n const next = simulateDominoPlacement(game, player, domino, placement);\n if (!next) continue;\n\n const score = expertEvaluate(\n search,\n next,\n game.dominoes,\n perTurn,\n turnsLeft,\n );\n if (score > bestScore) {\n bestScore = score;\n bestPlacement = placement;\n }\n }\n\n return bestPlacement;\n },\n\n ...modeAwareExtensions(EXPERT_PROFILE),\n};\n\n// ─── playBotTurn ─────────────────────────────────────────────────────\n\n/**\n * Plays an optional extension action: skipped without asking the strategy\n * when it has no valid target, otherwise the strategy's choice (or the greedy\n * choice when the strategy has no method for this action), `null` skipping.\n */\nconst playOptional = <C extends { canSkip: boolean }, T>(\n engine: GameEngine,\n game: GameWithNextAction,\n context: C,\n hasTarget: boolean,\n choose: ((context: C) => T | null) | undefined,\n fallback: (context: C) => T | null,\n apply: (choice: T) => GameState,\n): GameState => {\n const lordId = game.nextAction.nextLord;\n if (!hasTarget) return engine.skipOptionalAction({ game, lordId });\n const choice = (choose ?? fallback)(context);\n return choice === null\n ? engine.skipOptionalAction({ game, lordId })\n : apply(choice);\n};\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 const defaults = greedyStrategy;\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 = game.rules.basic.maxKingdomSize;\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 // Age of Giants: placeGiant is mandatory (own giant, or a giant sent by an\n // opponent: the targeted player chooses the crown of their own kingdom)\n if (action === \"placeGiant\") {\n const context = giantPositionContext(game, lordId);\n if (context.validPositions.length === 0) {\n return engine.skipOptionalAction({ game, lordId });\n }\n const position =\n strategy.chooseGiantPosition?.(context) ??\n defaults.chooseGiantPosition(context) ??\n context.validPositions[0]!;\n return engine.placeGiant({ game, lordId, position });\n }\n\n if (action === \"placeKnight\") {\n const context = knightContext(game, lordId);\n return playOptional(\n engine,\n game,\n context,\n context.validPositions.length > 0,\n strategy.chooseKnightPosition,\n defaults.chooseKnightPosition,\n (position) => engine.placeKnight({ game, lordId, position }),\n );\n }\n\n if (action === \"constructBuilding\") {\n const context = buildingContext(game, lordId);\n return playOptional(\n engine,\n game,\n context,\n context.validPositions.length > 0 &&\n context.affordableBuildings.length > 0,\n strategy.chooseBuilding,\n defaults.chooseBuilding,\n ({ buildingId, position }) =>\n engine.constructBuilding({ game, lordId, buildingId, position }),\n );\n }\n\n if (action === \"useDragon\") {\n const context = dragonContext(game, lordId);\n return playOptional(\n engine,\n game,\n context,\n context.targetBuildings.length > 0,\n strategy.chooseDragonTarget,\n defaults.chooseDragonTarget,\n (buildingId) => engine.useDragon({ game, lordId, buildingId }),\n );\n }\n\n if (action === \"placeFireToken\") {\n const context = fireTokenContext(game, lordId);\n return playOptional(\n engine,\n game,\n context,\n context.validPositions.length > 0,\n strategy.chooseFireTokenPosition,\n defaults.chooseFireTokenPosition,\n (position) => engine.placeFireToken({ game, lordId, position }),\n );\n }\n\n if (action === \"recruitCaveman\") {\n const context = cavemanContext(game, lordId);\n return playOptional(\n engine,\n game,\n context,\n context.recruitment.options.length > 0,\n strategy.chooseCavemanRecruitment,\n defaults.chooseCavemanRecruitment,\n ({ cavemanId, position, resourcePositions }) =>\n engine.recruitCaveman({\n game,\n lordId,\n cavemanId,\n position,\n resourcePositions,\n }),\n );\n }\n\n if (action === \"sendGiant\") {\n const context = sendGiantContext(game, lordId);\n return playOptional(\n engine,\n game,\n context,\n context.targets.giantIndexes.length > 0,\n strategy.chooseGiantToSend,\n defaults.chooseGiantToSend,\n ({ giantIndex, targetPlayerId }) =>\n engine.sendGiant({ game, lordId, giantIndex, targetPlayerId }),\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 { PlayerInput } from \"@application/commands/addPlayersCommand.js\";\nimport type {\n GameState,\n GameWithNextAction,\n GameWithNextStep,\n Position,\n Rotation,\n} from \"@core/domain/types/index.js\";\nimport type { GameEngine } from \"@core/portUserside/engine.js\";\n\n// ─── Types ──────────────────────────────────────────────────────────\n\n/**\n * Current action log format version.\n *\n * - `1` (or no `version` field): legacy logs. `createGame` may omit the seed,\n * player ids and lord ids are not recorded, so a replay regenerates them.\n * - `2`: the effective seed, the game id, the player ids and the lord ids are\n * recorded, so a replay reproduces a strictly identical game state.\n *\n * Version 1 logs remain replayable.\n */\nexport const ACTION_LOG_VERSION = 2;\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 | \"placeGiant\"\n | \"sendGiant\"\n | \"placeKnight\"\n | \"constructBuilding\"\n | \"useDragon\"\n | \"placeFireToken\"\n | \"recruitCaveman\"\n | \"skipOptionalAction\";\n\n/**\n * Payload types for each action, containing only the command parameters\n * (excluding the game state, which is too large to store), plus the ids the\n * engine generated so that a replay reproduces them.\n */\nexport type ActionPayloadMap = {\n createGame: {\n mode: string;\n /** Effective seed of the game (generated by the engine when the caller gave none) */\n seed?: string;\n /** Id the engine generated for the game (restored on replay) */\n gameId?: string;\n };\n /**\n * Players as `{ id, name, bot? }` objects carrying the ids the engine\n * assigned (legacy logs may contain plain names).\n */\n addPlayers: { players: PlayerInput[] };\n addExtraRules: { extraRules: string[] };\n startGame: {\n /** Ids of the lords, in `game.lords` order (restored on replay) */\n lordIds?: string[];\n };\n chooseDomino: { lordId: string; dominoPick: number };\n placeDomino: { lordId: string; position: Position; rotation: Rotation };\n discardDomino: { lordId: string };\n /**\n * `lordId` is the lord that played the action: the current lord, or a lord\n * of the targeted player when it places a giant sent by an opponent.\n */\n placeGiant: { lordId: string; position: Position };\n sendGiant: {\n lordId: string;\n giantIndex: number;\n targetPlayerId: string;\n targetCrownPosition?: Position;\n };\n placeKnight: { lordId: string; position: Position };\n constructBuilding: {\n lordId: string;\n buildingId: number;\n position: Position;\n };\n useDragon: { lordId: string; buildingId: number };\n placeFireToken: { lordId: string; position: Position };\n recruitCaveman: {\n lordId: string;\n cavemanId: number;\n position: Position;\n resourcePositions: Position[];\n };\n skipOptionalAction: { 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 * It is plain JSON: persist it with `JSON.stringify` and read it back with\n * `JSON.parse`.\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 /** Format version (see `ACTION_LOG_VERSION`); absent in legacy logs (version 1) */\n version?: number;\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 version: ACTION_LOG_VERSION,\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 calculatePlayerScore: (cmd) => engine.calculatePlayerScore(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(\n \"createGame\",\n { mode: cmd.mode, seed: game.seed ?? cmd.seed, gameId: game.id },\n game.turn,\n );\n return game;\n },\n\n addPlayers: (cmd) => {\n const game = engine.addPlayers(cmd);\n record(\n \"addPlayers\",\n {\n players: game.players.map((player) => ({\n id: player.id,\n name: player.name,\n ...(player.bot && { bot: player.bot }),\n })),\n },\n game.turn,\n );\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(\n \"startGame\",\n { lordIds: game.lords.map((lord) => lord.id) },\n game.turn,\n );\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 // Queendomino methods — record after execution\n placeKnight: (cmd) => {\n const game = engine.placeKnight(cmd);\n record(\n \"placeKnight\",\n { lordId: cmd.lordId, position: cmd.position },\n game.turn,\n );\n return game;\n },\n\n constructBuilding: (cmd) => {\n const game = engine.constructBuilding(cmd);\n record(\n \"constructBuilding\",\n {\n lordId: cmd.lordId,\n buildingId: cmd.buildingId,\n position: cmd.position,\n },\n game.turn,\n );\n return game;\n },\n\n useDragon: (cmd) => {\n const game = engine.useDragon(cmd);\n record(\n \"useDragon\",\n { lordId: cmd.lordId, buildingId: cmd.buildingId },\n game.turn,\n );\n return game;\n },\n\n skipOptionalAction: (cmd) => {\n const game = engine.skipOptionalAction(cmd);\n record(\"skipOptionalAction\", { lordId: cmd.lordId }, game.turn);\n return game;\n },\n\n // Origins methods — record after execution\n placeFireToken: (cmd) => {\n const game = engine.placeFireToken(cmd);\n record(\n \"placeFireToken\",\n { lordId: cmd.lordId, position: cmd.position },\n game.turn,\n );\n return game;\n },\n\n recruitCaveman: (cmd) => {\n const game = engine.recruitCaveman(cmd);\n record(\n \"recruitCaveman\",\n {\n lordId: cmd.lordId,\n cavemanId: cmd.cavemanId,\n position: cmd.position,\n resourcePositions: cmd.resourcePositions,\n },\n game.turn,\n );\n return game;\n },\n\n // Age of Giants methods — record after execution\n placeGiant: (cmd) => {\n const game = engine.placeGiant(cmd);\n record(\n \"placeGiant\",\n { lordId: cmd.lordId, position: cmd.position },\n game.turn,\n );\n return game;\n },\n\n sendGiant: (cmd) => {\n const game = engine.sendGiant(cmd);\n record(\n \"sendGiant\",\n {\n lordId: cmd.lordId,\n giantIndex: cmd.giantIndex,\n targetPlayerId: cmd.targetPlayerId,\n ...(cmd.targetCrownPosition !== undefined && {\n targetCrownPosition: cmd.targetCrownPosition,\n }),\n },\n game.turn,\n );\n return game;\n },\n\n // Valid targets for extension actions — read-only, pass through\n getValidFireTokenPositions: (cmd) => engine.getValidFireTokenPositions(cmd),\n getValidKnightPositions: (cmd) => engine.getValidKnightPositions(cmd),\n getValidBuildingPositions: (cmd) => engine.getValidBuildingPositions(cmd),\n getAffordableBuildings: (cmd) => engine.getAffordableBuildings(cmd),\n getValidCavemanPlacements: (cmd) => engine.getValidCavemanPlacements(cmd),\n getValidGiantPositions: (cmd) => engine.getValidGiantPositions(cmd),\n getValidGiantTargets: (cmd) => engine.getValidGiantTargets(cmd),\n canSkipOptionalAction: (cmd) => engine.canSkipOptionalAction(cmd),\n };\n\n return {\n engine: wrappedEngine,\n getLog: () => log,\n };\n};\n\n// ─── Replay ─────────────────────────────────────────────────────────\n\n/**\n * Restores the lord ids recorded by `startGame`. Lords are created and\n * shuffled deterministically (seeded shuffle), so the replayed lords match the\n * recorded ones position by position; only their generated ids differ.\n * Right after `startGame`, lord ids only appear in `lords` and `nextAction`.\n */\nconst restoreLordIds = (\n game: GameWithNextAction,\n lordIds: readonly string[] | undefined,\n): GameWithNextAction => {\n if (!lordIds || lordIds.length !== game.lords.length) return game;\n\n const idMap = new Map<string, string>();\n game.lords.forEach((lord, index) => {\n idMap.set(lord.id, lordIds[index] as string);\n });\n const mapId = (id: string): string => idMap.get(id) ?? id;\n\n return {\n ...game,\n lords: game.lords.map((lord) => ({ ...lord, id: mapId(lord.id) })),\n currentDominoes: game.currentDominoes.map((domino) =>\n domino.lordId ? { ...domino, lordId: mapId(domino.lordId) } : domino,\n ),\n nextAction: {\n ...game.nextAction,\n nextLord: mapId(game.nextAction.nextLord),\n },\n };\n};\n\n/**\n * Replays a `createGame` entry, restoring the recorded game id.\n */\nconst replayCreateGame = (\n engine: GameEngine,\n payload: ActionPayloadMap[\"createGame\"],\n): GameWithNextStep => {\n const game = engine.createGame({ mode: payload.mode, seed: payload.seed });\n return payload.gameId ? { ...game, id: payload.gameId } : game;\n};\n\n/**\n * Applies a single recorded action to a game state.\n */\nconst applyEntry = (\n engine: GameEngine,\n game: GameState,\n entry: ActionEntry,\n): GameState => {\n switch (entry.action) {\n case \"createGame\":\n return replayCreateGame(\n engine,\n entry.payload as ActionPayloadMap[\"createGame\"],\n );\n case \"addPlayers\": {\n const payload = entry.payload as ActionPayloadMap[\"addPlayers\"];\n return engine.addPlayers({ game, players: payload.players });\n }\n case \"addExtraRules\": {\n const payload = entry.payload as ActionPayloadMap[\"addExtraRules\"];\n return engine.addExtraRules({ game, extraRules: payload.extraRules });\n }\n case \"startGame\": {\n const payload = entry.payload as ActionPayloadMap[\"startGame\"];\n return restoreLordIds(engine.startGame({ game }), payload.lordIds);\n }\n case \"chooseDomino\": {\n const payload = entry.payload as ActionPayloadMap[\"chooseDomino\"];\n return engine.chooseDomino({\n game,\n lordId: payload.lordId,\n dominoPick: payload.dominoPick,\n });\n }\n case \"placeDomino\": {\n const payload = entry.payload as ActionPayloadMap[\"placeDomino\"];\n return engine.placeDomino({\n game,\n lordId: payload.lordId,\n position: payload.position,\n rotation: payload.rotation,\n });\n }\n case \"discardDomino\": {\n const payload = entry.payload as ActionPayloadMap[\"discardDomino\"];\n return engine.discardDomino({ game, lordId: payload.lordId });\n }\n case \"placeGiant\": {\n const payload = entry.payload as ActionPayloadMap[\"placeGiant\"];\n return engine.placeGiant({\n game: game as GameWithNextAction,\n lordId: payload.lordId,\n position: payload.position,\n });\n }\n case \"sendGiant\": {\n const payload = entry.payload as ActionPayloadMap[\"sendGiant\"];\n return engine.sendGiant({\n game: game as GameWithNextAction,\n lordId: payload.lordId,\n giantIndex: payload.giantIndex,\n targetPlayerId: payload.targetPlayerId,\n ...(payload.targetCrownPosition !== undefined && {\n targetCrownPosition: payload.targetCrownPosition,\n }),\n });\n }\n case \"placeKnight\": {\n const payload = entry.payload as ActionPayloadMap[\"placeKnight\"];\n return engine.placeKnight({\n game: game as GameWithNextAction,\n lordId: payload.lordId,\n position: payload.position,\n });\n }\n case \"constructBuilding\": {\n const payload = entry.payload as ActionPayloadMap[\"constructBuilding\"];\n return engine.constructBuilding({\n game: game as GameWithNextAction,\n lordId: payload.lordId,\n buildingId: payload.buildingId,\n position: payload.position,\n });\n }\n case \"useDragon\": {\n const payload = entry.payload as ActionPayloadMap[\"useDragon\"];\n return engine.useDragon({\n game: game as GameWithNextAction,\n lordId: payload.lordId,\n buildingId: payload.buildingId,\n });\n }\n case \"placeFireToken\": {\n const payload = entry.payload as ActionPayloadMap[\"placeFireToken\"];\n return engine.placeFireToken({\n game: game as GameWithNextAction,\n lordId: payload.lordId,\n position: payload.position,\n });\n }\n case \"recruitCaveman\": {\n const payload = entry.payload as ActionPayloadMap[\"recruitCaveman\"];\n return engine.recruitCaveman({\n game: game as GameWithNextAction,\n lordId: payload.lordId,\n cavemanId: payload.cavemanId,\n position: payload.position,\n resourcePositions: payload.resourcePositions,\n });\n }\n case \"skipOptionalAction\": {\n const payload = entry.payload as ActionPayloadMap[\"skipOptionalAction\"];\n return engine.skipOptionalAction({\n game: game as GameWithNextAction,\n lordId: payload.lordId,\n });\n }\n default:\n throw new Error(\n `Unknown action in action log: ${String((entry as ActionEntry).action)}`,\n );\n }\n};\n\n/**\n * Replays all actions from a log on a fresh engine to reconstruct the final game state.\n *\n * Version 2 logs (see `ACTION_LOG_VERSION`) record the effective seed and every\n * generated id (game, players, lords), so the replayed state is strictly\n * identical to the original one, whatever the replay engine's `uuidMethod`\n * and `shuffleMethod`. Legacy logs (version 1) are still replayed; their ids\n * are regenerated, and when they lack a seed the replay engine should use the\n * same configuration (especially shuffleMethod) as the original game.\n *\n * @param engine - A game engine instance\n * @param log - The action log to replay\n * @returns The final game state after replaying all actions\n * @throws Error if the log is empty, does not start with createGame, or has an unsupported version\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 if (log.version !== undefined && log.version > ACTION_LOG_VERSION) {\n throw new Error(\n `Unsupported action log version: ${log.version}. Current version: ${ACTION_LOG_VERSION}`,\n );\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 let game: GameState = replayCreateGame(\n engine,\n firstEntry.payload as ActionPayloadMap[\"createGame\"],\n );\n\n for (let i = 1; i < log.entries.length; i++) {\n const entry = log.entries[i];\n if (!entry) continue;\n game = applyEntry(engine, game, entry);\n }\n\n return game;\n};\n","import { RedoError, UndoError } from \"@core/domain/errors/domainErrors.js\";\nimport type { GameState } from \"@core/domain/types/index.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 BotExtensionChoices,\n type BotStrategy,\n type BuildingChoice,\n type BuildingContext,\n type CavemanChoice,\n type CavemanContext,\n type DragonContext,\n type ExtensionContext,\n expertStrategy,\n type FireTokenContext,\n type GiantPositionContext,\n greedyStrategy,\n isBotTurn,\n type KnightContext,\n type PickContext,\n type PlaceContext,\n playBotTurn,\n playBotTurns,\n randomStrategy,\n type SendGiantChoice,\n type SendGiantContext,\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// Score breakdown (mode-aware live / final score)\nexport type { CalculatePlayerScoreUseCase } from \"@core/useCases/calculatePlayerScore.js\";\nexport type { ConstructBuildingUseCase } from \"@core/useCases/constructBuilding.js\";\n// Action log (game history / replay)\nexport {\n ACTION_LOG_VERSION,\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// Valid targets for extension actions\nexport type {\n CavemanRecruitmentOption,\n ValidActionTargetsUseCase,\n ValidCavemanPlacements,\n ValidGiantTargets,\n} from \"@core/useCases/getValidActionTargets.js\";\n// Use cases (for advanced usage)\nexport type { ValidPlacement } from \"@core/useCases/getValidPlacements.js\";\nexport type { PlaceFireTokenUseCase } from \"@core/useCases/placeFireToken.js\";\nexport type { PlaceGiantUseCase } from \"@core/useCases/placeGiant.js\";\nexport type { PlaceKnightUseCase } from \"@core/useCases/placeKnight.js\";\nexport type { RecruitCavemanUseCase } from \"@core/useCases/recruitCaveman.js\";\nexport type { SendGiantUseCase } from \"@core/useCases/sendGiant.js\";\nexport {\n createSavePoint,\n deserializeGame,\n type GameSavePoint,\n restoreFromSavePoint,\n serializeGame,\n} from \"@core/useCases/serialization.js\";\nexport type { SkipOptionalActionUseCase } from \"@core/useCases/skipOptionalAction.js\";\nexport { isSkippableAction } from \"@core/useCases/skipOptionalAction.js\";\nexport type { UseDragonUseCase } from \"@core/useCases/useDragon.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 placeGiantHandler,\n sendGiantHandler,\n placeKnightHandler,\n constructBuildingHandler,\n useDragonHandler,\n placeFireTokenHandler,\n recruitCavemanHandler,\n skipOptionalActionHandler,\n getValidFireTokenPositionsHandler,\n getValidKnightPositionsHandler,\n getValidBuildingPositionsHandler,\n getAffordableBuildingsHandler,\n getValidCavemanPlacementsHandler,\n getValidGiantPositionsHandler,\n getValidGiantTargetsHandler,\n canSkipOptionalActionHandler,\n calculatePlayerScoreHandler,\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 placeGiant: (command) => placeGiantHandler(command),\n sendGiant: (command) => sendGiantHandler(command),\n placeKnight: (command) => placeKnightHandler(command),\n constructBuilding: (command) => constructBuildingHandler(command),\n useDragon: (command) => useDragonHandler(command),\n placeFireToken: (command) => placeFireTokenHandler(command),\n recruitCaveman: (command) => recruitCavemanHandler(command),\n skipOptionalAction: (command) => skipOptionalActionHandler(command),\n getValidFireTokenPositions: (command) =>\n getValidFireTokenPositionsHandler(command),\n getValidKnightPositions: (command) =>\n getValidKnightPositionsHandler(command),\n getValidBuildingPositions: (command) =>\n getValidBuildingPositionsHandler(command),\n getAffordableBuildings: (command) => getAffordableBuildingsHandler(command),\n getValidCavemanPlacements: (command) =>\n getValidCavemanPlacementsHandler(command),\n getValidGiantPositions: (command) => getValidGiantPositionsHandler(command),\n getValidGiantTargets: (command) => getValidGiantTargetsHandler(command),\n canSkipOptionalAction: (command) => canSkipOptionalActionHandler(command),\n calculatePlayerScore: (command) => calculatePlayerScoreHandler(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":";AAgDO,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;AAiDO,IAAM,oBAAoB,CAC/B,SAC4B;AAC5B,SAAO,YAAY,QAAQ,MAAM,QAAQ,KAAK,MAAM;AACtD;;;AC3GO,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,IACA,aAAa,WAAW,eAAe,OAAO,aAAa,QAAQ,KAAK;AAAA,IACxE,mBAAmB;AAAA,MACjB;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,IACA,WAAW,WAAW,aAAa,OAAO,WAAW,QAAQ,KAAK;AAAA,IAClE,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,gBAAgB;AAAA,MACd;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,IACA,YAAY,WAAW,cAAc,OAAO,YAAY,QAAQ,KAAK;AAAA,IACrE,WAAW,WAAW,aAAa,OAAO,WAAW,QAAQ,KAAK;AAAA,IAClE,4BAA4B;AAAA,MAC1B;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,IACA,yBAAyB;AAAA,MACvB;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,IACA,2BAA2B;AAAA,MACzB;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,IACA,wBAAwB;AAAA,MACtB;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,IACA,2BAA2B;AAAA,MACzB;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,IACA,wBAAwB;AAAA,MACtB;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,IACA,sBAAsB;AAAA,MACpB;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,IACA,uBAAuB;AAAA,MACrB;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,IACA,sBAAsB;AAAA,MACpB;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;ACpRA,IAAM,cAAc,CAAC,SACnB,mBAAmB,IAAI,KAAK,KAAK,WAAW,SAAS;AAmBhD,IAAM,iBAAiB,CAC5B,QACA,cACe;AAIf,QAAM,cAAc,CAAC,QAAmB,UAA2B;AACjE,QAAI,MAAM,SAAS,OAAO,MAAM;AAC9B,gBAAU,YAAY,EAAE,MAAM,OAAO,MAAM,OAAO,KAAK,CAAC;AACxD,gBAAU,cAAc,EAAE,MAAM,OAAO,MAAM,MAAM,KAAK,CAAC;AAAA,IAC3D;AACA,QAAI,CAAC,YAAY,MAAM,KAAK,YAAY,KAAK,GAAG;AAC9C,gBAAU,YAAY,EAAE,MAAM,MAAM,CAAC;AAAA,IACvC;AAAA,EACF;AAMA,QAAM,WACJ,CACE,KACA,SAEF,CAAC,QAAc;AACb,UAAM,OAAO,IAAI,GAAG;AACpB,SAAK,MAAM,GAAG;AACd,gBAAY,IAAI,MAAM,IAAI;AAC1B,WAAO;AAAA,EACT;AAEF,SAAO;AAAA;AAAA,IAEL,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,IACxD,4BAA4B,CAAC,QAAQ,OAAO,2BAA2B,GAAG;AAAA,IAC1E,yBAAyB,CAAC,QAAQ,OAAO,wBAAwB,GAAG;AAAA,IACpE,2BAA2B,CAAC,QAAQ,OAAO,0BAA0B,GAAG;AAAA,IACxE,wBAAwB,CAAC,QAAQ,OAAO,uBAAuB,GAAG;AAAA,IAClE,2BAA2B,CAAC,QAAQ,OAAO,0BAA0B,GAAG;AAAA,IACxE,wBAAwB,CAAC,QAAQ,OAAO,uBAAuB,GAAG;AAAA,IAClE,sBAAsB,CAAC,QAAQ,OAAO,qBAAqB,GAAG;AAAA,IAC9D,uBAAuB,CAAC,QAAQ,OAAO,sBAAsB,GAAG;AAAA,IAChE,sBAAsB,CAAC,QAAQ,OAAO,qBAAqB,GAAG;AAAA;AAAA,IAG9D,YAAY,CAAC,QAAQ;AACnB,YAAM,OAAO,OAAO,WAAW,GAAG;AAClC,gBAAU,gBAAgB,EAAE,KAAK,CAAC;AAClC,aAAO;AAAA,IACT;AAAA,IAEA,YAAY,CAAC,QAAQ;AACnB,YAAM,OAAO,OAAO,WAAW,GAAG;AAClC,gBAAU,iBAAiB,EAAE,KAAK,CAAC;AACnC,aAAO;AAAA,IACT;AAAA,IAEA,eAAe,CAAC,QAAQ;AACtB,YAAM,OAAO,OAAO,cAAc,GAAG;AACrC,gBAAU,oBAAoB,EAAE,MAAM,YAAY,IAAI,WAAW,CAAC;AAClE,aAAO;AAAA,IACT;AAAA,IAEA,WAAW,CAAC,QAAQ;AAClB,YAAM,OAAO,OAAO,UAAU,GAAG;AACjC,gBAAU,gBAAgB,EAAE,KAAK,CAAC;AAClC,gBAAU,cAAc,EAAE,MAAM,MAAM,KAAK,KAAK,CAAC;AACjD,aAAO;AAAA,IACT;AAAA;AAAA,IAGA,cAAc;AAAA,MACZ,CAAC,QAAQ,OAAO,aAAa,GAAG;AAAA,MAChC,CAAC,MAAM,QACL,UAAU,iBAAiB;AAAA,QACzB;AAAA,QACA,QAAQ,IAAI;AAAA,QACZ,cAAc,IAAI;AAAA,MACpB,CAAC;AAAA,IACL;AAAA,IAEA,aAAa;AAAA,MACX,CAAC,QAAQ,OAAO,YAAY,GAAG;AAAA,MAC/B,CAAC,MAAM,QAAQ,UAAU,iBAAiB,EAAE,MAAM,QAAQ,IAAI,OAAO,CAAC;AAAA,IACxE;AAAA,IAEA,eAAe;AAAA,MACb,CAAC,QAAQ,OAAO,cAAc,GAAG;AAAA,MACjC,CAAC,MAAM,QACL,UAAU,oBAAoB,EAAE,MAAM,QAAQ,IAAI,OAAO,CAAC;AAAA,IAC9D;AAAA;AAAA,IAGA,aAAa;AAAA,MACX,CAAC,QAAQ,OAAO,YAAY,GAAG;AAAA,MAC/B,CAAC,MAAM,QAAQ,UAAU,iBAAiB,EAAE,MAAM,QAAQ,IAAI,OAAO,CAAC;AAAA,IACxE;AAAA,IAEA,mBAAmB;AAAA,MACjB,CAAC,QAAQ,OAAO,kBAAkB,GAAG;AAAA,MACrC,CAAC,MAAM,QACL,UAAU,wBAAwB;AAAA,QAChC;AAAA,QACA,QAAQ,IAAI;AAAA,QACZ,YAAY,IAAI;AAAA,MAClB,CAAC;AAAA,IACL;AAAA,IAEA,WAAW;AAAA,MACT,CAAC,QAAQ,OAAO,UAAU,GAAG;AAAA,MAC7B,CAAC,MAAM,QACL,UAAU,eAAe;AAAA,QACvB;AAAA,QACA,QAAQ,IAAI;AAAA,QACZ,YAAY,IAAI;AAAA,MAClB,CAAC;AAAA,IACL;AAAA,IAEA,oBAAoB;AAAA,MAClB,CAAC,QAAQ,OAAO,mBAAmB,GAAG;AAAA,MACtC,CAAC,MAAM,QACL,UAAU,0BAA0B;AAAA,QAClC;AAAA,QACA,QAAQ,IAAI;AAAA,QACZ,eAAe,IAAI,KAAK,WAAW;AAAA,MACrC,CAAC;AAAA,IACL;AAAA;AAAA,IAGA,gBAAgB;AAAA,MACd,CAAC,QAAQ,OAAO,eAAe,GAAG;AAAA,MAClC,CAAC,MAAM,QACL,UAAU,oBAAoB,EAAE,MAAM,QAAQ,IAAI,OAAO,CAAC;AAAA,IAC9D;AAAA,IAEA,gBAAgB;AAAA,MACd,CAAC,QAAQ,OAAO,eAAe,GAAG;AAAA,MAClC,CAAC,MAAM,QACL,UAAU,qBAAqB;AAAA,QAC7B;AAAA,QACA,QAAQ,IAAI;AAAA,QACZ,WAAW,IAAI;AAAA,MACjB,CAAC;AAAA,IACL;AAAA;AAAA,IAGA,YAAY;AAAA,MACV,CAAC,QAAQ,OAAO,WAAW,GAAG;AAAA,MAC9B,CAAC,MAAM,QAAQ,UAAU,gBAAgB,EAAE,MAAM,QAAQ,IAAI,OAAO,CAAC;AAAA,IACvE;AAAA,IAEA,WAAW;AAAA,MACT,CAAC,QAAQ,OAAO,UAAU,GAAG;AAAA,MAC7B,CAAC,MAAM,QACL,UAAU,cAAc;AAAA,QACtB;AAAA,QACA,QAAQ,IAAI;AAAA,QACZ,gBAAgB,IAAI;AAAA,MACtB,CAAC;AAAA,IACL;AAAA,EACF;AACF;;;AC1RO,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,EAAE,IAAM,GAAG,MAAQ,cAAc,MAAQ,GAAG,gBAAkB,EAAE,MAAQ,SAAS,QAAU,EAAE,GAAG,QAAU,GAAG,QAAU,EAAE;AAAA,EACzH,EAAE,IAAM,GAAG,MAAQ,cAAc,MAAQ,GAAG,gBAAkB,EAAE,MAAQ,SAAS,QAAU,EAAE,GAAG,QAAU,GAAG,QAAU,EAAE;AAAA,EACzH,EAAE,IAAM,GAAG,MAAQ,eAAe,MAAQ,GAAG,QAAU,GAAG,QAAU,GAAG,gBAAkB,EAAE,MAAQ,cAAc,SAAW,UAAU,QAAU,EAAE,EAAE;AAAA,EACpJ,EAAE,IAAM,GAAG,MAAQ,oBAAoB,MAAQ,GAAG,gBAAkB,EAAE,MAAQ,SAAS,QAAU,EAAE,GAAG,QAAU,GAAG,QAAU,GAAG,gBAAkB,EAAE,MAAQ,cAAc,SAAW,OAAO,QAAU,EAAE,EAAE;AAAA,EAC1M,EAAE,IAAM,GAAG,MAAQ,oBAAoB,MAAQ,GAAG,gBAAkB,EAAE,MAAQ,SAAS,QAAU,EAAE,GAAG,QAAU,GAAG,QAAU,GAAG,gBAAkB,EAAE,MAAQ,cAAc,SAAW,OAAO,QAAU,EAAE,EAAE;AAAA,EAC1M,EAAE,IAAM,GAAG,MAAQ,oBAAoB,MAAQ,GAAG,QAAU,GAAG,QAAU,GAAG,gBAAkB,EAAE,MAAQ,cAAc,SAAW,SAAS,QAAU,EAAE,EAAE;AAAA,EACxJ,EAAE,IAAM,GAAG,MAAQ,oBAAoB,MAAQ,GAAG,QAAU,GAAG,QAAU,GAAG,gBAAkB,EAAE,MAAQ,YAAY,QAAU,EAAE,EAAE;AAAA,EAClI,EAAE,IAAM,GAAG,MAAQ,gBAAgB,MAAQ,GAAG,QAAU,GAAG,QAAU,GAAG,gBAAkB,EAAE,MAAQ,YAAY,QAAU,EAAE,EAAE;AAAA,EAC9H,EAAE,IAAM,GAAG,MAAQ,cAAc,MAAQ,GAAG,QAAU,GAAG,QAAU,GAAG,gBAAkB,EAAE,MAAQ,eAAe,QAAU,EAAE,EAAE;AAAA,EAC/H,EAAE,IAAM,IAAI,MAAQ,YAAY,MAAQ,GAAG,gBAAkB,EAAE,MAAQ,SAAS,QAAU,EAAE,GAAG,QAAU,GAAG,QAAU,GAAG,gBAAkB,EAAE,MAAQ,QAAQ,QAAU,EAAE,EAAE;AAAA,EAC3K,EAAE,IAAM,IAAI,MAAQ,mBAAmB,MAAQ,GAAG,QAAU,GAAG,QAAU,GAAG,gBAAkB,EAAE,MAAQ,QAAQ,QAAU,EAAE,EAAE;AAAA,EAC9H,EAAE,IAAM,IAAI,MAAQ,mBAAmB,MAAQ,GAAG,QAAU,GAAG,QAAU,GAAG,gBAAkB,EAAE,MAAQ,QAAQ,QAAU,EAAE,EAAE;AAAA,EAC9H,EAAE,IAAM,IAAI,MAAQ,iBAAiB,MAAQ,GAAG,QAAU,GAAG,QAAU,GAAG,gBAAkB,EAAE,MAAQ,QAAQ,QAAU,EAAE,EAAE;AAAA,EAC5H,EAAE,IAAM,IAAI,MAAQ,kBAAkB,MAAQ,GAAG,QAAU,GAAG,QAAU,GAAG,gBAAkB,EAAE,MAAQ,eAAe,QAAU,EAAE,EAAE;AAAA,EACpI,EAAE,IAAM,IAAI,MAAQ,wBAAwB,MAAQ,GAAG,QAAU,GAAG,QAAU,GAAG,gBAAkB,EAAE,MAAQ,QAAQ,QAAU,EAAE,EAAE;AAAA,EACnI,EAAE,IAAM,IAAI,MAAQ,yBAAyB,MAAQ,GAAG,QAAU,GAAG,QAAU,GAAG,gBAAkB,EAAE,MAAQ,YAAY,QAAU,EAAE,EAAE;AAAA,EACxI,EAAE,IAAM,IAAI,MAAQ,wBAAwB,MAAQ,GAAG,gBAAkB,EAAE,MAAQ,SAAS,QAAU,EAAE,GAAG,QAAU,GAAG,QAAU,GAAG,gBAAkB,EAAE,MAAQ,eAAe,QAAU,EAAE,EAAE;AAAA,EAC9L,EAAE,IAAM,IAAI,MAAQ,eAAe,MAAQ,GAAG,QAAU,GAAG,QAAU,GAAG,gBAAkB,EAAE,MAAQ,cAAc,SAAW,OAAO,QAAU,EAAE,EAAE;AACpJ;;;ACTA,IAAM,gBAAgB,MAA2B;AAC/C,QAAM,YAA4B,kBAAc,IAAI,CAAC,MAAM;AACzD,UAAM,OAAqB;AAAA,MACzB,IAAI,EAAE;AAAA,MACN,MAAM,EAAE;AAAA,MACR,MAAM,EAAE;AAAA,MACR,QAAQ,EAAE;AAAA,MACV,QAAQ,EAAE;AAAA,IACZ;AAEA,QAAI,EAAE,gBAAgB;AACpB,WAAK,iBAAiB;AAAA,QACpB,MAAM,EAAE,eAAe;AAAA,QACvB,QAAQ,EAAE,eAAe;AAAA,MAC3B;AAAA,IACF;AAEA,QAAI,oBAAoB,KAAK,EAAE,gBAAgB;AAC7C,WAAK,iBAAiB;AAAA,QACpB,MAAM,EAAE,eAAe;AAAA,QACvB,QAAQ,EAAE,eAAe;AAAA,QACzB,GAAI,aAAa,EAAE,kBAAkB;AAAA,UACnC,SAAS,EAAE,eAAe;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT,CAAC;AAED,SAAO;AAAA,IACL,QAAQ,MAAM;AAAA,EAChB;AACF;AAEA,IAAO,wBAAQ;;;AC7Cf;AAAA,EACE,EAAE,MAAQ,kBAAkB,IAAM,GAAG,YAAc,iBAAiB,gBAAkB,EAAE;AAAA,EACxF,EAAE,MAAQ,kBAAkB,IAAM,GAAG,YAAc,iBAAiB,gBAAkB,EAAE;AAAA,EACxF,EAAE,MAAQ,kBAAkB,IAAM,GAAG,YAAc,aAAa,gBAAkB,EAAE;AAAA,EACpF,EAAE,MAAQ,kBAAkB,IAAM,GAAG,YAAc,aAAa,gBAAkB,EAAE;AAAA,EACpF,EAAE,MAAQ,kBAAkB,IAAM,GAAG,YAAc,kBAAkB,gBAAkB,EAAE;AAAA,EACzF,EAAE,MAAQ,kBAAkB,IAAM,GAAG,YAAc,kBAAkB,gBAAkB,EAAE;AAAA,EACzF,EAAE,MAAQ,kBAAkB,IAAM,GAAG,YAAc,kBAAkB,gBAAkB,EAAE;AAAA,EACzF,EAAE,MAAQ,kBAAkB,IAAM,GAAG,YAAc,kBAAkB,gBAAkB,EAAE;AAAA,EACzF,EAAE,MAAQ,kBAAkB,IAAM,GAAG,YAAc,WAAW,gBAAkB,EAAE;AAAA,EAClF,EAAE,MAAQ,kBAAkB,IAAM,IAAI,YAAc,WAAW,gBAAkB,EAAE;AAAA,EACnF,EAAE,MAAQ,kBAAkB,IAAM,IAAI,YAAc,YAAY,gBAAkB,EAAE;AAAA,EACpF,EAAE,MAAQ,kBAAkB,IAAM,IAAI,YAAc,YAAY,gBAAkB,EAAE;AAAA,EACpF,EAAE,MAAQ,kBAAkB,IAAM,IAAI,YAAc,YAAY,gBAAkB,EAAE;AAAA,EACpF,EAAE,MAAQ,kBAAkB,IAAM,IAAI,YAAc,YAAY,gBAAkB,EAAE;AAAA,EACpF,EAAE,MAAQ,WAAW,IAAM,IAAI,aAAe,SAAS,OAAS,EAAE;AAAA,EAClE,EAAE,MAAQ,WAAW,IAAM,IAAI,aAAe,SAAS,OAAS,EAAE;AAAA,EAClE,EAAE,MAAQ,WAAW,IAAM,IAAI,aAAe,SAAS,OAAS,EAAE;AAAA,EAClE,EAAE,MAAQ,WAAW,IAAM,IAAI,aAAe,SAAS,OAAS,EAAE;AAAA,EAClE,EAAE,MAAQ,WAAW,IAAM,IAAI,aAAe,UAAU,OAAS,EAAE;AAAA,EACnE,EAAE,MAAQ,WAAW,IAAM,IAAI,aAAe,UAAU,OAAS,EAAE;AAAA,EACnE,EAAE,MAAQ,WAAW,IAAM,IAAI,aAAe,UAAU,OAAS,EAAE;AAAA,EACnE,EAAE,MAAQ,WAAW,IAAM,IAAI,aAAe,UAAU,OAAS,EAAE;AACrE;;;ACbA,IAAM,aAAa,CAAC,QAOD;AACjB,MAAI,IAAI,SAAS,kBAAkB;AACjC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,IAAI,IAAI;AAAA,MACR,YAAY,IAAI;AAAA,MAChB,gBAAgB,IAAI;AAAA,IACtB;AAAA,EACF;AACA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,IAAI,IAAI;AAAA,IACR,aAAa,IAAI;AAAA,IACjB,OAAO,IAAI;AAAA,EACb;AACF;AAEA,IAAM,cAAc,MAAyB;AAC3C,QAAM,UAAyB,gBAAY,IAAI,UAAU;AAEzD,SAAO;AAAA,IACL,QAAQ,MAAM,CAAC,GAAG,OAAO;AAAA,EAC3B;AACF;AAEA,IAAO,sBAAQ;;;AC1Cf;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;AAAA,EACA,aAAe;AAAA,IACb;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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;AAAA,EACA,mBAAqB;AAAA,IACnB;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,QACV,gBAAkB;AAAA,MACpB;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,QACV,gBAAkB;AAAA,MACpB;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,QACV,gBAAkB;AAAA,MACpB;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,QACV,gBAAkB;AAAA,MACpB;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,QACV,gBAAkB;AAAA,MACpB;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,QACV,gBAAkB;AAAA,MACpB;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,QACV,gBAAkB;AAAA,MACpB;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,QACV,gBAAkB;AAAA,MACpB;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,QACV,gBAAkB;AAAA,MACpB;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,QACV,gBAAkB;AAAA,MACpB;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;AAAA,EACA,aAAe;AAAA,IACb;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,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,QACV,UAAY;AAAA,MACd;AAAA,MACA,QAAU;AAAA,MACV,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,QACV,UAAY;AAAA,MACd;AAAA,MACA,QAAU;AAAA,MACV,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,QACV,UAAY;AAAA,MACd;AAAA,MACA,QAAU;AAAA,MACV,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,QACV,UAAY;AAAA,MACd;AAAA,MACA,QAAU;AAAA,MACV,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,QACV,UAAY;AAAA,MACd;AAAA,MACA,QAAU;AAAA,MACV,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,QACV,UAAY;AAAA,MACd;AAAA,MACA,QAAU;AAAA,MACV,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,QACV,cAAgB;AAAA,MAClB;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,QACV,cAAgB;AAAA,MAClB;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,QACV,cAAgB;AAAA,MAClB;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,QACV,cAAgB;AAAA,MAClB;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,QACV,cAAgB;AAAA,MAClB;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,QACV,cAAgB;AAAA,MAClB;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,EACF;AAAA,EACA,2BAA2B;AAAA,IACzB;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,uBAAyB;AAAA,MAC3B;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,QACV,UAAY;AAAA,MACd;AAAA,MACA,QAAU;AAAA,MACV,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,QACV,UAAY;AAAA,MACd;AAAA,MACA,QAAU;AAAA,MACV,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,QACV,UAAY;AAAA,MACd;AAAA,MACA,QAAU;AAAA,MACV,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,QACV,UAAY;AAAA,MACd;AAAA,MACA,QAAU;AAAA,MACV,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,QACV,UAAY;AAAA,MACd;AAAA,MACA,QAAU;AAAA,MACV,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,QACV,UAAY;AAAA,MACd;AAAA,MACA,QAAU;AAAA,MACV,QAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,QAAU;AAAA,QACV,cAAgB;AAAA,MAClB;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,QACV,cAAgB;AAAA,MAClB;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,QACV,cAAgB;AAAA,MAClB;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,QACV,cAAgB;AAAA,MAClB;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,QACV,cAAgB;AAAA,MAClB;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,QACV,cAAgB;AAAA,MAClB;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,QAAU;AAAA,MACZ;AAAA,MACA,QAAU;AAAA,IACZ;AAAA,EACF;AACF;;;ACp7FA,IAAM,UAAU,CAAC,QAOL;AACV,QAAM,OAAa;AAAA,IACjB,MAAM,IAAI;AAAA,IACV,QAAQ,IAAI;AAAA,EACd;AACA,MAAI,IAAI,uBAAuB;AAC7B,SAAK,wBAAwB;AAAA,EAC/B;AACA,MAAI,IAAI,gBAAgB;AACtB,SAAK,iBAAiB,IAAI;AAAA,EAC5B;AACA,MAAI,IAAI,UAAU;AAChB,SAAK,WAAW;AAAA,EAClB;AACA,MAAI,IAAI,cAAc;AACpB,SAAK,eAAe;AAAA,EACtB;AACA,SAAO;AACT;AAGA,IAAM,sBAAsB;AAC5B,IAAM,iBAAiB,CAAC,aAA6B;AACnD,MAAI,SAAS,WAAW,mBAAmB,GAAG;AAC5C,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,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,YAAM,IAAY;AAAA,QAChB,MAAM,QAAQ,OAAO,IAAI;AAAA,QACzB,OAAO,QAAQ,OAAO,KAAK;AAAA,QAC3B,QAAQ,OAAO;AAAA,MACjB;AACA,UAAI,YAAY,UAAU,OAAO,OAAO,WAAW,UAAU;AAC3D,UAAE,SAAS,OAAO;AAAA,MACpB;AACA,sBAAgB,KAAK,CAAC;AAAA,IACxB,CAAC;AAED,aAAS,GAAG,IAAI;AAAA,EAClB;AAEA,SAAO;AAAA,IACL,YAAY,CAAC,SAAmB;AAC9B,YAAM,MAAM,eAAe,KAAK,IAAI;AACpC,aAAO,SAAS,GAAG,KAAK,CAAC;AAAA,IAC3B;AAAA,EACF;AACF;AAEA,IAAO,uBAAQ;;;ACrEf;AAAA,EACI;AAAA,IACI,MAAQ;AAAA,IACR,aAAe;AAAA,EACnB;AAAA,EACA;AAAA,IACI,MAAQ;AAAA,IACR,aAAe;AAAA,EACnB;AAAA,EACA;AAAA,IACI,MAAQ;AAAA,IACR,aAAe;AAAA,EACnB;AAAA,EACA;AAAA,IACI,MAAQ;AAAA,IACR,aAAe;AAAA,EACnB;AAAA,EACA;AAAA,IACI,MAAQ;AAAA,IACR,aAAe;AAAA,EACnB;AAAA,EACA;AAAA,IACI,MAAQ;AAAA,IACR,aAAe;AAAA,EACnB;AAAA,EACA;AAAA,IACI,MAAQ;AAAA,IACR,aAAe;AAAA,EACnB;AACJ;;;ACzBA,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;AAAA,IACE,IAAM;AAAA,IACN,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,aAAe;AAAA,IACf,QAAU;AAAA,IACV,SAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAM;AAAA,IACN,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,aAAe;AAAA,IACf,QAAU;AAAA,IACV,SAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAM;AAAA,IACN,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,aAAe;AAAA,IACf,QAAU;AAAA,IACV,SAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAM;AAAA,IACN,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,aAAe;AAAA,IACf,QAAU;AAAA,IACV,SAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAM;AAAA,IACN,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,aAAe;AAAA,IACf,QAAU;AAAA,IACV,SAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAM;AAAA,IACN,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,aAAe;AAAA,IACf,QAAU;AAAA,IACV,SAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAM;AAAA,IACN,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,aAAe;AAAA,IACf,QAAU;AAAA,IACV,SAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAM;AAAA,IACN,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,aAAe;AAAA,IACf,QAAU;AAAA,IACV,SAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAM;AAAA,IACN,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,aAAe;AAAA,IACf,QAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAM;AAAA,IACN,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,aAAe;AAAA,IACf,QAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAM;AAAA,IACN,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,aAAe;AAAA,IACf,QAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAM;AAAA,IACN,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,aAAe;AAAA,IACf,QAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAM;AAAA,IACN,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,aAAe;AAAA,IACf,QAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAM;AAAA,IACN,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,aAAe;AAAA,IACf,QAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAM;AAAA,IACN,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,aAAe;AAAA,IACf,QAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAM;AAAA,IACN,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,aAAe;AAAA,IACf,QAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAM;AAAA,IACN,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,aAAe;AAAA,IACf,QAAU;AAAA,EACZ;AACF;;;ACzHA,IAAM,eAAe,CAAC,QAOL;AACf,QAAM,OAAkB;AAAA,IACtB,IAAI,IAAI;AAAA,IACR,MAAM,IAAI;AAAA,IACV,MAAM,IAAI;AAAA,IACV,aAAa,IAAI;AAAA,IACjB,QAAQ,IAAI;AAAA,EACd;AACA,MAAI,IAAI,SAAS;AACf,SAAK,UAAU,IAAI;AAAA,EACrB;AACA,SAAO;AACT;AAEA,IAAM,iBAAiB,MAA4B;AACjD,QAAM,aAA0B,mBAAe,IAAI,YAAY;AAE/D,SAAO;AAAA,IACL,QAAQ,MAAM,CAAC,GAAG,UAAU;AAAA,EAC9B;AACF;AAEA,IAAO,yBAAQ;;;ACpCf;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,KAAO;AAAA,IACL;AAAA,MACE,cAAgB;AAAA,MAChB,gBAAkB;AAAA,MAClB,aAAe;AAAA,MACf,iBAAmB;AAAA,MACnB,UAAY;AAAA,MACZ,gBAAkB;AAAA,MAClB,0BAA4B;AAAA,IAC9B;AAAA,IACA;AAAA,MACE,cAAgB;AAAA,MAChB,gBAAkB;AAAA,MAClB,aAAe;AAAA,MACf,iBAAmB;AAAA,MACnB,UAAY;AAAA,MACZ,gBAAkB;AAAA,MAClB,0BAA4B;AAAA,IAC9B;AAAA,IACA;AAAA,MACE,cAAgB;AAAA,MAChB,gBAAkB;AAAA,MAClB,aAAe;AAAA,MACf,iBAAmB;AAAA,MACnB,UAAY;AAAA,MACZ,gBAAkB;AAAA,MAClB,0BAA4B;AAAA,IAC9B;AAAA,IACA;AAAA,MACE,cAAgB;AAAA,MAChB,gBAAkB;AAAA,MAClB,aAAe;AAAA,MACf,iBAAmB;AAAA,MACnB,UAAY;AAAA,MACZ,gBAAkB;AAAA,MAClB,0BAA4B;AAAA,IAC9B;AAAA,EACF;AAAA,EACA,OAAS;AAAA,IACP;AAAA,MACE,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,MAAQ;AAAA,QACN,EAAE,MAAQ,WAAW,aAAe,2BAA2B;AAAA,QAC/D,EAAE,MAAQ,eAAe,aAAe,iFAAiF;AAAA,MAC3H;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,MAAQ;AAAA,QACN,EAAE,MAAQ,WAAW,aAAe,2BAA2B;AAAA,QAC/D,EAAE,MAAQ,eAAe,aAAe,iFAAiF;AAAA,MAC3H;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,MAAQ;AAAA,QACN,EAAE,MAAQ,WAAW,aAAe,2BAA2B;AAAA,QAC/D,EAAE,MAAQ,eAAe,aAAe,iFAAiF;AAAA,MAC3H;AAAA,MACA,cAAgB;AAAA,IAClB;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,MAAQ;AAAA,QACN,EAAE,MAAQ,WAAW,aAAe,2BAA2B;AAAA,QAC/D,EAAE,MAAQ,eAAe,aAAe,iFAAiF;AAAA,MAC3H;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,MAAQ;AAAA,QACN,EAAE,MAAQ,+BAA+B,aAAe,sCAAsC;AAAA,QAC9F,EAAE,MAAQ,2BAA2B,aAAe,kCAAkC;AAAA,QACtF,EAAE,MAAQ,2BAA2B,aAAe,kCAAkC;AAAA,MACxF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,MAAQ;AAAA,QACN,EAAE,MAAQ,+BAA+B,aAAe,sCAAsC;AAAA,QAC9F,EAAE,MAAQ,2BAA2B,aAAe,kCAAkC;AAAA,QACtF,EAAE,MAAQ,2BAA2B,aAAe,kCAAkC;AAAA,MACxF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,MAAQ;AAAA,QACN,EAAE,MAAQ,+BAA+B,aAAe,sCAAsC;AAAA,QAC9F,EAAE,MAAQ,2BAA2B,aAAe,kCAAkC;AAAA,QACtF,EAAE,MAAQ,2BAA2B,aAAe,kCAAkC;AAAA,MACxF;AAAA,MACA,cAAgB;AAAA,IAClB;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,MAAQ;AAAA,QACN,EAAE,MAAQ,+BAA+B,aAAe,sCAAsC;AAAA,QAC9F,EAAE,MAAQ,2BAA2B,aAAe,kCAAkC;AAAA,QACtF,EAAE,MAAQ,2BAA2B,aAAe,kCAAkC;AAAA,MACxF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,MAAQ;AAAA,QACN,EAAE,MAAQ,eAAe,aAAe,gDAAgD;AAAA,QACxF,EAAE,MAAQ,2BAA2B,aAAe,yCAAyC;AAAA,MAC/F;AAAA,IACF;AAAA,EACF;AACF;;;ACrJA,IAAM,YAAY,MAAsB;AACtC,QAAM,QAAe;AAAA,IACnB,OAAO,CAAC;AAAA,IACR,YAAY,CAAC;AAAA,EACf;AAEA,QAAM,cAAc,cAAU;AAC9B,QAAM,WAAW,cAAU;AAC3B,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,MAAI,UAAU;AACZ,UAAM,WAAW,CAAC;AAClB,aAAS,QAAQ,CAAC,SAAS;AACzB,YAAM,SAAU,KAAK,YAAY,IAAI;AAAA,QACnC,OAAO,KAAK;AAAA,QACZ,aAAa,KAAK;AAAA,QAClB,iBAAiB,KAAK;AAAA,QACtB,UAAU,KAAK;AAAA,QACf,gBAAgB,KAAK;AAAA,QACrB,0BAA0B,KAAK;AAAA,MACjC;AAAA,IACF,CAAC;AAAA,EACH;AAEA,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;;;ACvDR,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,0BAA0B;AAAA,EAC1B,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;AAAA;AAAA,EAGlB,qBAAqB;AAAA,EACrB,qBAAqB;AAAA,EACrB,2BAA2B;AAAA,EAC3B,wBAAwB;AAAA,EACxB,wBAAwB;AAAA,EACxB,oBAAoB;AAAA,EACpB,gCAAgC;AAAA,EAChC,oBAAoB;AAAA,EACpB,yBAAyB;AAAA;AAAA,EAGzB,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,yBAAyB;AAAA,EACzB,cAAc;AAAA;AAAA,EAGd,uBAAuB;AAAA,EACvB,6BAA6B;AAAA,EAC7B,uBAAuB;AAAA,EACvB,wBAAwB;AAAA,EACxB,wBAAwB;AAAA,EACxB,2BAA2B;AAAA,EAC3B,mBAAmB;AAAA,EACnB,gBAAgB;AAAA;AAAA,EAGhB,mBAAmB;AACrB;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;;;AC5MO,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,gCAAgC;AAAA,EAChC,wBAAwB;AAAA,EACxB,wBAAwB;AAAA;AAAA,EAGxB,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,wBAAwB;AAAA,EACxB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,gCAAgC;AAAA;AAAA,EAGhC,qBAAqB;AAAA,EACrB,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,cAAc;AAAA,EACd,qBAAqB;AAAA,EACrB,mBAAmB;AAAA,EACnB,gBAAgB;AAAA;AAAA,EAGhB,eAAe;AAAA,EACf,cAAc;AAAA,EACd,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,cAAc;AAAA,EACd,aAAa;AAAA;AAAA,EAEb,kBAAkB;AAAA,EAClB,aAAa;AAAA,EACb,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,gBAAgB;AAAA;AAAA,EAGhB,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,gBAAgB;AAAA;AAAA,EAGhB,yBAAyB;AAAA,EACzB,iBAAiB;AAAA,EACjB,wBAAwB;AAAA,EACxB,mBAAmB;AAAA,EACnB,yBAAyB;AAAA,EACzB,yBAAyB;AAAA,EACzB,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,uBAAuB;AAAA,EACvB,wBAAwB;AAAA,EACxB,wBAAwB;AAAA;AAAA,EAGxB,mBAAmB;AAAA,EACnB,eAAe;AAAA,EACf,aAAa;AAAA,EACb,cAAc;AAAA;AAAA,EAGd,oBAAoB;AAAA,EACpB,qBAAqB;AAAA,EACrB,aAAa;AAAA,EACb,qBAAqB;AAAA,EACrB,2BAA2B;AAAA,EAC3B,mBAAmB;AAAA,EACnB,6BAA6B;AAAA,EAC7B,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,yBAAyB;AAAA,EACzB,wBAAwB;AAAA;AAAA,EAGxB,2BAA2B;AAAA,EAC3B,2BAA2B;AAAA,EAC3B,iCAAiC;AAAA,EACjC,8BAA8B;AAAA,EAC9B,8BAA8B;AAAA,EAC9B,0BAA0B;AAAA,EAC1B,sCAAsC;AAAA,EACtC,0BAA0B;AAAA,EAC1B,+BAA+B;AAAA;AAAA,EAG/B,wBAAwB;AAAA,EACxB,uBAAuB;AAAA,EACvB,+BAA+B;AAAA,EAC/B,oBAAoB;AAAA;AAAA,EAGpB,6BAA6B;AAAA,EAC7B,mCAAmC;AAAA,EACnC,6BAA6B;AAAA,EAC7B,8BAA8B;AAAA,EAC9B,8BAA8B;AAAA,EAC9B,iCAAiC;AAAA,EACjC,yBAAyB;AAAA,EACzB,sBAAsB;AAAA,EACtB,yBAAyB;AAAA;AAAA;AAAA,EAIzB,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,qBAAqB;AAAA,EACrB,kBAAkB;AAAA,EAClB,sBAAsB;AAAA,EACtB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,mBAAmB;AAAA,EACnB,uBAAuB;AAAA,EACvB,eAAe;AAAA,EACf,sBAAsB;AAAA,EACtB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,oBAAoB;AACtB;AASO,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,8BAA8B,GAC5C;AAAA,EACF,CAAC,eAAe,sBAAsB,GAAG;AAAA,EACzC,CAAC,eAAe,sBAAsB,GAAG;AAAA;AAAA,EAGzC,CAAC,eAAe,YAAY,GAAG;AAAA,EAC/B,CAAC,eAAe,gBAAgB,GAAG;AAAA,EACnC,CAAC,eAAe,sBAAsB,GAAG;AAAA,EACzC,CAAC,eAAe,kBAAkB,GAAG;AAAA,EACrC,CAAC,eAAe,kBAAkB,GAAG;AAAA,EACrC,CAAC,eAAe,kBAAkB,GAAG;AAAA,EACrC,CAAC,eAAe,8BAA8B,GAC5C;AAAA;AAAA,EAGF,CAAC,eAAe,mBAAmB,GAAG;AAAA,EACtC,CAAC,eAAe,YAAY,GAAG;AAAA,EAC/B,CAAC,eAAe,gBAAgB,GAAG;AAAA,EACnC,CAAC,eAAe,YAAY,GAAG;AAAA,EAC/B,CAAC,eAAe,mBAAmB,GAAG;AAAA,EACtC,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,cAAc,GAAG;AAAA;AAAA,EAGjC,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,EAC9B,CAAC,eAAe,gBAAgB,GAAG;AAAA,EACnC,CAAC,eAAe,WAAW,GAAG;AAAA,EAC9B,CAAC,eAAe,aAAa,GAAG;AAAA,EAChC,CAAC,eAAe,aAAa,GAAG;AAAA,EAChC,CAAC,eAAe,aAAa,GAAG;AAAA,EAChC,CAAC,eAAe,cAAc,GAAG;AAAA;AAAA,EAGjC,CAAC,eAAe,gBAAgB,GAAG;AAAA,EACnC,CAAC,eAAe,aAAa,GAAG;AAAA,EAChC,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,cAAc,GAAG;AAAA;AAAA,EAGjC,CAAC,eAAe,uBAAuB,GAAG;AAAA,EAC1C,CAAC,eAAe,eAAe,GAAG;AAAA,EAClC,CAAC,eAAe,sBAAsB,GAAG;AAAA,EACzC,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,uBAAuB,GAAG;AAAA,EAC1C,CAAC,eAAe,uBAAuB,GAAG;AAAA,EAC1C,CAAC,eAAe,eAAe,GAAG;AAAA,EAClC,CAAC,eAAe,gBAAgB,GAAG;AAAA,EACnC,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,qBAAqB,GAAG;AAAA,EACxC,CAAC,eAAe,sBAAsB,GAAG;AAAA,EACzC,CAAC,eAAe,sBAAsB,GAAG;AAAA;AAAA,EAGzC,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;AAAA,EAC9B,CAAC,eAAe,mBAAmB,GAAG;AAAA,EACtC,CAAC,eAAe,yBAAyB,GAAG;AAAA,EAC5C,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,2BAA2B,GAAG;AAAA,EAC9C,CAAC,eAAe,kBAAkB,GAAG;AAAA,EACrC,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,uBAAuB,GAAG;AAAA,EAC1C,CAAC,eAAe,sBAAsB,GAAG;AAAA;AAAA,EAGzC,CAAC,eAAe,yBAAyB,GAAG;AAAA,EAC5C,CAAC,eAAe,yBAAyB,GACvC;AAAA,EACF,CAAC,eAAe,+BAA+B,GAC7C;AAAA,EACF,CAAC,eAAe,4BAA4B,GAC1C;AAAA,EACF,CAAC,eAAe,4BAA4B,GAC1C;AAAA,EACF,CAAC,eAAe,wBAAwB,GACtC;AAAA,EACF,CAAC,eAAe,oCAAoC,GAClD;AAAA,EACF,CAAC,eAAe,wBAAwB,GACtC;AAAA,EACF,CAAC,eAAe,6BAA6B,GAC3C;AAAA;AAAA,EAGF,CAAC,eAAe,sBAAsB,GAAG;AAAA,EACzC,CAAC,eAAe,qBAAqB,GAAG;AAAA,EACxC,CAAC,eAAe,6BAA6B,GAC3C;AAAA,EACF,CAAC,eAAe,kBAAkB,GAAG;AAAA;AAAA,EAGrC,CAAC,eAAe,2BAA2B,GACzC;AAAA,EACF,CAAC,eAAe,iCAAiC,GAC/C;AAAA,EACF,CAAC,eAAe,2BAA2B,GACzC;AAAA,EACF,CAAC,eAAe,4BAA4B,GAAG;AAAA,EAC/C,CAAC,eAAe,4BAA4B,GAC1C;AAAA,EACF,CAAC,eAAe,+BAA+B,GAC7C;AAAA,EACF,CAAC,eAAe,uBAAuB,GAAG;AAAA,EAC1C,CAAC,eAAe,oBAAoB,GAAG;AAAA,EACvC,CAAC,eAAe,uBAAuB,GACrC;AAAA;AAAA,EAGF,CAAC,eAAe,WAAW,GAAG;AAAA,EAC9B,CAAC,eAAe,cAAc,GAAG;AAAA,EACjC,CAAC,eAAe,mBAAmB,GAAG;AAAA,EACtC,CAAC,eAAe,gBAAgB,GAAG;AAAA,EACnC,CAAC,eAAe,oBAAoB,GAAG;AAAA,EACvC,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,eAAe,GAAG;AAAA,EAClC,CAAC,eAAe,cAAc,GAAG;AAAA,EACjC,CAAC,eAAe,UAAU,GAAG;AAAA,EAC7B,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,qBAAqB,GAAG;AAAA,EACxC,CAAC,eAAe,aAAa,GAAG;AAAA,EAChC,CAAC,eAAe,oBAAoB,GAAG;AAAA,EACvC,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,kBAAkB,GAAG;AACvC;AAGO,IAAM,sBACX;AAKK,IAAM,qBAAyD;AAAA;AAAA,EAEpE,CAAC,eAAe,kBAAkB,GAAG;AAAA,EACrC,CAAC,eAAe,2BAA2B,GACzC;AAAA,EACF,CAAC,eAAe,6BAA6B,GAC3C;AAAA,EACF,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,GAC/B;AAAA,EACF,CAAC,eAAe,kBAAkB,GAChC;AAAA,EACF,CAAC,eAAe,2BAA2B,GAAG;AAAA,EAC9C,CAAC,eAAe,0BAA0B,GACxC;AAAA,EACF,CAAC,eAAe,yBAAyB,GACvC;AAAA,EACF,CAAC,eAAe,8BAA8B,GAC5C;AAAA,EACF,CAAC,eAAe,sBAAsB,GAAG;AAAA,EACzC,CAAC,eAAe,sBAAsB,GAAG;AAAA;AAAA,EAGzC,CAAC,eAAe,YAAY,GAAG;AAAA,EAC/B,CAAC,eAAe,gBAAgB,GAAG;AAAA,EACnC,CAAC,eAAe,sBAAsB,GAAG;AAAA,EACzC,CAAC,eAAe,kBAAkB,GAAG;AAAA,EACrC,CAAC,eAAe,kBAAkB,GAAG;AAAA,EACrC,CAAC,eAAe,kBAAkB,GAAG;AAAA,EACrC,CAAC,eAAe,8BAA8B,GAC5C;AAAA;AAAA,EAGF,CAAC,eAAe,mBAAmB,GAAG;AAAA,EACtC,CAAC,eAAe,YAAY,GAAG;AAAA,EAC/B,CAAC,eAAe,gBAAgB,GAAG;AAAA,EACnC,CAAC,eAAe,YAAY,GAAG;AAAA,EAC/B,CAAC,eAAe,mBAAmB,GAAG;AAAA,EACtC,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,cAAc,GAAG;AAAA;AAAA,EAGjC,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,EAC9B,CAAC,eAAe,gBAAgB,GAAG;AAAA,EACnC,CAAC,eAAe,WAAW,GAAG;AAAA,EAC9B,CAAC,eAAe,aAAa,GAAG;AAAA,EAChC,CAAC,eAAe,aAAa,GAAG;AAAA,EAChC,CAAC,eAAe,aAAa,GAAG;AAAA,EAChC,CAAC,eAAe,cAAc,GAAG;AAAA;AAAA,EAGjC,CAAC,eAAe,gBAAgB,GAAG;AAAA,EACnC,CAAC,eAAe,aAAa,GAAG;AAAA,EAChC,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,cAAc,GAAG;AAAA;AAAA,EAGjC,CAAC,eAAe,uBAAuB,GAAG;AAAA,EAC1C,CAAC,eAAe,eAAe,GAAG;AAAA,EAClC,CAAC,eAAe,sBAAsB,GAAG;AAAA,EACzC,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,uBAAuB,GAAG;AAAA,EAC1C,CAAC,eAAe,uBAAuB,GAAG;AAAA,EAC1C,CAAC,eAAe,eAAe,GAAG;AAAA,EAClC,CAAC,eAAe,gBAAgB,GAAG;AAAA,EACnC,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,qBAAqB,GAAG;AAAA,EACxC,CAAC,eAAe,sBAAsB,GAAG;AAAA,EACzC,CAAC,eAAe,sBAAsB,GAAG;AAAA;AAAA,EAGzC,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;AAAA,EAC9B,CAAC,eAAe,mBAAmB,GAAG;AAAA,EACtC,CAAC,eAAe,yBAAyB,GAAG;AAAA,EAC5C,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,2BAA2B,GAAG;AAAA,EAC9C,CAAC,eAAe,kBAAkB,GAAG;AAAA,EACrC,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,uBAAuB,GAAG;AAAA,EAC1C,CAAC,eAAe,sBAAsB,GAAG;AAAA;AAAA,EAGzC,CAAC,eAAe,yBAAyB,GACvC;AAAA,EACF,CAAC,eAAe,yBAAyB,GACvC;AAAA,EACF,CAAC,eAAe,+BAA+B,GAC7C;AAAA,EACF,CAAC,eAAe,4BAA4B,GAC1C;AAAA,EACF,CAAC,eAAe,4BAA4B,GAC1C;AAAA,EACF,CAAC,eAAe,wBAAwB,GACtC;AAAA,EACF,CAAC,eAAe,oCAAoC,GAClD;AAAA,EACF,CAAC,eAAe,wBAAwB,GACtC;AAAA,EACF,CAAC,eAAe,6BAA6B,GAC3C;AAAA;AAAA,EAGF,CAAC,eAAe,sBAAsB,GACpC;AAAA,EACF,CAAC,eAAe,qBAAqB,GAAG;AAAA,EACxC,CAAC,eAAe,6BAA6B,GAC3C;AAAA,EACF,CAAC,eAAe,kBAAkB,GAChC;AAAA;AAAA,EAGF,CAAC,eAAe,2BAA2B,GACzC;AAAA,EACF,CAAC,eAAe,iCAAiC,GAC/C;AAAA,EACF,CAAC,eAAe,2BAA2B,GAAG;AAAA,EAC9C,CAAC,eAAe,4BAA4B,GAC1C;AAAA,EACF,CAAC,eAAe,4BAA4B,GAC1C;AAAA,EACF,CAAC,eAAe,+BAA+B,GAC7C;AAAA,EACF,CAAC,eAAe,uBAAuB,GAAG;AAAA,EAC1C,CAAC,eAAe,oBAAoB,GAAG;AAAA,EACvC,CAAC,eAAe,uBAAuB,GACrC;AAAA;AAAA,EAGF,CAAC,eAAe,WAAW,GAAG;AAAA,EAC9B,CAAC,eAAe,cAAc,GAAG;AAAA,EACjC,CAAC,eAAe,mBAAmB,GAAG;AAAA,EACtC,CAAC,eAAe,gBAAgB,GAAG;AAAA,EACnC,CAAC,eAAe,oBAAoB,GAAG;AAAA,EACvC,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,eAAe,GAAG;AAAA,EAClC,CAAC,eAAe,cAAc,GAAG;AAAA,EACjC,CAAC,eAAe,UAAU,GAAG;AAAA,EAC7B,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,qBAAqB,GAAG;AAAA,EACxC,CAAC,eAAe,aAAa,GAAG;AAAA,EAChC,CAAC,eAAe,oBAAoB,GAAG;AAAA,EACvC,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,kBAAkB,GAAG;AACvC;AAGO,IAAM,mBAAmB,CAAC,MAAM,IAAI;AAcpC,IAAM,qBAGT;AAAA,EACF,IAAI;AAAA,EACJ,IAAI;AACN;AAKO,IAAM,yBAA6D;AAAA,EACxE,QAAQ,eAAe;AAAA,EACvB,OAAO,eAAe;AAAA,EACtB,QAAQ,eAAe;AAAA,EACvB,KAAK,eAAe;AAAA,EACpB,OAAO,eAAe;AAAA,EACtB,OAAO,eAAe;AAAA,EACtB,MAAM,eAAe;AAAA,EACrB,WAAW,eAAe;AAAA,EAC1B,MAAM,eAAe;AAAA,EACrB,QAAQ,eAAe;AAAA,EACvB,QAAQ,eAAe;AAAA,EACvB,QAAQ,eAAe;AAAA,EACvB,SAAS,eAAe;AAC1B;AAKO,IAAM,+BAGT;AAAA,EACF,YAAY,eAAe;AAAA,EAC3B,aAAa,eAAe;AAAA,EAC5B,MAAM,eAAe;AAAA,EACrB,aAAa,eAAe;AAAA,EAC5B,mBAAmB,eAAe;AAAA,EAClC,WAAW,eAAe;AAAA,EAC1B,oBAAoB,eAAe;AAAA,EACnC,YAAY,eAAe;AAAA,EAC3B,WAAW,eAAe;AAAA,EAC1B,gBAAgB,eAAe;AAAA,EAC/B,gBAAgB,eAAe;AACjC;AAKO,IAAM,2BAGT;AAAA,EACF,SAAS,eAAe;AAAA,EACxB,MAAM,eAAe;AAAA,EACrB,UAAU,eAAe;AAAA,EACzB,OAAO,eAAe;AACxB;AAKO,IAAM,8BAGT;AAAA,EACF,gBAAgB,eAAe;AAAA,EAC/B,SAAS,eAAe;AAC1B;AAKO,IAAM,qCAGT;AAAA,EACF,eAAe,eAAe;AAAA,EAC9B,WAAW,eAAe;AAAA,EAC1B,gBAAgB,eAAe;AAAA,EAC/B,gBAAgB,eAAe;AAAA,EAC/B,SAAS,eAAe;AAAA,EACxB,UAAU,eAAe;AAAA,EACzB,UAAU,eAAe;AAC3B;AAKO,IAAM,8BAGT;AAAA,EACF,OAAO,eAAe;AAAA,EACtB,QAAQ,eAAe;AAAA,EACvB,QAAQ,eAAe;AACzB;AAMO,IAAM,2BAET;AAAA,EACF,SAAS,eAAe;AAAA,EACxB,aAAa,eAAe;AAAA,EAC5B,+BAA+B,eAAe;AAAA,EAC9C,2BAA2B,eAAe;AAAA,EAC1C,2BAA2B,eAAe;AAAA,EAC1C,aAAa,eAAe;AAAA,EAC5B,2BAA2B,eAAe;AAC5C;AAMO,IAAM,gCAET;AAAA,EACF,sBAAsB,eAAe;AAAA,EACrC,SAAS,eAAe;AAAA,EACxB,mBAAmB,eAAe;AAAA,EAClC,SAAS,eAAe;AAAA,EACxB,kBAAkB,eAAe;AAAA,EACjC,gBAAgB,eAAe;AAAA,EAC/B,WAAW,eAAe;AAC5B;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,wBAAwB,GACjC,eAAe;AAAA,EACjB,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;AAAA,EAC7C,CAAC,UAAU,mBAAmB,GAAG,eAAe;AAAA,EAChD,CAAC,UAAU,mBAAmB,GAAG,eAAe;AAAA,EAChD,CAAC,UAAU,yBAAyB,GAClC,eAAe;AAAA,EACjB,CAAC,UAAU,sBAAsB,GAC/B,eAAe;AAAA,EACjB,CAAC,UAAU,sBAAsB,GAC/B,eAAe;AAAA,EACjB,CAAC,UAAU,kBAAkB,GAAG,eAAe;AAAA,EAC/C,CAAC,UAAU,8BAA8B,GACvC,eAAe;AAAA,EACjB,CAAC,UAAU,kBAAkB,GAAG,eAAe;AAAA,EAC/C,CAAC,UAAU,uBAAuB,GAChC,eAAe;AAAA,EACjB,CAAC,UAAU,gBAAgB,GAAG,eAAe;AAAA,EAC7C,CAAC,UAAU,eAAe,GAAG,eAAe;AAAA,EAC5C,CAAC,UAAU,uBAAuB,GAChC,eAAe;AAAA,EACjB,CAAC,UAAU,YAAY,GAAG,eAAe;AAAA,EACzC,CAAC,UAAU,qBAAqB,GAAG,eAAe;AAAA,EAClD,CAAC,UAAU,2BAA2B,GACpC,eAAe;AAAA,EACjB,CAAC,UAAU,qBAAqB,GAAG,eAAe;AAAA,EAClD,CAAC,UAAU,sBAAsB,GAC/B,eAAe;AAAA,EACjB,CAAC,UAAU,sBAAsB,GAC/B,eAAe;AAAA,EACjB,CAAC,UAAU,yBAAyB,GAClC,eAAe;AAAA,EACjB,CAAC,UAAU,iBAAiB,GAAG,eAAe;AAAA,EAC9C,CAAC,UAAU,cAAc,GAAG,eAAe;AAAA,EAC3C,CAAC,UAAU,iBAAiB,GAAG,eAAe;AAChD;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;AAMvD,IAAM,4BACX;AAAA,EACE,YAAY,eAAe;AAAA,EAC3B,gBAAgB,eAAe;AAAA,EAC/B,SAAS,eAAe;AAAA,EACxB,eAAe,eAAe;AAAA,EAC9B,YAAY,eAAe;AAAA,EAC3B,aAAa,eAAe;AAAA,EAC5B,aAAa,eAAe;AAC9B;AAMK,IAAM,wBAAkE;AAAA,EAC7E,SAAS,eAAe;AAAA,EACxB,MAAM,eAAe;AAAA,EACrB,UAAU,eAAe;AAAA,EACzB,OAAO,eAAe;AACxB;;;AC3yBO,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;;;ACnDK,IAAM,8BACX,CACE,QACA,YACA,YAEF,CAAC,YAAY;AACX,QAAM,EAAE,MAAM,SAAS,IAAI;AAC3B,SAAO,KAAK,+BAA+B,QAAQ,aAAa,KAAK,EAAE,EAAE;AAEzE,QAAM,SAAS,QAAQ,MAAM,QAAQ;AAErC,MAAI,MAAM,MAAM,GAAG;AACjB,WAAO,MAAM,mCAAmC,OAAO,KAAK,EAAE;AAC9D,UAAM,OAAO,OAAO;AACpB,UAAM,IAAI,cAAc,mBAAmB,YAAY,IAAI,GAAG,MAAM;AAAA,MAClE,QAAQ,KAAK;AAAA,MACb;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,4BAA4B,OAAO,MAAM,MAAM,KAAK,OAAO,MAAM,QAAQ,UAAU,MAAM;AAAA,EAC3F;AACA,SAAO,OAAO;AAChB;;;AChCK,IAAM,wBACX,CACE,QACA,aACA,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,aACA,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;;;ACzDK,IAAM,2BACX,CACE,QACA,YACA,YAEF,CAAC,YAAsC;AACrC,QAAM,EAAE,MAAM,QAAQ,YAAY,SAAS,IAAI;AAC/C,SAAO;AAAA,IACL,0BAA0B,UAAU,cAAc,MAAM,iBAAiB,KAAK;AAAA,MAC5E;AAAA,IACF,CAAC,aAAa,KAAK,EAAE;AAAA,EACvB;AAEA,MAAI,KAAK,WAAW,eAAe,qBAAqB;AACtD,WAAO;AAAA,MACL,wDAAwD,KAAK,WAAW,UAAU;AAAA,IACpF;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,YAAY,QAAQ;AAEzD,MAAI,MAAM,MAAM,GAAG;AACjB,WAAO,MAAM,gCAAgC,OAAO,KAAK,EAAE;AAC3D,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,QACpB,UAAU,QAAQ;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,yBAAyB,UAAU,cAAc,MAAM,iBAAiB,KAAK;AAAA,MAC3E;AAAA,IACF,CAAC,aAAa,KAAK,EAAE;AAAA,EACvB;AACA,SAAO,OAAO;AAChB;;;ACvDK,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,aACA,YAC4B;AAC5B,SAAO,CAAC,YAAY;AAClB,WAAO;AAAA,MACL,mCAAmC,QAAQ,MAAM,MAAM;AAAA,IACzD;AACA,UAAM,UAAU,QAAQ,QAAQ,OAAO,QAAQ,OAAO;AACtD,WAAO,KAAK,4BAA4B;AACxC,WAAO;AAAA,EACT;AACF;;;ACXO,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;;;ACbK,IAAM,mBACX,CACE,QACA,YACA,aAIF,CAAC,YAA8B;AAC7B,QAAM,EAAE,kBAAAE,kBAAiB,IAAI;AAC7B,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;AAIA,QAAM,SAASA,kBAAiB,IAAI;AAEpC,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;;;AChDK,IAAM,+BAA+B,CAC1C,QACA,aACA,MACA,SACA,aACoC;AACpC,SAAO,CAAC,YAAY;AAClB,UAAM,EAAE,MAAM,OAAO,IAAI;AACzB,WAAO,KAAK,GAAG,IAAI,cAAc,UAAU,SAAS,aAAa,KAAK,EAAE,EAAE;AAC1E,UAAM,SAAS,QAAQ,MAAM,MAAM;AACnC,WAAO,KAAK,GAAG,IAAI,KAAK,SAAS,MAAM,CAAC,EAAE;AAC1C,WAAO;AAAA,EACT;AACF;;;ACbO,IAAM,4BAA4B,CACvC,QACA,aACA,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;;;ACzEK,IAAM,wBACX,CACE,QACA,YACA,YAEF,CAAC,YAAmC;AAClC,QAAM,EAAE,MAAM,QAAQ,SAAS,IAAI;AACnC,SAAO;AAAA,IACL,gCAAgC,MAAM,iBAAiB,KAAK;AAAA,MAC1D;AAAA,IACF,CAAC,aAAa,KAAK,EAAE;AAAA,EACvB;AAEA,MAAI,KAAK,WAAW,eAAe,kBAAkB;AACnD,WAAO;AAAA,MACL,qDAAqD,KAAK,WAAW,UAAU;AAAA,IACjF;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,QAAQ;AAE7C,MAAI,MAAM,MAAM,GAAG;AACjB,WAAO,MAAM,6BAA6B,OAAO,KAAK,EAAE;AACxD,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,MACpB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,+BAA+B,MAAM,iBAAiB,KAAK;AAAA,MACzD;AAAA,IACF,CAAC,aAAa,KAAK,EAAE;AAAA,EACvB;AACA,SAAO,OAAO;AAChB;;;AClDK,IAAM,oBACX,CACE,QACA,YACA,YAEF,CAAC,YAA+B;AAC9B,QAAM,EAAE,MAAM,QAAQ,SAAS,IAAI;AACnC,SAAO;AAAA,IACL,2BAA2B,MAAM,iBAAiB,KAAK,UAAU,QAAQ,CAAC,aAAa,KAAK,EAAE;AAAA,EAChG;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,QAAQ;AAE7C,MAAI,MAAM,MAAM,GAAG;AACjB,WAAO,MAAM,wBAAwB,OAAO,KAAK,EAAE;AACnD,UAAM,OAAO,OAAO;AACpB,UAAM,IAAI;AAAA,MACR,mBAAmB,YAAY,IAAI;AAAA,MACnC;AAAA,MACA,EAAE,QAAQ,KAAK,IAAI,QAAQ,SAAS;AAAA,IACtC;AAAA,EACF;AAEA,SAAO,KAAK,0BAA0B,MAAM,aAAa,KAAK,EAAE,EAAE;AAClE,SAAO,OAAO;AAChB;;;ACxCK,IAAM,qBACX,CACE,QACA,YACA,YAEF,CAAC,YAAgC;AAC/B,QAAM,EAAE,MAAM,QAAQ,SAAS,IAAI;AACnC,SAAO;AAAA,IACL,4BAA4B,MAAM,iBAAiB,KAAK;AAAA,MACtD;AAAA,IACF,CAAC,aAAa,KAAK,EAAE;AAAA,EACvB;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,QAAQ;AAE7C,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,MACpB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,2BAA2B,MAAM,iBAAiB,KAAK;AAAA,MACrD;AAAA,IACF,CAAC,aAAa,KAAK,EAAE;AAAA,EACvB;AACA,SAAO,OAAO;AAChB;;;AClDK,IAAM,wBACX,CACE,QACA,YACA,YAEF,CAAC,YAAmC;AAClC,QAAM,EAAE,MAAM,QAAQ,WAAW,UAAU,kBAAkB,IAAI;AACjE,SAAO;AAAA,IACL,sBAAsB,SAAS,cAAc,MAAM,aAAa,KAAK,EAAE;AAAA,EACzE;AAEA,MAAI,KAAK,WAAW,eAAe,kBAAkB;AACnD,WAAO;AAAA,MACL,qDAAqD,KAAK,WAAW,UAAU;AAAA,IACjF;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;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,MAAI,MAAM,MAAM,GAAG;AACjB,WAAO,MAAM,6BAA6B,OAAO,KAAK,EAAE;AACxD,UAAM,OAAO,OAAO;AACpB,UAAM,IAAI;AAAA,MACR,mBAAmB,YAAY,IAAI;AAAA,MACnC;AAAA,MACA;AAAA,QACE,QAAQ,KAAK;AAAA,QACb;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,WAAW,SAAS,wBAAwB,MAAM,aAAa,KAAK,EAAE;AAAA,EACxE;AACA,SAAO,OAAO;AAChB;;;ACrDK,IAAM,mBACX,CACE,QACA,YACA,YAEF,CAAC,YAA8B;AAC7B,QAAM,EAAE,MAAM,QAAQ,YAAY,gBAAgB,oBAAoB,IACpE;AACF,SAAO;AAAA,IACL,2BAA2B,MAAM,eAAe,cAAc,aAAa,KAAK,EAAE;AAAA,EACpF;AAEA,MAAI,KAAK,WAAW,eAAe,aAAa;AAC9C,WAAO;AAAA,MACL,gDAAgD,KAAK,WAAW,UAAU;AAAA,IAC5E;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;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,MAAI,MAAM,MAAM,GAAG;AACjB,WAAO,MAAM,wBAAwB,OAAO,KAAK,EAAE;AACnD,UAAM,OAAO,OAAO;AACpB,UAAM,IAAI;AAAA,MACR,mBAAmB,YAAY,IAAI;AAAA,MACnC;AAAA,MACA,EAAE,QAAQ,KAAK,IAAI,QAAQ,gBAAgB,oBAAoB;AAAA,IACjE;AAAA,EACF;AAEA,SAAO;AAAA,IACL,yBAAyB,MAAM,eAAe,cAAc,aAAa,KAAK,EAAE;AAAA,EAClF;AACA,SAAO,OAAO;AAChB;;;AC3DF,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;;;ACzCO,IAAM,4BACX,CACE,QACA,YACA,YAEF,CAAC,YAAuC;AACtC,QAAM,EAAE,MAAM,OAAO,IAAI;AACzB,SAAO;AAAA,IACL,sCAAsC,MAAM,aAAa,KAAK,EAAE;AAAA,EAClE;AAEA,QAAM,SAAS,QAAQ,MAAM,MAAM;AAEnC,MAAI,MAAM,MAAM,GAAG;AACjB,WAAO,MAAM,mCAAmC,OAAO,KAAK,EAAE;AAC9D,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,SAAO;AAAA,IACL,qCAAqC,MAAM,aAAa,KAAK,EAAE;AAAA,EACjE;AACA,SAAO,OAAO;AAChB;;;ACzBK,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;;;ACpDK,IAAM,mBACX,CACE,QACA,YACA,YAEF,CAAC,YAA8B;AAC7B,QAAM,EAAE,MAAM,QAAQ,WAAW,IAAI;AACrC,SAAO;AAAA,IACL,6BAA6B,UAAU,cAAc,MAAM,aAAa,KAAK,EAAE;AAAA,EACjF;AAEA,MAAI,KAAK,WAAW,eAAe,aAAa;AAC9C,WAAO;AAAA,MACL,gDAAgD,KAAK,WAAW,UAAU;AAAA,IAC5E;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,uBAAuB,OAAO,KAAK,EAAE;AAClD,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,4BAA4B,UAAU,cAAc,MAAM,aAAa,KAAK,EAAE;AAAA,EAChF;AACA,SAAO,OAAO;AAChB;;;ACtDK,IAAM,4BAA+C;AAAA,EAC1D;AAAA,EACA;AACF;AAEO,IAAM,0BAA0B,CAAC,SACtC,0BAA0B,SAAS,KAAK,IAAI;AAMvC,IAAM,uBAAuB,CAClC,MACA,MACA,oBAEA,KAAK,KAAK,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI,MACpC,CAAC,KAAK,gBAAgB,KAAK,iBAAiB;AAMxC,IAAM,0BAA0B,CACrC,YACA,MACA,oBAEA;AAAA,EACE,WAAW;AAAA,IAAO,CAAC,SACjB,qBAAqB,MAAM,MAAM,eAAe;AAAA,EAClD;AACF;;;ACrBK,IAAM,aAAa;AAAA;AAAA,EAExB,YAAY;AAAA;AAAA,EAEZ,gBAAgB;AAAA;AAAA,EAEhB,SAAS;AAAA;AAAA,EAET,eAAe;AAAA;AAAA,EAEf,YAAY;AAAA;AAAA,EAEZ,aAAa;AAAA;AAAA,EAEb,aAAa;AACf;;;AC/BO,IAAM,SAAS;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACeO,IAAM,WAAW;AAKjB,IAAM,mBAAmB;;;AC7BzB,IAAM,kBAAkB;AAAA,EAC7B,WAAW;AAAA,EACX,OAAO;AAAA,EACP,OAAO;AACT;AA2CO,IAAM,gBAAgB;AAAA,EAC3B,SAAS;AAAA,EACT,MAAM;AAAA,EACN,UAAU;AAAA,EACV,OAAO;AACT;AAiCO,IAAM,sBAAsB;AAAA;AAAA,EAEjC,eAAe;AAAA;AAAA,EAEf,WAAW;AAAA;AAAA,EAEX,gBAAgB;AAAA;AAAA,EAEhB,gBAAgB;AAAA;AAAA,EAEhB,SAAS;AAAA;AAAA,EAET,UAAU;AAAA;AAAA,EAEV,UAAU;AACZ;AAOO,IAAM,eAAe;AAAA,EAC1B,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AACV;AAOO,IAAM,gBAA6C;AAAA,EACxD,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AACV;AA6BO,IAAM,eAAe;AAAA,EAC1B,gBAAgB;AAAA,EAChB,SAAS;AACX;AAYO,IAAM,uBAAuB,CAClC,YACkC;AAClC,SAAO,QAAQ,SAAS,aAAa;AACvC;AAOO,IAAM,gBAAgB,CAAC,YAAiD;AAC7E,SAAO,QAAQ,SAAS,aAAa;AACvC;;;ACxHO,IAAM,gBAAgB;AAAA;AAAA,EAE3B,aAAa;AAAA;AAAA,EAEb,YAAY;AAAA;AAAA,EAEZ,MAAM;AAAA;AAAA,EAEN,aAAa;AAAA;AAAA,EAEb,mBAAmB;AAAA;AAAA,EAEnB,WAAW;AAAA;AAAA,EAEX,oBAAoB;AAAA;AAAA,EAEpB,YAAY;AAAA;AAAA,EAEZ,WAAW;AAAA;AAAA,EAEX,gBAAgB;AAAA;AAAA,EAEhB,gBAAgB;AAClB;;;AC7DO,IAAM,kBAAkB;AAAA;AAAA,EAE7B,eAAe;AAAA;AAAA,EAEf,cAAc;AAAA;AAAA,EAEd,SAAS;AAAA;AAAA,EAET,aAAa;AAAA;AAAA,EAEb,OAAO;AAAA;AAAA,EAEP,UAAU;AAAA;AAAA,EAEV,OAAO;AAAA;AAAA,EAEP,OAAO;AAAA;AAAA,EAEP,WAAW;AAAA;AAAA,EAEX,gBAAgB;AAAA;AAAA,EAEhB,UAAU;AAAA;AAAA,EAEV,MAAM;AACR;;;ACrDA,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;AAMO,IAAM,qBAAqB,CAChC,MACA,SACmB,WAAW,SAAS,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;AAEpD,IAAM,sBAAsB,CACjC,MACA,SACkB;AAClB,QAAM,SAAS,mBAAmB,MAAM,IAAI;AAE5C,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;;;ACvBO,IAAM,uBACX,CAAC,SAKD,CAAC,MAAM,UAAU;AACf,QAAM,EAAE,gBAAgB,oBAAoB,eAAAC,eAAc,IAAI;AAC9D,QAAM,sBAAsB,eAAe,YAAY;AAEvD,QAAM,gBAA6B,CAAC;AACpC,QAAM,kBAAkB,KAAK,QAAQ;AAErC,aAAW,QAAQ,OAAO;AACxB,UAAM,aAAa,oBAAoB,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI;AAEpE,QAAI,WAAW,WAAW,GAAG;AAC3B,aAAO,IAAI,UAAU,qBAAqB;AAAA,IAC5C;AAIA,UAAM,YAAY,WAAW;AAAA,MAAK,CAAC,MACjC,qBAAqB,GAAG,KAAK,KAAK,MAAM,eAAe;AAAA,IACzD;AAEA,QAAI,CAAC,WAAW;AACd,aAAO,IAAI,UAAU,wBAAwB;AAAA,IAC/C;AAEA,kBAAc,KAAK,SAAS;AAAA,EAC9B;AAIA,MAAI,eAAe,KAAK,MAAM;AAC9B,MAAI,kBAAkB,KAAK;AAC3B,QAAM,sBAAsB,cAAc,KAAK,uBAAuB;AACtE,MAAI,qBAAqB;AACvB,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;;;AC7FF,IAAM,kBAAkB;AAKjB,IAAM,oBAAoB,CAAC,aAChC,SAAS,WAAW,eAAe;AAK9B,IAAM,+BAA+B,CAAC,aAC3C,aAAa;AAMR,IAAM,gBAAgB,CAAC,YAC3B,OAAO,KAAK,YAAY,WAAW,OAAO,MAAM,YAAY;AAQ/D,IAAM,wBAAqE;AAAA,EACzE,GAAG,CAAC,CAAC;AAAA,EACL,GAAG,CAAC,GAAG,CAAC;AACV;AAOO,IAAM,6BAA6B,CACxC,YACA,iBACQ;AACR,MAAI,gBAAgB,GAAG;AACrB,WAAO;AAAA,EACT;AACA,QAAM,YAAY,sBAAsB,YAAY,KAAK,CAAC;AAC1D,SAAO,WAAW,OAAO,CAAC,GAAG,UAAU,CAAC,UAAU,SAAS,KAAK,CAAC;AACnE;AAMO,IAAM,oBAAoB,CAAC,YAC/B,OAAO,KAAK,gBAAgB,WAAW,OAAO,MAAM,gBAAgB;;;ACpDhE,IAAM,iBAAiB;AAGvB,IAAM,cAAc;AAIpB,IAAM,WAAW,CAAC,QAAgB,YAA4B;AAAA,EACnE,GAAG;AAAA,EACH,QAAQ,OAAO,SAAS,KAAK;AAC/B;AAEO,IAAM,cAAc,CAAC,QAAgB,YAA4B;AAAA,EACtE,GAAG;AAAA,EACH,QAAQ,OAAO,SAAS,KAAK;AAC/B;AAEO,IAAM,YAAY,CAAC,QAAgB,UACvC,OAAO,SAAS,MAAM;AAElB,IAAM,YAAY,CAAC,QAAgB,YAA4B;AAAA,EACpE,GAAG;AAAA,EACH,SAAS,OAAO,UAAU,KAAK;AACjC;AAEO,IAAM,gBAAgB,CAAC,WAA2B,OAAO,UAAU;AAGnE,IAAM,kBAAkB,CAAC,QAAgB,YAA4B;AAAA,EAC1E,GAAG;AAAA,EACH,eAAe,OAAO,gBAAgB,KAAK;AAC7C;AAGO,IAAM,gBAAgB,CAAC,WAC5B,eAAe,OAAO,gBAAgB;;;AC7BxC,IAAM,WAAW,CAAC,WAAsC;AACtD,SAAO,OAAO,SAAS,MAAgB;AACzC;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,EAAE,QAAQ,SAAS;AAAA,IAAG,MACtC,MAAM,KAAK,EAAE,QAAQ,SAAS,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,MACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV,WAAW;AAAA,IACX;AAAA,EACF,GACA;AACA,WAAO,IAAI,UAAU,8BAA8B;AAAA,EACrD;AAEA,QAAM,gBAAgB,WAAW,SAAS,WAAW,UAAU;AAE/D,MAAI,cAAc,WAAW,GAAG;AAC9B,WAAO,IAAI,UAAU,sBAAsB;AAAA,EAC7C;AAEA,MAAI,CAAC,iBAAiB,aAAa,GAAG;AACpC,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;AAIA,IAAM,aAAa,CACjB,SACA,WACA,eACmB;AACnB,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,UAAU,SAAS,KAAK,MAAM,UAAU,SAAS,KACvD,MAAM,WAAW,SAAS,KAAK,MAAM,WAAW,SAAS;AAE5D,QAAM,QAAwB,CAAC;AAE/B,aAAW,OAAO,CAAC,WAAW,UAAU,GAAG;AACzC,eAAW,UAAU,SAAS;AAC5B,YAAM,KAAK,IAAI,SAAS,IAAI,OAAO;AACnC,YAAM,KAAK,IAAI,SAAS,IAAI,OAAO;AACnC,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,cAAM,KAAK,EAAE,UAAU,KAAK,OAAO,KAAK,IAAI,KAAK,CAAC;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,IAAM,mBAAmB,CAAC,UAAmC;AAC3D,SAAO,MAAM;AAAA,IACX,CAAC,EAAE,UAAU,IAAI,MACf,SAAS,SAAS,YAAY,SAAS,SAAS,IAAI;AAAA,EACxD;AACF;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,SAAO,OAAO,OAAO,IAAI,WAAW,OAAO,OAAO,IAAI;AACxD;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;;;AC/UA,IAAMC,uBAAsB;AAKrB,IAAM,gBAAgB,CAAC,aAC5B,SAAS,WAAWA,oBAAmB;AAMlC,IAAM,oBAAoB,CAC/B,aAC+B;AAC/B,MAAI,CAAC,cAAc,QAAQ,EAAG,QAAO;AACrC,SAAO,SAAS,MAAMA,qBAAoB,MAAM;AAClD;AAKO,IAAM,iBAAiB,CAAC,aAA8B;AAC3D,QAAM,MAAM,kBAAkB,QAAQ;AACtC,SAAO,QAAQ,WAAW,QAAQ;AACpC;AAKO,IAAM,cAAc,CAAC,aAA8B;AACxD,SAAO,kBAAkB,QAAQ,MAAM;AACzC;AAKO,IAAM,cAAc,CAAC,aAA8B;AACxD,SAAO,kBAAkB,QAAQ,MAAM;AACzC;;;ACpCA,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;;;ACAA,IAAM,uBAAuB,CAC3B,UACkE;AAClE,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,EAAE,MAAM,MAAM;AAAA,EACvB;AACA,SAAO,EAAE,IAAI,MAAM,IAAI,MAAM,MAAM,MAAM,KAAK,MAAM,IAAI;AAC1D;AAKA,IAAM,oBAAoB,CAAC,YAAoC;AAC7D,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,UAAU,SAAS;AAC5B,QAAI,OAAO,WAAW,YAAY,OAAO,OAAO,OAAW;AAC3D,QAAI,OAAO,OAAO,OAAO,YAAY,OAAO,GAAG,KAAK,EAAE,WAAW,GAAG;AAClE,aAAO;AAAA,IACT;AACA,QAAI,KAAK,IAAI,OAAO,EAAE,EAAG,QAAO;AAChC,SAAK,IAAI,OAAO,EAAE;AAAA,EACpB;AACA,SAAO;AACT;AAEO,IAAM,oBACX,CAAC,SAKD,CAAC,MAAM,YAAY;AACjB,QAAM,EAAE,YAAAC,aAAY,eAAAC,gBAAe,eAAe,IAAI;AAEtD,QAAM,QAAQ,kBAAkB,KAAK,KAAK,IAAI;AAC9C,QAAM,aAAa,QAAQ,IAAI;AAC/B,QAAM,aAAa,QAAQ,IAAI;AAE/B,MACE,CAAC,WACD,QAAQ,SAAS,cACjB,QAAQ,SAAS,YACjB;AACA,WAAO,IAAI,UAAU,oBAAoB;AAAA,EAC3C;AAEA,MAAI,CAAC,kBAAkB,OAAO,GAAG;AAC/B,WAAO,IAAI,UAAU,iBAAiB;AAAA,EACxC;AAEA,QAAM,aAAsB,CAAC;AAE7B,aAAW,UAAU,SAAS;AAC5B,UAAM,EAAE,IAAI,YAAY,MAAM,IAAI,IAAI,qBAAqB,MAAM;AACjE,QAAI,UAAU,mBAAmB;AACjC,cAAU,YAAY,OAAO;AAC7B,UAAM,KAAK,cAAcD,YAAW;AACpC,UAAM,YAAY,aAAa,MAAM,IAAI,SAAS,GAAG;AAErD,QAAI,MAAM,SAAS,GAAG;AACpB,aAAO;AAAA,IACT;AAGA,QAAI,KAAK,KAAK,SAAS,eAAe;AACpC,gBAAU,MAAM,QAAQ;AACxB,gBAAU,MAAM,SAAS;AACzB,gBAAU,MAAM,UAAU,CAAC;AAC3B,gBAAU,MAAM,YAAY,CAAC;AAAA,IAC/B;AAGA,QAAI,OAAO;AACT,gBAAU,MAAM,SAAS,CAAC;AAE1B,UAAI,6BAA6B,KAAK,KAAK,IAAI,GAAG;AAChD,kBAAU,MAAM,QAAQ;AACxB,kBAAU,MAAM,SAAS;AACzB,kBAAU,MAAM,UAAU,CAAC;AAC3B,kBAAU,MAAM,YAAY,CAAC;AAAA,MAC/B;AAAA,IACF;AAGA,QAAI,cAAc,KAAK,KAAK,IAAI,GAAG;AACjC,gBAAU,MAAM,aAAa,CAAC;AAC9B,UAAI,eAAe,KAAK,KAAK,IAAI,GAAG;AAClC,kBAAU,MAAM,YAAY,CAAC;AAAA,MAC/B;AACA,UAAI,YAAY,KAAK,KAAK,IAAI,GAAG;AAC/B,kBAAU,MAAM,UAAU,CAAC;AAAA,MAC7B;AAAA,IACF;AAEA,eAAW,KAAK,UAAU,KAAK;AAAA,EACjC;AAGA,QAAM,QAAQ,eAAe,OAAO;AACpC,QAAM,aACJ,SAAS,MAAM,WACX,MAAM,SAAS,WAAW,MAAM,IAChC,MAAM,MAAM,WAAW,MAAM;AAEnC,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;;;AC3JF,IAAM,qBAAqB;AAQpB,IAAM,kBAAkB,CAC7B,OACA,YACc;AACd,QAAM,WAAW,QAAQ,KAAK;AAC9B,SAAO;AAAA,IACL,SAAS,SAAS,MAAM,GAAG,kBAAkB;AAAA,IAC7C,UAAU,SAAS,MAAM,kBAAkB;AAAA,EAC7C;AACF;AAKO,IAAM,yBAAyB,CACpC,OACA,cACkE;AAClE,QAAM,QAAQ,MAAM,QAAQ,UAAU,CAAC,MAAM,EAAE,OAAO,SAAS;AAC/D,MAAI,UAAU,GAAI,QAAO;AAEzB,QAAM,UAAU,MAAM,QAAQ,KAAK;AACnC,QAAM,aAAa,CAAC,GAAG,MAAM,OAAO;AACpC,aAAW,OAAO,OAAO,CAAC;AAG1B,QAAM,cAAc,CAAC,GAAG,MAAM,QAAQ;AACtC,MAAI,YAAY,SAAS,GAAG;AAC1B,eAAW,KAAK,YAAY,MAAM,CAAE;AAAA,EACtC;AAEA,SAAO;AAAA,IACL;AAAA,IACA,cAAc,EAAE,SAAS,YAAY,UAAU,YAAY;AAAA,EAC7D;AACF;AAKO,IAAM,0BAA0B,CACrC,OACA,cACkE;AAClE,QAAM,QAAQ,MAAM,SAAS,UAAU,CAAC,MAAM,EAAE,OAAO,SAAS;AAChE,MAAI,UAAU,GAAI,QAAO;AAEzB,QAAM,UAAU,MAAM,SAAS,KAAK;AACpC,QAAM,cAAc,CAAC,GAAG,MAAM,QAAQ;AACtC,cAAY,OAAO,OAAO,CAAC;AAE3B,SAAO;AAAA,IACL;AAAA,IACA,cAAc,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,GAAG,UAAU,YAAY;AAAA,EACrE;AACF;AAqBO,IAAM,qBAAqB,CAChC,OACA,cACgC;AAChC,MAAI,MAAM,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS,GAAG;AACjD,WAAO,EAAE,QAAQ,WAAW,eAAe,GAAG,gBAAgB,EAAE;AAAA,EAClE;AACA,MAAI,MAAM,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS,GAAG;AAClD,WAAO,EAAE,QAAQ,YAAY,eAAe,GAAG,gBAAgB,EAAE;AAAA,EACnE;AACA,SAAO;AACT;AAQO,IAAM,yBAAyB,CACpC,SACA,UACA,YACA,WACA,YACY;AACZ,QAAM,OAAO,QAAQ,SAAS,CAAC,IAAI,SAAS,CAAC;AAC7C,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,KAAK,SAAS,WAAW,KAAK,SAAS,SAAU,QAAO;AAG5D,MAAI,KAAK,SAAS,EAAG,QAAO;AAG5B,MACE,WAAW;AAAA,IACT,CAAC,OAAO,GAAG,SAAS,MAAM,SAAS,KAAK,GAAG,SAAS,MAAM,SAAS;AAAA,EACrE;AAEA,WAAO;AAGT,MACE,UAAU;AAAA,IACR,CAAC,MAAM,EAAE,SAAS,MAAM,SAAS,KAAK,EAAE,SAAS,MAAM,SAAS;AAAA,EAClE;AAEA,WAAO;AAGT,MACE,QAAQ;AAAA,IACN,CAAC,MAAM,EAAE,SAAS,MAAM,SAAS,KAAK,EAAE,SAAS,MAAM,SAAS;AAAA,EAClE;AAEA,WAAO;AAET,SAAO;AACT;AAOA,IAAM,mBAAmB;AAAA,EACvB,CAAC,IAAI,EAAE;AAAA,EACP,CAAC,IAAI,CAAC;AAAA,EACN,CAAC,IAAI,CAAC;AAAA,EACN,CAAC,GAAG,EAAE;AAAA,EACN,CAAC,GAAG,CAAC;AAAA,EACL,CAAC,GAAG,EAAE;AAAA,EACN,CAAC,GAAG,CAAC;AAAA,EACL,CAAC,GAAG,CAAC;AACP;AAKO,IAAM,+BAA+B,CAC1C,SACA,SACA,WACA,eACW;AACX,MAAI,QAAQ,QAAQ,SAAS,iBAAkB,QAAO;AAEtD,QAAM,EAAE,YAAY,eAAe,IAAI,QAAQ;AAC/C,QAAM,EAAE,GAAG,EAAE,IAAI,QAAQ;AACzB,MAAI,UAAU;AAEd,aAAW,CAAC,IAAI,EAAE,KAAK,kBAAkB;AACvC,UAAM,KAAK,IAAK;AAChB,UAAM,KAAK,IAAK;AAEhB,YAAQ,YAAY;AAAA,MAClB,KAAK;AACH,YACE,UAAU;AAAA,UACR,CAAC,MACC,EAAE,SAAS,MAAM,MACjB,EAAE,SAAS,MAAM,MACjB,EAAE,SAAS;AAAA,QACf;AAEA;AACF;AAAA,MACF,KAAK;AACH,YACE,UAAU;AAAA,UACR,CAAC,MACC,EAAE,SAAS,MAAM,MAAM,EAAE,SAAS,MAAM,MAAM,EAAE,SAAS;AAAA,QAC7D;AAEA;AACF;AAAA,MACF,KAAK;AACH,YACE,UAAU;AAAA,UACR,CAAC,MACC,EAAE,SAAS,MAAM,MACjB,EAAE,SAAS,MAAM,MACjB,EAAE,SAAS;AAAA,QACf;AAEA;AACF;AAAA,MACF,KAAK;AACH,YACE,UAAU;AAAA,UACR,CAAC,MACC,EAAE,SAAS,MAAM,MAAM,EAAE,SAAS,MAAM,MAAM,EAAE,SAAS;AAAA,QAC7D;AAEA;AACF;AAAA,MACF,KAAK,WAAW;AAEd,cAAM,gBAAgB,oBAAI,IAAkB;AAC5C,mBAAW,KAAK,WAAW;AACzB,cAAI,EAAE,SAAS,MAAM,MAAM,EAAE,SAAS,MAAM,IAAI;AAC9C,0BAAc,IAAI,EAAE,IAAI;AAAA,UAC1B;AAAA,QACF;AACA,mBAAW,cAAc;AACzB;AAAA,MACF;AAAA,MACA,KAAK;AAEH,YAAI,UAAU,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,MAAM,EAAE,SAAS,MAAM,EAAE;AAClE;AACF;AAAA,MACF,KAAK,YAAY;AAEf,cAAM,OAAO,QAAQ,EAAE,IAAI,EAAE;AAC7B,YAAI,QAAQ,KAAK,SAAS,SAAS;AACjC,qBAAW,KAAK;AAAA,QAClB;AACA,YACE,WAAW,KAAK,CAAC,OAAO,GAAG,SAAS,MAAM,MAAM,GAAG,SAAS,MAAM,EAAE,GACpE;AACA,gBAAM,QAAQ,WAAW;AAAA,YACvB,CAAC,OAAO,GAAG,SAAS,MAAM,MAAM,GAAG,SAAS,MAAM;AAAA,UACpD;AACA,cAAI,MAAO,YAAW,MAAM;AAAA,QAC9B;AACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,UAAU;AACnB;AAOO,IAAM,6BAA6B,CACxC,YACW;AACX,QAAM,WAAW,QAAQ,OAAO,CAAC,MAAM,EAAE,QAAQ,SAAS,SAAS;AACnE,MAAI,SAAS,WAAW,EAAG,QAAO;AAElC,QAAM,UAAU,oBAAI,IAAY;AAChC,MAAI,aAAa;AAEjB,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,aAAW,WAAW,UAAU;AAC9B,UAAM,MAAM,GAAG,QAAQ,SAAS,CAAC,IAAI,QAAQ,SAAS,CAAC;AACvD,QAAI,QAAQ,IAAI,GAAG,EAAG;AAGtB,QAAI,YAAY;AAChB,QAAI,aAAa;AACjB,UAAM,QAAyB,CAAC,OAAO;AACvC,YAAQ,IAAI,GAAG;AAEf,WAAO,MAAM,SAAS,GAAG;AACvB,YAAM,UAAU,MAAM,IAAI;AAC1B;AACA,UAAI,QAAQ,QAAQ,SAAS,WAAW;AACtC,sBAAc,QAAQ,QAAQ;AAAA,MAChC;AAEA,iBAAW,CAAC,IAAI,EAAE,KAAK,YAAY;AACjC,cAAM,KAAK,QAAQ,SAAS,IAAK;AACjC,cAAM,KAAK,QAAQ,SAAS,IAAK;AACjC,cAAM,OAAO,GAAG,EAAE,IAAI,EAAE;AAExB,YAAI,CAAC,QAAQ,IAAI,IAAI,GAAG;AACtB,gBAAM,WAAW,SAAS;AAAA,YACxB,CAAC,MAAM,EAAE,SAAS,MAAM,MAAM,EAAE,SAAS,MAAM;AAAA,UACjD;AACA,cAAI,UAAU;AACZ,oBAAQ,IAAI,IAAI;AAChB,kBAAM,KAAK,QAAQ;AAAA,UACrB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,kBAAc,YAAY;AAAA,EAC5B;AAEA,SAAO;AACT;;;AC3TO,IAAM,4BAA4B,CACvC,SACA,qBACW;AACX,MAAI,iBAAiB,WAAW,EAAG,QAAO;AAE1C,QAAM,OAAO,QAAQ;AACrB,QAAM,OAAO,QAAQ,CAAC,EAAG;AACzB,QAAM,UAAuB,QAAQ,IAAI,CAAC,QAAQ,IAAI,IAAI,MAAM,KAAK,CAAC;AAEtE,QAAM,aAAa;AAAA,IACjB,CAAC,IAAI,CAAC;AAAA,IACN,CAAC,GAAG,CAAC;AAAA,IACL,CAAC,GAAG,EAAE;AAAA,IACN,CAAC,GAAG,CAAC;AAAA,EACP;AAGA,QAAM,WAAW,oBAAI,IAAoB;AACzC,aAAW,SAAS,kBAAkB;AACpC,UAAM,MAAM,GAAG,MAAM,SAAS,CAAC,IAAI,MAAM,SAAS,CAAC;AACnD,aAAS,IAAI,MAAM,SAAS,IAAI,GAAG,KAAK,KAAK,MAAM,KAAK;AAAA,EAC1D;AAEA,MAAI,aAAa;AAEjB,WAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC7B,aAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC7B,YAAM,OAAO,QAAQ,CAAC,EAAG,CAAC;AAC1B,UACE,QAAQ,CAAC,EAAG,CAAC,KACb,KAAK,SAAS,WACd,KAAK,SAAS,YACd,KAAK,SAAS,WACd;AACA;AAAA,MACF;AAGA,YAAM,OAAO,KAAK;AAClB,UAAI,OAAO;AACX,UAAI,iBAAiB;AACrB,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;AAGA,cAAM,MAAM,GAAG,EAAE,IAAI,EAAE;AACvB,YAAI,SAAS,IAAI,GAAG,GAAG;AACrB,4BAAkB,SAAS,IAAI,GAAG;AAAA,QACpC;AAEA,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;AAGA,oBAAc,OAAO;AAAA,IACvB;AAAA,EACF;AAEA,SAAO;AACT;;;ACjFO,IAAM,uBAAuB,CAClC,SACA,oBACkB;AAClB,MAAI,YAAY;AAChB,MAAI,WAA0B;AAC9B,MAAI,SAAS;AAEb,aAAW,UAAU,SAAS;AAC5B,UAAM,SAAS,cAAc,MAAM;AACnC,QAAI,SAAS,WAAW;AACtB,kBAAY;AACZ,iBAAW,OAAO;AAClB,eAAS;AAAA,IACX,WAAW,WAAW,aAAa,SAAS,KAAK,aAAa,MAAM;AAClE,eAAS;AAAA,IACX;AAAA,EACF;AAEA,MAAI,UAAU,cAAc,GAAG;AAC7B,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAWA,IAAM,iBAAiB,CAAC,YAAiC;AACvD,QAAM,OAAO,QAAQ;AACrB,QAAM,OAAO,QAAQ,CAAC,GAAG,UAAU;AACnC,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;AAEA,YAAM,cAAc,KAAK;AACzB,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,aAC3B;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,SAAO;AACT;AAeO,IAAM,gBAAgB,CAAC,YAA6B;AACzD,QAAM,aAAa,eAAe,OAAO;AACzC,MAAI,UAAU;AACd,aAAW,QAAQ,YAAY;AAC7B,QAAI,KAAK,OAAO,SAAS;AACvB,gBAAU,KAAK;AAAA,IACjB;AAAA,EACF;AACA,SAAO;AACT;AAMO,IAAM,gCAAgC,CAC3C,QACA,WACW;AACX,QAAM,UAAU,OAAO,SAAS;AAChC,MAAI,CAAC,QAAS,QAAO;AAErB,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK;AACH,aAAO,QAAQ;AAAA,IACjB,KAAK;AACH,cAAQ,OAAO,aAAa,CAAC,GAAG,SAAS,QAAQ;AAAA,IACnD,KAAK;AACH,aAAO,cAAc,MAAM,IAAI,QAAQ;AAAA,IACzC,KAAK,YAAY;AACf,YAAM,cAAc;AAAA,QAClB,OAAO;AAAA,SACN,OAAO,UAAU,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ;AAAA,MAC7C;AACA,aAAO,cAAc,QAAQ;AAAA,IAC/B;AAAA,IACA,KAAK;AACH,aAAO,QAAQ,UACX,kBAAkB,OAAO,SAAS,QAAQ,OAAO,IAAI,QAAQ,SAC7D;AAAA,IACN;AACE,aAAO;AAAA,EACX;AACF;AAeA,IAAM,qBAAqB,CACzB,SACA,iBAA6B,CAAC,MACnB;AACX,QAAM,UAAU,IAAI,IAAI,eAAe,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;AAClE,MAAI,QAAQ;AACZ,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,MAAM,QAAQ,CAAC;AACrB,aAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,YAAM,OAAO,IAAI,CAAC;AAClB,UAAI,KAAK,SAAS,WAAW,KAAK,SAAS,UAAU;AACnD,iBAAS,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC,EAAE,IAC5B,KAAK,IAAI,GAAG,KAAK,SAAS,CAAC,IAC3B,KAAK;AAAA,MACX;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAkBA,IAAM,oBAAoB,CAAC,SAAkB,YAA4B;AACvE,MAAI,QAAQ;AACZ,aAAW,OAAO,SAAS;AACzB,eAAW,QAAQ,KAAK;AACtB,UAAI,KAAK,SAAS,SAAS;AACzB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;;;ACjNA,IAAM,qBAAqB,CACzB,YACyC;AACzC,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,MAAM,QAAQ,CAAC;AACrB,aAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,UAAI,IAAI,CAAC,EAAG,SAAS,UAAU;AAC7B,eAAO,EAAE,GAAG,EAAE;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAKA,IAAMC,kBAAiB,CACrB,YAC2E;AAC3E,MAAI,OAAO,OAAO;AAClB,MAAI,OAAO,OAAO;AAClB,MAAI,OAAO;AACX,MAAI,OAAO;AAEX,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,MAAM,QAAQ,CAAC;AACrB,aAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,UAAI,IAAI,CAAC,EAAG,SAAS,SAAS;AAC5B,eAAO,KAAK,IAAI,MAAM,CAAC;AACvB,eAAO,KAAK,IAAI,MAAM,CAAC;AACvB,eAAO,KAAK,IAAI,MAAM,CAAC;AACvB,eAAO,KAAK,IAAI,MAAM,CAAC;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,SAAS,GAAI,QAAO;AACxB,SAAO,EAAE,MAAM,MAAM,MAAM,KAAK;AAClC;AAKO,IAAM,2BAA2B,CACtC,SACA,SACA,mBACW;AACX,QAAM,SAAS,mBAAmB,OAAO;AACzC,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,aAAa;AAAA,IACjB,CAAC,IAAI,EAAE;AAAA,IACP,CAAC,IAAI,CAAC;AAAA,IACN,CAAC,IAAI,CAAC;AAAA,IACN,CAAC,GAAG,EAAE;AAAA,IACN,CAAC,GAAG,CAAC;AAAA,IACL,CAAC,GAAG,EAAE;AAAA,IACN,CAAC,GAAG,CAAC;AAAA,IACL,CAAC,GAAG,CAAC;AAAA,EACP;AAEA,MAAI,QAAQ;AACZ,aAAW,CAAC,IAAI,EAAE,KAAK,YAAY;AACjC,UAAM,KAAK,OAAO,IAAK;AACvB,UAAM,KAAK,OAAO,IAAK;AACvB,UAAM,OAAO,QAAQ,EAAE,IAAI,EAAE;AAC7B,QAAI,QAAQ,KAAK,SAAS,SAAS;AACjC;AAAA,IACF;AAAA,EACF;AAEA,SAAO,QAAQ;AACjB;AAKO,IAAM,+BAA+B,CAC1C,SACA,SACA,mBACW;AACX,QAAM,MAAMA,gBAAe,OAAO;AAClC,MAAI,CAAC,IAAK,QAAO;AAEjB,QAAM,UAAU;AAAA,IACd,EAAE,GAAG,IAAI,MAAM,GAAG,IAAI,KAAK;AAAA,IAC3B,EAAE,GAAG,IAAI,MAAM,GAAG,IAAI,KAAK;AAAA,IAC3B,EAAE,GAAG,IAAI,MAAM,GAAG,IAAI,KAAK;AAAA,IAC3B,EAAE,GAAG,IAAI,MAAM,GAAG,IAAI,KAAK;AAAA,EAC7B;AAEA,MAAI,QAAQ;AACZ,aAAW,UAAU,SAAS;AAC5B,UAAM,OAAO,QAAQ,OAAO,CAAC,IAAI,OAAO,CAAC;AACzC,QAAI,QAAQ,KAAK,SAAS,SAAS;AACjC;AAAA,IACF;AAAA,EACF;AAEA,SAAO,QAAQ;AACjB;AAKO,IAAM,2BAA2B,CACtC,SACA,WACW;AACX,QAAM,SAAS,mBAAmB,OAAO;AACzC,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,MAAMA,gBAAe,OAAO;AAClC,MAAI,CAAC,IAAK,QAAO;AAEjB,QAAM,WACH,OAAO,MAAM,IAAI,QAAQ,OAAO,MAAM,IAAI,QAC1C,OAAO,MAAM,IAAI,QAAQ,OAAO,MAAM,IAAI,QAC1C,OAAO,MAAM,IAAI,QAAQ,OAAO,MAAM,IAAI,QAC1C,OAAO,MAAM,IAAI,QAAQ,OAAO,MAAM,IAAI;AAE7C,SAAO,WAAW,SAAS;AAC7B;AAMO,IAAM,4BAA4B,CACvC,SACA,QACA,WACW;AACX,QAAM,OAAO,QAAQ;AACrB,QAAM,OAAO,QAAQ,CAAC,EAAG;AAGzB,QAAM,WAAwB,MAAM;AAAA,IAAK,EAAE,QAAQ,KAAK;AAAA,IAAG,MACzD,MAAM,KAAK,EAAE,QAAQ,KAAK,GAAG,MAAM,KAAK;AAAA,EAC1C;AAEA,WAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC7B,aAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC7B,YAAM,OAAO,QAAQ,CAAC,EAAG,CAAC;AAC1B,UAAI,KAAK,SAAS,WAAW,KAAK,SAAS,YAAY,KAAK,SAAS,GAAG;AACtE,cAAM,iBAAiB,OAAO;AAAA,UAC5B,CAAC,MAAM,EAAE,SAAS,MAAM,KAAK,EAAE,SAAS,MAAM;AAAA,QAChD;AACA,YAAI,CAAC,gBAAgB;AACnB,mBAAS,CAAC,EAAG,CAAC,IAAI;AAAA,QACpB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,aAAa;AAGjB,QAAM,aAAa;AAAA,IACjB,EAAE,IAAI,GAAG,IAAI,EAAE;AAAA;AAAA,IACf,EAAE,IAAI,GAAG,IAAI,EAAE;AAAA;AAAA,IACf,EAAE,IAAI,GAAG,IAAI,EAAE;AAAA;AAAA,IACf,EAAE,IAAI,GAAG,IAAI,GAAG;AAAA;AAAA,EAClB;AAEA,aAAW,EAAE,IAAI,GAAG,KAAK,YAAY;AAEnC,UAAM,UAAuB,MAAM;AAAA,MAAK,EAAE,QAAQ,KAAK;AAAA,MAAG,MACxD,MAAM,KAAK,EAAE,QAAQ,KAAK,GAAG,MAAM,KAAK;AAAA,IAC1C;AAEA,aAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC7B,eAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC7B,YAAI,QAAQ,CAAC,EAAG,CAAC,KAAK,CAAC,SAAS,CAAC,EAAG,CAAC,EAAG;AAGxC,YAAI,SAAS;AACb,YAAI,KAAK;AACT,YAAI,KAAK;AACT,eACE,MAAM,KACN,KAAK,QACL,MAAM,KACN,KAAK,QACL,SAAS,EAAE,EAAG,EAAE,GAChB;AACA,kBAAQ,EAAE,EAAG,EAAE,IAAI;AACnB;AACA,gBAAM;AACN,gBAAM;AAAA,QACR;AAEA,YAAI,UAAU,GAAG;AACf;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,aAAa;AACtB;AAKO,IAAM,4BAA4B,CACvC,SACA,WACW;AACX,QAAM,mBAA6B,CAAC,SAAS,UAAU,OAAO,OAAO;AACrE,QAAM,OAAO,QAAQ;AACrB,QAAM,OAAO,QAAQ,CAAC,EAAG;AACzB,QAAM,UAAuB,MAAM;AAAA,IAAK,EAAE,QAAQ,KAAK;AAAA,IAAG,MACxD,MAAM,KAAK,EAAE,QAAQ,KAAK,GAAG,MAAM,KAAK;AAAA,EAC1C;AAEA,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,MAAI,uBAAuB;AAE3B,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,CAAC,iBAAiB,SAAS,KAAK,IAAc;AAClE;AACF,UAAI,KAAK,SAAS,WAAW,KAAK,SAAS,SAAU;AAGrD,YAAM,OAAO,KAAK;AAClB,UAAI,OAAO;AACX,UAAI,cAAc;AAClB,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,YAAI,QAAQ,SAAS,EAAG,eAAc;AAEtC,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,UAAI,QAAQ,KAAK,CAAC,aAAa;AAC7B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,uBAAuB;AAChC;AAOO,IAAM,sBAAsB,CACjC,OACA,SACA,QACA,sBACW;AACX,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK,WAAW;AACd,aAAO,yBAAyB,SAAS,MAAM,SAAU,MAAM,MAAM;AAAA,IAEvE,KAAK,WAAW;AACd,aAAO;AAAA,QACL;AAAA,QACA,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IAEF,KAAK,WAAW,SAAS;AAEvB,YAAM,gBAAgB,cAAc,OAAO;AAC3C,aAAO,kBAAkB,oBAAoB,MAAM,SAAS;AAAA,IAC9D;AAAA,IAEA,KAAK,WAAW;AACd,aAAO,sBAAsB,OAAO,IAAI,MAAM,SAAS;AAAA,IAEzD,KAAK,WAAW;AACd,aAAO,yBAAyB,SAAS,MAAM,MAAM;AAAA,IAEvD,KAAK,WAAW;AACd,aAAO,0BAA0B,SAAS,QAAQ,MAAM,MAAM;AAAA,IAEhE,KAAK,WAAW;AACd,aAAO,0BAA0B,SAAS,MAAM,MAAM;AAAA,IAExD;AACE,aAAO;AAAA,EACX;AACF;;;AC9TO,IAAM,oBAAoB,CAAC,YAAyC;AACzE,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAcO,IAAM,wBAAwB,CACnC,MACA,aACoB;AACpB,QAAM,eAAe,kBAAkB,KAAK,IAAI;AAChD,MAAI,iBAAiB,QAAQ,KAAK,SAAS,EAAG,QAAO;AACrD,SAAO,EAAE,MAAM,cAAc,SAAS;AACxC;AAkBO,IAAM,uBAAuB,CAClC,cACiC;AACjC,QAAM,SAAuC;AAAA,IAC3C,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,OAAO;AAAA,EACT;AACA,aAAW,KAAK,WAAW;AACzB,WAAO,EAAE,IAAI;AAAA,EACf;AACA,SAAO;AACT;AAQO,IAAM,oBAAoB,CAC/B,WACA,WACA,2BACY;AACZ,QAAM,UAAU,UAAU;AAAA,IAAI,CAAC,QAC7B,UAAU,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,IAAI,KAAK,EAAE,SAAS,MAAM,IAAI,CAAC;AAAA,EACxE;AAGA,MAAI,QAAQ,KAAK,CAAC,MAAM,MAAM,MAAS,EAAG,QAAO;AAGjD,QAAM,QAAQ,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,EAAG,IAAI,CAAC;AACjD,SAAO,MAAM,QAAQ;AACvB;AAMO,IAAM,yBAAyB,CACpC,WACA,WACA,OACA,2BAEA,UAAU,WAAW,SACrB,kBAAkB,WAAW,WAAW,sBAAsB;AAUzD,IAAM,2BAA2B,CACtC,WACA,OACA,2BACiB;AACjB,QAAM,WAAyB,CAAC;AAChC,QAAM,SAAqB,CAAC;AAE5B,QAAM,UAAU,CAAC,UAAwB;AACvC,QAAI,OAAO,WAAW,OAAO;AAC3B,YAAM,YAAY,OAAO,IAAI,CAAC,MAAM,EAAE,QAAQ;AAC9C,UACE;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,GACA;AACA,iBAAS,KAAK,SAAS;AAAA,MACzB;AACA;AAAA,IACF;AACA,UAAM,iBACJ,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,QAAQ,QAAQ,OAAO;AAC5D,QAAI,iBAAiB,uBAAwB;AAE7C,aAAS,IAAI,OAAO,KAAK,UAAU,UAAU,QAAQ,OAAO,SAAS,KAAK;AACxE,aAAO,KAAK,UAAU,CAAC,CAAE;AACzB,cAAQ,IAAI,CAAC;AACb,aAAO,IAAI;AAAA,IACb;AAAA,EACF;AAEA,MAAI,QAAQ,EAAG,SAAQ,CAAC;AACxB,SAAO;AACT;AAKO,IAAM,iBAAiB,CAC5B,WACA,cACe;AACf,QAAM,SAAS,IAAI,IAAI,UAAU,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;AAC5D,SAAO,UAAU;AAAA,IACf,CAAC,MAAM,CAAC,OAAO,IAAI,GAAG,EAAE,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE;AAAA,EACtD;AACF;;;AC5JO,IAAM,gBAA8C;AAAA,EACzD,SAAS;AAAA,EACT,MAAM;AAAA,EACN,UAAU;AAAA,EACV,OAAO;AACT;AAEA,IAAM,iBAAiC,CAAC,WAAW,QAAQ,YAAY,OAAO;AAgBvE,IAAM,wBAAwB,CACnC,SACA,kBACe;AACf,QAAM,SAAqB,EAAE,GAAG,cAAc;AAE9C,aAAW,gBAAgB,gBAAgB;AACzC,UAAM,SAAS,QAAQ;AAAA,MACrB,CAAC,WAAW,qBAAqB,OAAO,aAAa,CAAC,CAAC,EAAE,YAAY;AAAA,IACvE;AACA,UAAM,WAAW,KAAK,IAAI,GAAG,GAAG,MAAM;AACtC,UAAM,UAAU,QAAQ,OAAO,CAAC,GAAG,UAAU,OAAO,KAAK,MAAM,QAAQ;AACvE,UAAM,SAAS,OAAO,YAAY;AAElC,QAAI,aAAa,GAAG;AAElB,aAAO,YAAY,IAAI;AAAA,IACzB,WAAW,QAAQ,WAAW,GAAG;AAE/B,aAAO,YAAY,IAAI,QAAQ,CAAC,EAAG;AAAA,IACrC,WAAW,WAAW,QAAQ,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,GAAG;AAElE,aAAO,YAAY,IAAI;AAAA,IACzB,WAAW,WAAW,QAAQ,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,GAAG;AAElE,aAAO,YAAY,IAAI,QAAQ,CAAC,EAAG;AAAA,IACrC,OAAO;AAEL,aAAO,YAAY,IAAI;AAAA,IACzB;AAAA,EACF;AAEA,SAAO;AACT;AAMO,IAAM,sBAAsB,CACjC,SACA,YAC6B;AAC7B,MAAI,CAAC,SAAS,OAAQ,QAAO;AAC7B,SAAO;AAAA,IACL,GAAG;AAAA,IACH,QAAQ,sBAAsB,SAAS,QAAQ,MAAM;AAAA,EACvD;AACF;;;ACtCA,IAAM,wBAAwB;AAE9B,IAAM,iBAAiB;AAEvB,IAAM,aAAa;AAAA,EACjB,CAAC,IAAI,CAAC;AAAA,EACN,CAAC,GAAG,CAAC;AAAA,EACL,CAAC,GAAG,EAAE;AAAA,EACN,CAAC,GAAG,CAAC;AACP;AAOO,IAAM,qBAAqB,CAChC,SACA,iBAA6B,CAAC,MACT;AACrB,QAAM,OAAO,QAAQ;AACrB,QAAM,OAAO,QAAQ,CAAC,GAAG,UAAU;AACnC,QAAM,UAAuB,QAAQ,IAAI,CAAC,QAAQ,IAAI,IAAI,MAAM,KAAK,CAAC;AACtE,QAAM,WAAW,IAAI,IAAI,eAAe,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;AACnE,QAAM,cAAgC,CAAC;AAEvC,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;AAEA,YAAM,UAAU,KAAK;AACrB,YAAM,QAAoB,CAAC;AAC3B,UAAI,SAAS;AACb,UAAI,gBAAgB;AACpB,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,cAAM,KAAK,EAAE,GAAG,IAAI,GAAG,GAAG,CAAC;AAE3B,cAAM,UAAU,SAAS,IAAI,GAAG,EAAE,IAAI,EAAE,EAAE,IACtC,KAAK,IAAI,GAAG,QAAQ,SAAS,CAAC,IAC9B,QAAQ;AACZ,kBAAU;AACV,yBAAiB,QAAQ,SAAS;AAElC,mBAAW,CAAC,IAAI,EAAE,KAAK,YAAY;AACjC,gBAAM,KAAK,KAAK;AAChB,gBAAM,KAAK,KAAK;AAChB,cACE,MAAM,KACN,MAAM,KACN,KAAK,QACL,KAAK,QACL,CAAC,QAAQ,EAAE,EAAG,EAAE,KAChB,QAAQ,EAAE,EAAG,EAAE,EAAG,SAAS,SAC3B;AACA,oBAAQ,EAAE,EAAG,EAAE,IAAI;AACnB,kBAAM,KAAK,CAAC,IAAI,EAAE,CAAC;AAAA,UACrB;AAAA,QACF;AAAA,MACF;AAEA,YAAM,KAAK,CAAC,GAAG,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAC3C,kBAAY,KAAK;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,QAAQ,MAAM,SAAS;AAAA,MACzB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;AAKO,IAAM,aAAa,CAAC,SACzB,KAAK,WAAW,SAAS,UAAU,KAAK,WAAW,SAAS;AAG9D,IAAM,4BAA4B,CAAC,SACjC,KAAK,MAAM,MAAM,QAAQ,KAAK,MAAM,MAAM;AAE5C,IAAM,qBAAqB,CACzB,MACA,QACA,gBACiB;AACjB,MAAI,CAAC,KAAK,YAAa,QAAO,CAAC;AAC/B,QAAM,UAAwB,CAAC;AAG/B,MACE,KAAK,YAAY,kBAAkB,QACnC,KAAK,YAAY,kBAAkB,OAAO,IAC1C;AACA,YAAQ,KAAK;AAAA,MACX,MAAM;AAAA,MACN,OAAO,eAAe;AAAA,MACtB,QAAQ,cAAc,OAAO,OAAO;AAAA,MACpC;AAAA,IACF,CAAC;AAAA,EACH;AAGA,aAAW,UAAU,OAAO,aAAa,CAAC,GAAG;AAC3C,QAAI,CAAC,OAAO,SAAS,eAAgB;AACrC,YAAQ,KAAK;AAAA,MACX,MAAM;AAAA,MACN,OAAO,eAAe;AAAA,MACtB,aAAa,EAAE,MAAM,OAAO,SAAS,KAAK;AAAA,MAC1C,QAAQ,8BAA8B,QAAQ,MAAM;AAAA,MACpD;AAAA,MACA,YAAY,OAAO,SAAS;AAAA,MAC5B,UAAU,OAAO;AAAA,IACnB,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,IAAM,iBAAiB,CACrB,MACA,QACA,gBACiB;AACjB,QAAM,WAAW,KAAK,KAAK;AAC3B,MAAI,CAAC,cAAc,QAAQ,EAAG,QAAO,CAAC;AACtC,QAAM,UAAwB,CAAC;AAC/B,QAAM,aAAa,OAAO,cAAc,CAAC;AACzC,QAAM,YAAY,OAAO,aAAa,CAAC;AAGvC,MAAI,WAAW,SAAS,GAAG;AACzB,YAAQ,KAAK;AAAA,MACX,MAAM;AAAA,MACN,OAAO,eAAe;AAAA,MACtB,QAAQ,0BAA0B,OAAO,SAAS,UAAU;AAAA,MAC5D;AAAA,IACF,CAAC;AAAA,EACH;AAIA,MAAI,YAAY,QAAQ,KAAK,KAAK,SAAS,QAAQ;AACjD,YAAQ,KAAK;AAAA,MACX,MAAM;AAAA,MACN,OAAO,eAAe;AAAA,MACtB,QAAQ,UAAU;AAAA,MAClB;AAAA,IACF,CAAC;AAED,UAAM,UAAU,sBAAsB,KAAK,SAAS,KAAK,QAAQ,MAAM;AACvE,eAAW,YAAY,OAAO,OAAO,aAAa,GAAG;AACnD,UAAI,QAAQ,QAAQ,MAAM,OAAO,GAAI;AACrC,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,OAAO,sBAAsB,QAAQ;AAAA,QACrC,QAAQ,cAAc,QAAQ;AAAA,QAC9B;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAGA,QAAM,UAAU,OAAO,WAAW,CAAC;AACnC,MAAI,YAAY,QAAQ,KAAK,QAAQ,SAAS,GAAG;AAC/C,eAAW,UAAU,SAAS;AAC5B,YAAM,EAAE,QAAQ,IAAI;AACpB,UAAI,QAAQ,SAAS,iBAAkB;AACvC,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,OAAO,mCAAmC,QAAQ,UAAU;AAAA,QAC5D,QAAQ;AAAA,UACN;AAAA,UACA,OAAO;AAAA,UACP;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,QACA,WAAW,QAAQ;AAAA,QACnB,UAAU,OAAO;AAAA,MACnB,CAAC;AAAA,IACH;AAEA,QAAI,QAAQ,KAAK,CAAC,WAAW,OAAO,QAAQ,SAAS,SAAS,GAAG;AAC/D,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,OAAO,eAAe;AAAA,QACtB,QAAQ,2BAA2B,OAAO;AAAA,QAC1C;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;AAEA,IAAM,eAAe,CACnB,MACA,QACA,UACiB;AACjB,MAAI,CAAC,kBAAkB,KAAK,KAAK,IAAI,KAAK,CAAC,KAAK,aAAa,YAAY;AACvE,WAAO,CAAC;AAAA,EACV;AACA,QAAM,SAAS,OAAO,UAAU,CAAC;AAEjC,SAAO,KAAK,YAAY,WACrB,OAAO,CAAC,UAAqB,SAAS,MAAM,SAAS,WAAW,OAAO,EACvE;AAAA,IACC,CAAC,WAAuB;AAAA,MACtB,MAAM;AAAA,MACN,OAAO,0BAA0B,MAAM,IAAI;AAAA,MAC3C,QAAQ;AAAA,QACN;AAAA,QACA,OAAO;AAAA,QACP;AAAA,QACA,0BAA0B,IAAI;AAAA,MAChC;AAAA,MACA,aAAa,CAAC;AAAA,MACd,SAAS,MAAM;AAAA,MACf,WAAW,MAAM;AAAA,MACjB,GAAI,MAAM,WAAW,EAAE,SAAS,MAAM,QAAQ;AAAA,IAChD;AAAA,EACF;AACJ;AAEA,IAAM,mBAAmB,CACvB,MACA,QACA,UACiB;AACjB,QAAM,UAAwB,CAAC;AAC/B,QAAM,cAAc,CAAC;AAErB,aAAW,aAAa,KAAK,MAAM,OAAO;AAGxC,QACE,UAAU,SAAS,wBACnB,UAAU,SAAS,kBACnB;AACA,YAAM,kBAAkB,UAAU,SAAS;AAC3C,cAAQ,KAAK;AAAA,QACX,MAAM,kBAAkB,kBAAkB;AAAA,QAC1C,OAAO,kBACH,eAAe,sBACf,eAAe;AAAA,QACnB,QAAQ,sBAAsB,OAAO,OAAO,IACxC,wBACA;AAAA,QACJ;AAAA,MACF,CAAC;AAAA,IACH;AAKA,QACE,UACC,UAAU,SAAS,aAAa,UAAU,SAAS,iBACpD;AACA,YAAM,YAAY,UAAU,SAAS;AACrC,cAAQ,KAAK;AAAA,QACX,MAAM,YAAY,YAAY;AAAA,QAC9B,OAAO,YACH,eAAe,eACf,eAAe;AAAA,QACnB,QACE,cAAc,OAAO,OAAO,MAAM,0BAA0B,IAAI,IAC5D,iBACA;AAAA,QACN;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;AAEA,IAAM,MAAM,CAAC,WACX,OAAO,OAAO,CAAC,OAAO,UAAU,QAAQ,MAAM,QAAQ,CAAC;AAQlD,IAAM,wBAAwB,CACnC,MACA,QACA,UACmB;AACnB,QAAM,cAAc;AAAA,IAClB,OAAO;AAAA,IACP,OAAO,QAAQ,IAAI,CAAC,MAAM,EAAE,QAAQ;AAAA,EACtC;AACA,QAAM,cAAc,CAAC;AAErB,QAAM,UAAwB;AAAA,IAC5B,GAAG,mBAAmB,MAAM,QAAQ,WAAW;AAAA,IAC/C,GAAG,eAAe,MAAM,QAAQ,WAAW;AAAA,IAC3C,GAAG,aAAa,MAAM,QAAQ,KAAK;AAAA,IACnC,GAAG,iBAAiB,MAAM,QAAQ,KAAK;AAAA,EACzC;AAEA,QAAM,kBAAkB,IAAI,WAAW;AACvC,QAAM,cAAc,IAAI,OAAO;AAE/B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO,kBAAkB;AAAA,EAC3B;AACF;AAMO,IAAM,qBAAqB,CAChC,MACA,QACA,QAAiB,WAAW,IAAI,MAChB;AAChB,QAAM,YAAY,sBAAsB,MAAM,QAAQ,KAAK;AAC3D,QAAM,EAAE,YAAY,IAAI;AAExB,SAAO;AAAA,IACL,UAAU,OAAO;AAAA,IACjB,YAAY,OAAO;AAAA,IACnB,QAAQ,UAAU;AAAA,IAClB,mBAAmB,YAAY;AAAA,MAC7B,CAAC,KAAK,cAAc,KAAK,IAAI,KAAK,UAAU,MAAM,MAAM;AAAA,MACxD;AAAA,IACF;AAAA,IACA,aAAa,YAAY;AAAA,MACvB,CAAC,OAAO,cAAc,QAAQ,UAAU;AAAA,MACxC;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACnYO,IAAM,8BAA2D,CACtE,MACA,aACG;AACH,QAAM,SAAS,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ;AACzD,MAAI,CAAC,QAAQ;AACX,WAAO,IAAI,UAAU,gBAAgB;AAAA,EACvC;AAEA,SAAO,GAAG,mBAAmB,MAAM,MAAM,CAAC;AAC5C;;;ACZO,IAAM,wBAA+C,CAC1D,SACA,mBACG;AACH,QAAM,cAAc,mBAAmB,SAAS,cAAc;AAE9D,MAAI,SAAS;AACb,MAAI,oBAAoB;AACxB,MAAI,cAAc;AAElB,aAAW,aAAa,aAAa;AACnC,cAAU,UAAU;AACpB,wBAAoB,KAAK,IAAI,mBAAmB,UAAU,MAAM,MAAM;AACtE,mBAAe,UAAU;AAAA,EAC3B;AAEA,SAAO,GAAG;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;;;AChBA,IAAM,cAAc;AAEb,IAAM,sBAAsB,CACjC,OACA,YACkB;AAClB,QAAM,WAAW,QAAQ,CAAC,GAAG,KAAK,CAAC;AACnC,QAAM,QAAQ,SAAS,MAAM,GAAG,WAAW;AAC3C,QAAM,WAAW,SAAS,MAAM,WAAW;AAE3C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;AAMO,IAAM,sBAAsB,CAAC,UAAwC;AAC1E,QAAM,WAAW,CAAC,GAAG,MAAM,KAAK;AAChC,QAAM,cAAc,CAAC,GAAG,MAAM,QAAQ;AAEtC,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,QAAI,SAAS,CAAC,MAAM,QAAQ,YAAY,SAAS,GAAG;AAClD,eAAS,CAAC,IAAI,YAAY,MAAM;AAAA,IAClC;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,UAAU,UAAU,YAAY;AAClD;AASO,IAAM,2BAA2B,CACtC,WACsB;AAAA,EACtB,GAAG;AAAA,EACH,eAAe,oBAAoB,MAAM,aAAa;AAAA,EACtD,qBAAqB;AACvB;AAEO,IAAM,sBAAsB,CACjC,OACA,eACyD;AACzD,WAAS,IAAI,GAAG,IAAI,MAAM,MAAM,QAAQ,KAAK;AAC3C,UAAM,OAAO,MAAM,MAAM,CAAC;AAC1B,QAAI,QAAQ,KAAK,OAAO,YAAY;AAClC,aAAO,EAAE,UAAU,MAAM,WAAW,EAAE;AAAA,IACxC;AAAA,EACF;AACA,SAAO;AACT;AAEO,IAAM,0BAA0B,CACrC,OACA,cACkB;AAClB,QAAM,WAAW,CAAC,GAAG,MAAM,KAAK;AAChC,WAAS,SAAS,IAAI;AACtB,SAAO,EAAE,GAAG,OAAO,OAAO,SAAS;AACrC;AAEO,IAAM,mBAAmB,CAC9B,OACA,QACA,eAKU;AACV,QAAM,QAAQ,oBAAoB,OAAO,UAAU;AACnD,MAAI,CAAC,MAAO,QAAO;AAEnB,QAAM,EAAE,UAAU,UAAU,IAAI;AAChC,MAAI,CAAC,UAAU,QAAQ,SAAS,IAAI,EAAG,QAAO;AAE9C,MAAI,gBAAgB,YAAY,QAAQ,SAAS,IAAI;AAGrD,MAAI,SAAS,gBAAgB;AAC3B,YAAQ,SAAS,eAAe,MAAM;AAAA,MACpC,KAAK;AACH,wBAAgB,SAAS,eAAe,SAAS,eAAe,MAAM;AACtE;AAAA,MACF,KAAK;AACH,wBAAgB;AAAA,UACd;AAAA,UACA,SAAS,eAAe;AAAA,QAC1B;AACA;AAAA,MACF,KAAK;AACH,wBAAgB;AAAA,UACd;AAAA,UACA,SAAS,eAAe;AAAA,QAC1B;AACA;AAAA,IACJ;AAAA,EACF;AAGA,MAAI,SAAS,SAAS,GAAG;AACvB,oBAAgB,UAAU,eAAe,SAAS,MAAM;AAAA,EAC1D;AAEA,QAAM,eAAe,wBAAwB,OAAO,SAAS;AAE7D,SAAO,EAAE,cAAc,eAAe,SAAS;AACjD;AA4BO,IAAM,8BAA8B,CACzC,SACA,iBACA,aACY;AACZ,QAAM,OAAO,QAAQ,SAAS,CAAC,IAAI,SAAS,CAAC;AAC7C,MAAI,CAAC,QAAQ,KAAK,SAAS,WAAW,KAAK,SAAS,SAAU,QAAO;AACrE,MAAI,EAAE,2BAA2B,SAAS,CAAC,KAAK;AAC9C,WAAO;AAET,QAAM,WAAW,gBAAgB;AAAA,IAC/B,CAAC,MAAM,EAAE,SAAS,MAAM,SAAS,KAAK,EAAE,SAAS,MAAM,SAAS;AAAA,EAClE;AACA,SAAO,CAAC;AACV;AAEO,IAAM,yBAAyB,CACpC,SACA,UACA,aACY;AAEZ,QAAM,aAAa,QAAQ,IAAI,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC;AAChD,QAAM,OAAO,WAAW,SAAS,CAAC,EAAG,SAAS,CAAC;AAE/C,MAAI,KAAK,SAAS,WAAW,KAAK,SAAS,UAAU;AACnD,eAAW,SAAS,CAAC,EAAG,SAAS,CAAC,IAAI;AAAA,MACpC,GAAG;AAAA,MACH,QAAQ,KAAK,SAAS,SAAS;AAAA,IACjC;AAAA,EACF;AAEA,SAAO;AACT;AAEO,IAAM,oBAAoB,CAC/B,OACA,YACA,WAIU;AACV,QAAM,QAAQ,oBAAoB,OAAO,UAAU;AACnD,MAAI,CAAC,MAAO,QAAO;AAEnB,QAAM,EAAE,UAAU,UAAU,IAAI;AAChC,MAAI,CAAC,UAAU,QAAQ,SAAS,IAAI,EAAG,QAAO;AAE9C,QAAM,gBAAgB,YAAY,QAAQ,SAAS,IAAI;AACvD,QAAM,eAAe,wBAAwB,OAAO,SAAS;AAE7D,SAAO,EAAE,cAAc,cAAc;AACvC;;;AC3MO,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;AAOO,IAAM,4BAA4B,CACvC,MACA,UACc;AACd,MAAI,KAAK,SAAS,KAAK,MAAM,MAAM,YAAY,mBAAmB,KAAK,GAAG;AACxE,WAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,MACA,YAAY,EAAE,MAAM,QAAQ,MAAM,UAAU,OAAO;AAAA,IACrD;AAAA,EACF;AACA,SAAO,EAAE,GAAG,MAAM,OAAO,YAAY,mBAAmB,KAAK,EAAE;AACjE;AAQA,IAAM,8BAA+C;AAAA,EACnD,cAAc;AAAA,EACd,cAAc;AAAA,EACd,cAAc;AAAA,EACd,cAAc;AAChB;AAEO,IAAM,wBAAwB,CACnC,kBACkB;AAClB,QAAM,QAAQ,4BAA4B,QAAQ,aAAa;AAC/D,MAAI,UAAU,MAAM,SAAS,4BAA4B,SAAS,GAAG;AACnE,WAAO,cAAc;AAAA,EACvB;AACA,SAAO,4BAA4B,QAAQ,CAAC;AAC9C;AASA,IAAM,yBAA0C;AAAA,EAC9C,cAAc;AAAA;AAAA,EACd,cAAc;AAAA,EACd,cAAc;AAAA,EACd,cAAc;AAAA,EACd,cAAc;AAChB;AAOO,IAAM,wBAAwB,CACnC,eACA,kBACkB;AAClB,MAAI,CAAC,eAAe;AAElB,WAAO,cAAc;AAAA,EACvB;AAGA,QAAM,WAAW;AAEjB,QAAM,mBACJ,kBAAkB,cAAc,YAC5B,cAAc,aACd;AAEN,QAAM,QAAQ,SAAS,QAAQ,gBAAgB;AAC/C,MAAI,UAAU,MAAM,SAAS,SAAS,SAAS,GAAG;AAChD,WAAO,cAAc;AAAA,EACvB;AACA,SAAO,SAAS,QAAQ,CAAC;AAC3B;AAQA,IAAM,6BAA8C;AAAA,EAClD,cAAc;AAAA,EACd,cAAc;AAChB;AAQA,IAAM,yBAA0C;AAAA,EAC9C,cAAc;AAAA,EACd,cAAc;AAAA,EACd,cAAc;AAChB;AAOO,IAAM,oBAAoB,CAC/B,eACA,YACkB;AAClB,QAAM,WAAW,UACb,yBACA;AACJ,QAAM,QAAQ,SAAS,QAAQ,aAAa;AAC5C,MAAI,UAAU,MAAM,SAAS,SAAS,SAAS,GAAG;AAEhD,WAAO,cAAc;AAAA,EACvB;AACA,SAAO,SAAS,QAAQ,CAAC;AAC3B;;;AC9LO,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;AAEA,QAAM,UAAU,YAAY,KAAK,KAAK,IAAI;AAG1C,QAAM,eAAe,KAAK,MAAM;AAAA,IAAI,CAAC,SACnC,KAAK,OAAO,YAAY,KACpB;AAAA,MACE,GAAG;AAAA,MACH,SAAS;AAAA,MACT,WAAW;AAAA,MACX,cAAc,eAAe;AAAA,IAC/B,IACA;AAAA,EACN;AAEA,QAAM,YAAY,mBAAmB,YAAY;AAEjD,MAAI,WAAW;AAEb,UAAM,QAAQ,kBAAkB,gBAAgB,YAAY,CAAC;AAC7D,UAAM,cAAc,KAAK,OAAO;AAChC,UAAM,eAAe,CAAC,GAAG,KAAK,QAAQ;AACtC,UAAM,aAAa,aAAa,OAAO,GAAG,KAAK,MAAM,MAAM,eAAe;AAC1E,eAAW,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAI7C,UAAM,gBAAgB;AAAA,MACpB;AAAA,MACA,KAAK,MAAM,MAAM,4BAA4B;AAAA,IAC/C;AAEA,UAAM,qBAAqB,cAAc,IAAI,CAAC,QAAQ,WAAW;AAAA,MAC/D;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,UAAU,QAAQ;AAAA,IACpB,EAAE;AAEF,QAAI,SAAS;AAEX,aAAO,GAAG;AAAA,QACR,GAAG;AAAA,QACH,iBAAiB;AAAA,QACjB,UAAU;AAAA,QACV;AAAA,QACA,MAAM;AAAA,QACN,YAAY;AAAA,UACV,MAAM;AAAA,UACN,UAAU,YAAY;AAAA,UACtB,YAAY,cAAc;AAAA,QAC5B;AAAA,MACF,CAAC;AAAA,IACH;AAIA,UAAM,cACJ,KAAK,eAAe,yBAAyB,KAAK,WAAW;AAE/D,UAAMC,QAAO,mBAAmB,KAAK;AACrC,WAAO,GAAG;AAAA,MACR,GAAG;AAAA,MACH,iBAAiB;AAAA,MACjB,UAAU;AAAA,MACV;AAAA,MACA,MAAM;AAAA,MACN,YAAYA;AAAA,MACZ,GAAI,eAAe,EAAE,YAAY;AAAA,IACnC,CAAC;AAAA,EACH;AAEA,MAAI,SAAS;AAEX,WAAO,GAAG;AAAA,MACR,GAAG;AAAA,MACH,iBAAiB;AAAA,MACjB,OAAO;AAAA,MACP,YAAY;AAAA,QACV,MAAM;AAAA,QACN,UAAU,YAAY;AAAA,QACtB,YAAY,cAAc;AAAA,MAC5B;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,OAAO,mBAAmB,YAAY;AAE5C,SAAO,GAAG;AAAA,IACR,GAAG;AAAA,IACH,iBAAiB;AAAA,IACjB,OAAO;AAAA,IACP,YAAY;AAAA,EACd,CAAC;AACH;;;ACxHO,IAAM,sBAAsB,CACjC,MACA,WACgC;AAChC,QAAM,gBAAgB,KAAK;AAE3B,MAAI,cAAc,aAAa,QAAQ;AACrC,WAAO,IAAI,UAAU,aAAa;AAAA,EACpC;AAEA,MAAI,cAAc,eAAe,cAAc,mBAAmB;AAChE,WAAO,IAAI,UAAU,uBAAuB;AAAA,EAC9C;AAEA,MAAI,CAAC,KAAK,aAAa;AACrB,WAAO,IAAI,UAAU,uBAAuB;AAAA,EAC9C;AAEA,QAAM,cAAc,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM;AAC1D,MAAI,CAAC,YAAa,QAAO,IAAI,UAAU,cAAc;AAErD,QAAM,gBAAgB,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,YAAY,QAAQ;AAC5E,MAAI,CAAC,cAAe,QAAO,IAAI,UAAU,gBAAgB;AAEzD,SAAO,GAAG,EAAE,QAAQ,eAAe,aAAa,KAAK,YAAY,CAAC;AACpE;AAEO,IAAM,2BAAqD,CAChE,MACA,QACA,YACA,aACG;AACH,QAAM,UAAU,oBAAoB,MAAM,MAAM;AAChD,MAAI,MAAM,OAAO,GAAG;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,EAAE,QAAQ,eAAe,YAAY,IAAI,QAAQ;AAGvD,MACE,CAAC;AAAA,IACC,cAAc;AAAA,IACd,cAAc,aAAa,CAAC;AAAA,IAC5B;AAAA,EACF,GACA;AACA,WAAO,IAAI,UAAU,sBAAsB;AAAA,EAC7C;AAGA,QAAM,iBAAiB;AAAA,IACrB,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,EACF;AAEA,MAAI,CAAC,gBAAgB;AACnB,WAAO,IAAI,UAAU,sBAAsB;AAAA,EAC7C;AAEA,QAAM,EAAE,cAAc,eAAe,SAAS,IAAI;AAGlD,QAAM,iBAAiB;AAAA,IACrB,cAAc;AAAA,IACd;AAAA,IACA;AAAA,EACF;AAEA,QAAM,iBAAiC,EAAE,UAAU,SAAS;AAC5D,QAAM,cAAc;AAAA,IAClB,GAAG;AAAA,IACH,SAAS;AAAA,IACT,WAAW,CAAC,GAAI,cAAc,aAAa,CAAC,GAAI,cAAc;AAAA,EAChE;AAEA,QAAM,iBAAiB,KAAK,QAAQ;AAAA,IAAI,CAAC,MACvC,EAAE,OAAO,cAAc,KAAK,cAAc;AAAA,EAC5C;AAGA,QAAM,iBAAiB;AAAA,IACrB;AAAA,IACA,YAAY;AAAA,EACd;AAEA,QAAM,aAAa,sBAAsB,cAAc,iBAAiB;AAExE,SAAO,GAAG;AAAA,IACR,GAAG;AAAA,IACH,SAAS;AAAA,IACT,aAAa;AAAA,MACX,GAAG;AAAA,MACH,eAAe;AAAA,MACf,eAAe;AAAA,IACjB;AAAA,IACA,YAAY;AAAA,MACV,MAAM;AAAA,MACN,UAAU;AAAA,MACV;AAAA,IACF;AAAA,EACF,CAAC;AACH;;;AC7HO,IAAM,sBAAsB,OAAsB;AAAA,EACvD,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ;AACV;AAMO,IAAM,gBAAgB,CAC3B,MACA,YAC6D;AAC7D,MAAI,YAAY,KAAK,KAAK,OAAO,GAAG;AAClC,WAAO,GAAG,EAAE,OAAO,GAAG,aAAa,EAAE,GAAG,MAAM,MAAM,KAAK,OAAO,EAAE,EAAE,CAAC;AAAA,EACvE;AACA,MAAI,YAAY,KAAK,KAAK,OAAO,GAAG;AAClC,WAAO,GAAG,EAAE,OAAO,GAAG,aAAa,EAAE,GAAG,MAAM,MAAM,KAAK,OAAO,EAAE,EAAE,CAAC;AAAA,EACvE;AACA,MAAI,YAAY,KAAK,KAAK,SAAS,GAAG;AACpC,WAAO,GAAG,EAAE,OAAO,GAAG,aAAa,EAAE,GAAG,MAAM,QAAQ,KAAK,SAAS,EAAE,EAAE,CAAC;AAAA,EAC3E;AACA,SAAO,IAAI,UAAU,qBAAqB;AAC5C;AAkBA,IAAM,wBAAwB,CAC5B,MACA,OACA,aACe;AACf,MAAI,UAAU,EAAG,QAAO,CAAC,IAAI;AAG7B,MAAI,UAAU,oBAAI,IAAY;AAC9B,UAAQ,IAAI,GAAG,KAAK,CAAC,IAAI,KAAK,CAAC,EAAE;AAEjC,WAAS,OAAO,GAAG,OAAO,OAAO,QAAQ;AACvC,UAAM,OAAO,oBAAI,IAAY;AAC7B,eAAW,OAAO,SAAS;AACzB,YAAM,CAAC,IAAI,EAAE,IAAI,IAAI,MAAM,GAAG,EAAE,IAAI,MAAM;AAC1C,eAAS,KAAK,IAAI,MAAM,GAAG,MAAM;AAC/B,iBAAS,KAAK,IAAI,MAAM,GAAG,MAAM;AAC/B,cAAI,OAAO,KAAK,OAAO,EAAG;AAC1B,gBAAM,KAAK,KAAK;AAChB,gBAAM,KAAK,KAAK;AAChB,cAAI,MAAM,KAAK,KAAK,YAAY,MAAM,KAAK,KAAK,UAAU;AACxD,iBAAK,IAAI,GAAG,EAAE,IAAI,EAAE,EAAE;AAAA,UACxB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,cAAU;AAAA,EACZ;AAEA,SAAO,CAAC,GAAG,OAAO,EAAE,IAAI,CAAC,QAAQ;AAC/B,UAAM,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,GAAG,EAAE,IAAI,MAAM;AACxC,WAAO,EAAE,GAAG,EAAE;AAAA,EAChB,CAAC;AACH;AAaO,IAAM,6BAA6B,CACxC,SACA,iBACA,OACA,uBACe;AACf,QAAM,WAAW,QAAQ;AACzB,QAAM,YAAY,sBAAsB,iBAAiB,OAAO,QAAQ;AAExE,QAAM,qBAAqB,IAAI;AAAA,IAC7B,mBAAmB,IAAI,CAAC,OAAO,GAAG,GAAG,SAAS,CAAC,IAAI,GAAG,SAAS,CAAC,EAAE;AAAA,EACpE;AAEA,SAAO,UAAU,OAAO,CAAC,QAAQ;AAC/B,UAAM,OAAO,QAAQ,IAAI,CAAC,IAAI,IAAI,CAAC;AACnC,QAAI,CAAC,KAAM,QAAO;AAClB,QAAI,KAAK,SAAS,QAAS,QAAO;AAClC,QAAI,KAAK,SAAS,UAAW,QAAO;AACpC,QAAI,KAAK,SAAS,SAAU,QAAO;AACnC,QAAI,KAAK,SAAS,EAAG,QAAO;AAC5B,QAAI,mBAAmB,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,EAAE,EAAG,QAAO;AACxD,WAAO;AAAA,EACT,CAAC;AACH;AAKO,IAAM,2BAA2B,CACtC,SACA,UACA,iBACA,OACA,uBACY;AACZ,QAAM,iBAAiB;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,SAAO,eAAe,KAAK,CAAC,MAAM,EAAE,MAAM,SAAS,KAAK,EAAE,MAAM,SAAS,CAAC;AAC5E;;;AC1IA,IAAM,qBAAqB;AAKpB,IAAM,kBAAkB,MAAc;AAMtC,IAAM,oBAAoB,CAAC,SAAiC;AACjE,MAAI,QAAQ,GAAG;AACb,WAAO,IAAI,UAAU,gBAAgB;AAAA,EACvC;AACA,SAAO,GAAG,OAAO,CAAC;AACpB;AAKO,IAAM,sBAAsB,CAAC,YAAiC;AACnE,QAAM,SAAqB,CAAC;AAC5B,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,MAAM,QAAQ,CAAC;AACrB,aAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,YAAM,OAAO,IAAI,CAAC;AAClB,UAAI,KAAK,SAAS,WAAW,KAAK,SAAS,YAAY,KAAK,SAAS,GAAG;AACtE,eAAO,KAAK,EAAE,GAAG,EAAE,CAAC;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAKO,IAAM,+BAA+B,CAC1C,SACA,WACe;AACf,QAAM,YAAY,oBAAoB,OAAO;AAC7C,SAAO,UAAU;AAAA,IACf,CAAC,UACC,CAAC,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,MAAM,KAAK,EAAE,SAAS,MAAM,MAAM,CAAC;AAAA,EAC5E;AACF;AAKO,IAAM,iBAAiB,CAAC,YAC5B,OAAO,QAAQ,UAAU,KAAK;AAM1B,IAAM,oBAAoB,CAC/B,QACA,aACmB;AACnB,QAAM,UAAU,OAAO;AACvB,QAAM,OAAO,QAAQ,SAAS,CAAC,IAAI,SAAS,CAAC;AAE7C,MAAI,CAAC,QAAQ,KAAK,SAAS,WAAW,KAAK,SAAS,UAAU;AAC5D,WAAO,IAAI,UAAU,uBAAuB;AAAA,EAC9C;AAEA,MAAI,KAAK,UAAU,GAAG;AACpB,WAAO,IAAI,UAAU,uBAAuB;AAAA,EAC9C;AAEA,QAAM,SAAS,OAAO,UAAU,CAAC;AAGjC,QAAM,iBAAiB,OAAO;AAAA,IAC5B,CAAC,MAAM,EAAE,SAAS,MAAM,SAAS,KAAK,EAAE,SAAS,MAAM,SAAS;AAAA,EAClE;AACA,MAAI,gBAAgB;AAClB,WAAO,IAAI,UAAU,uBAAuB;AAAA,EAC9C;AAEA,QAAM,WAAwB,EAAE,SAAS;AACzC,SAAO,GAAG;AAAA,IACR,GAAG;AAAA,IACH,QAAQ,CAAC,GAAG,QAAQ,QAAQ;AAAA,EAC9B,CAAC;AACH;AAKO,IAAM,kBAAkB,CAAC,QAAgB,eAC9C,cAAc,KAAK,cAAc,OAAO,UAAU,CAAC,GAAG;AAKjD,IAAM,wBAAwB,CACnC,QACA,eACmB;AACnB,QAAM,SAAS,OAAO,UAAU,CAAC;AACjC,MAAI,CAAC,gBAAgB,QAAQ,UAAU,GAAG;AACxC,WAAO,IAAI,UAAU,eAAe;AAAA,EACtC;AACA,SAAO,GAAG,EAAE,GAAG,QAAQ,QAAQ,OAAO,OAAO,CAAC,GAAG,MAAM,MAAM,UAAU,EAAE,CAAC;AAC5E;AAMO,IAAM,sBAAsB,CACjC,cACA,cACA,YACA,wBAC+C;AAC/C,QAAM,eAAe,aAAa,UAAU,CAAC;AAE7C,MAAI,CAAC,gBAAgB,cAAc,UAAU,GAAG;AAC9C,WAAO,IAAI,UAAU,eAAe;AAAA,EACtC;AAGA,QAAM,aACJ,aAAa,QAAQ,oBAAoB,CAAC,IAAI,oBAAoB,CAAC;AACrE,MACE,CAAC,cACD,WAAW,SAAS,WACpB,WAAW,SAAS,YACpB,WAAW,UAAU,GACrB;AACA,WAAO,IAAI,UAAU,uBAAuB;AAAA,EAC9C;AAGA,QAAM,eAAe,aAAa,UAAU,CAAC;AAC7C,QAAM,iBAAiB,aAAa;AAAA,IAClC,CAAC,MACC,EAAE,SAAS,MAAM,oBAAoB,KACrC,EAAE,SAAS,MAAM,oBAAoB;AAAA,EACzC;AACA,MAAI,gBAAgB;AAClB,WAAO,IAAI,UAAU,uBAAuB;AAAA,EAC9C;AAGA,QAAM,sBAAsB,aAAa,OAAO,CAAC,GAAG,MAAM,MAAM,UAAU;AAG1E,QAAM,WAAwB,EAAE,UAAU,oBAAoB;AAE9D,SAAO,GAAG;AAAA,IACR,QAAQ,EAAE,GAAG,cAAc,QAAQ,oBAAoB;AAAA,IACvD,QAAQ,EAAE,GAAG,cAAc,QAAQ,CAAC,GAAG,cAAc,QAAQ,EAAE;AAAA,EACjE,CAAC;AACH;;;AC/IO,IAAM,SAAS,CAAC,YAQC;AACtB,QAAM,EAAE,IAAI,MAAM,UAAU,MAAM,WAAW,SAAS,WAAW,IAAI;AAErE,MAAI;AACJ,OACG,KAAK,SAAS,iBAAiB,KAAK,SAAS,8BAC9C,WACA;AACA,kBAAc;AAAA,MACZ,eAAe;AAAA,QACb,OAAO,CAAC;AAAA,QACR,UAAU;AAAA,MACZ;AAAA,MACA,eAAe;AAAA,MACf,iBAAiB;AAAA,MACjB,qBAAqB;AAAA,IACvB;AAAA,EACF;AAEA,MAAI;AACJ,MAAI,cAAc,KAAK,IAAI,GAAG;AAC5B,UAAM,UAAU,kBAAkB,KAAK,IAAI;AAC3C,cAAU;AAAA,MACR;AAAA,MACA,eAAe,oBAAoB;AAAA,MACnC,GAAI,YAAY,KAAK,IAAI,KAAK;AAAA,QAC5B,QAAQ;AAAA,UACN,SAAS;AAAA,UACT,MAAM;AAAA,UACN,UAAU;AAAA,UACV,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,GAAI,YAAY,KAAK,IAAI,KACvB,WAAW;AAAA,QACT,WAAW;AAAA,UACT,SAAS,CAAC;AAAA,UACV,UAAU;AAAA,QACZ;AAAA,MACF;AAAA,IACJ;AAAA,EACF;AAEA,MAAI;AACJ,MAAI,kBAAkB,KAAK,IAAI,KAAK,YAAY;AAC9C,kBAAc;AAAA,MACZ,WAAW,gBAAgB;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAEA,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,IACjC,GAAI,gBAAgB,UAAa,EAAE,YAAY;AAAA,IAC/C,GAAI,YAAY,UAAa,EAAE,QAAQ;AAAA,IACvC,GAAI,gBAAgB,UAAa,EAAE,YAAY;AAAA,EACjD;AACF;;;ACzGA,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;;;ACMO,IAAM,oBACX,CAAC,SASD,CAAC,MAAM,SAAS;AACd,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,YAAAC;AAAA,IACA,eAAAC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,QAAM,KAAKD,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,gBACJ,QAAQ,MAAM,SAAS,iBACvB,6BAA6B,QAAQ,MAAM,IAAI;AACjD,MAAI;AAEJ,MAAI,iBAAiB,qBAAqB;AACxC,gBAAY,oBAAoB,OAAO;AAAA,EACzC;AAEA,MAAI;AACJ,MAAI,YAAY,QAAQ,MAAM,IAAI,KAAK,mBAAmB;AACxD,cAAU,kBAAkB,OAAO;AAAA,EACrC;AAEA,MAAI;AACJ,MAAI,kBAAkB,QAAQ,MAAM,IAAI,KAAK,sBAAsB;AACjE,UAAM,YAAY,qBAAqB,OAAO;AAE9C,UAAM,eAAe,WACjB,oBAAoB,UAAU,QAAQ,IACtCC;AACJ,UAAM,iBAAiB,aAAa,SAAS;AAC7C,iBAAa,eAAe,MAAM,GAAG,CAAC;AAAA,EACxC;AAEA,QAAM,UAAU;AAAA,IACd;AAAA,IACA,MAAM,QAAQ;AAAA,IACd;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,UAAU,OAAO,OAAO;AAE9B,SAAO,GAAG,OAAO;AACnB;;;ACnEK,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;AAAA,UACb;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,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;AAAA,UACb;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,YAAI,KAAK,MAAM,GAAG;AAChB,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;AC/EO,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,QACE,iBACA;AAAA,MACE,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,KAAK,MAAM,MAAM;AAAA,IACnB,GACA;AACA,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;AAKD,MAAI,KAAK,aAAa;AACpB,WAAO,GAAG;AAAA,MACR,GAAG;AAAA,MACH,OAAO;AAAA,MACP,aAAa,EAAE,GAAG,KAAK,aAAa,qBAAqB,CAAC,EAAE;AAAA,MAC5D,YAAY;AAAA,QACV,MAAM;AAAA,QACN,UAAU,YAAY;AAAA,QACtB,YAAY,cAAc;AAAA,MAC5B;AAAA,IACF,CAAC;AAAA,EACH;AAEA,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;;;ACnGO,IAAM,0BAAmD,CAC9D,OACA,UAAU,eACP;AAEH,QAAM,YAAY,oBAAI,IAGpB;AAEF,aAAW,QAAQ,OAAO;AACxB,eAAW,UAAU,KAAK,QAAQ;AAChC,YAAM,MACJ,YAAY,eAAe,OAAO,aAAa,OAAO;AACxD,YAAM,WAAW,UAAU,IAAI,GAAG;AAClC,UAAI,UAAU;AACZ,iBAAS,OAAO,KAAK,OAAO,QAAQ,MAAM;AAAA,MAC5C,OAAO;AACL,kBAAU,IAAI,KAAK;AAAA,UACjB,UAAU,OAAO;AAAA,UACjB,MAAM,OAAO;AAAA,UACb,QAAQ,CAAC,OAAO,QAAQ,MAAM;AAAA,QAChC,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAGA,QAAM,UAA6C,CAAC;AACpD,aAAW,QAAQ,UAAU,OAAO,GAAG;AACrC,YAAQ,KAAK;AAAA,MACX,UAAU,KAAK;AAAA,MACf,YAAY,KAAK;AAAA,MACjB,aAAa,KAAK,OAAO,OAAO,CAACC,MAAK,MAAMA,OAAM,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;;;AC7DO,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,mBAAmB,CAAC,gBAA8C;AAC7E,QAAM,SAAS,CAAC,GAAG,WAAW,EAAE,KAAK,CAAC,GAAG,MAAM;AAC7C,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;AAC/B,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,SAAO,KAAK,EAAE,GAAG,OAAO,CAAC,GAAI,UAAU,EAAE,CAAC;AAE1C,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAM,eAAe,OAAO,CAAC;AAC7B,UAAM,gBAAgB,OAAO,IAAI,CAAC;AAClC,UAAM,QACJ,aAAa,QAAQ,WAAW,cAAc,QAAQ,UACtD,aAAa,QAAQ,sBACnB,cAAc,QAAQ;AAE1B,WAAO,KAAK;AAAA,MACV,GAAG;AAAA,MACH,UAAU,QAAQ,OAAO,IAAI,CAAC,EAAG,WAAW,IAAI;AAAA,IAClD,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAMO,IAAM,mBAAqC,CAAC,SAAS;AAC1D,QAAM,cAAc,KAAK,QAAQ,IAAI,CAAC,WAAwB;AAC5D,UAAM,QAAQ,mBAAmB,MAAM,QAAQ,IAAI;AACnD,WAAO;AAAA,MACL,UAAU,MAAM;AAAA,MAChB,YAAY,MAAM;AAAA,MAClB,SAAS;AAAA,QACP,QAAQ,MAAM;AAAA,QACd,mBAAmB,MAAM;AAAA,QACzB,aAAa,MAAM;AAAA,MACrB;AAAA,MACA,WAAW,MAAM;AAAA,IACnB;AAAA,EACF,CAAC;AAED,SAAO,GAAG;AAAA,IACR,GAAG;AAAA,IACH,QAAQ,iBAAiB,WAAW;AAAA,EACtC,CAAC;AACH;;;AC9DO,IAAM,sCAAsC,CACjD,SACA,aACW;AACX,QAAM,OAAO,QAAQ;AACrB,QAAM,OAAO,QAAQ,CAAC,GAAG,UAAU;AACnC,QAAM,YAAY,QAAQ,SAAS,CAAC,IAAI,SAAS,CAAC;AAElD,MAAI,CAAC,aAAa,UAAU,SAAS,WAAW,UAAU,SAAS,UAAU;AAC3E,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,UAAU;AAC9B,QAAM,UAAuB,QAAQ,IAAI,CAAC,QAAQ,IAAI,IAAI,MAAM,KAAK,CAAC;AACtE,QAAM,QAA4B,CAAC,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;AAC3D,UAAQ,SAAS,CAAC,EAAG,SAAS,CAAC,IAAI;AACnC,MAAI,QAAQ;AAEZ,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,SAAO,MAAM,SAAS,GAAG;AACvB,UAAM,CAAC,IAAI,EAAE,IAAI,MAAM,IAAI;AAC3B,UAAM,OAAO,QAAQ,EAAE,EAAG,EAAE;AAE5B,QACE,KAAK,SAAS,WACd,KAAK,SAAS,YACd,2BAA2B,QAC3B,KAAK,uBACL;AACA;AAAA,IACF;AAEA,eAAW,CAAC,IAAI,EAAE,KAAK,YAAY;AACjC,YAAM,KAAK,KAAM;AACjB,YAAM,KAAK,KAAM;AACjB,UACE,MAAM,KACN,MAAM,KACN,KAAK,QACL,KAAK,QACL,CAAC,QAAQ,EAAE,EAAG,EAAE,KAChB,QAAQ,EAAE,EAAG,EAAE,EAAG,SAAS,aAC3B;AACA,gBAAQ,EAAE,EAAG,EAAE,IAAI;AACnB,cAAM,KAAK,CAAC,IAAI,EAAE,CAAC;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKA,IAAM,sBAAsB,CAC1B,SACA,aACkB;AAClB,QAAM,OAAO,QAAQ,SAAS,CAAC,IAAI,SAAS,CAAC;AAC7C,MAAI,CAAC,QAAQ,KAAK,SAAS,WAAW,KAAK,SAAS,SAAU,QAAO;AACrE,SAAO,KAAK;AACd;AAKA,IAAM,qBAAqB,CACzB,SACA,UACA,YACY;AACZ,QAAM,UAAU,oBAAoB,SAAS,QAAQ;AACrD,MAAI,CAAC,QAAS,QAAO;AAGrB,QAAM,OAAO,QAAQ;AACrB,QAAM,OAAO,QAAQ,CAAC,GAAG,UAAU;AACnC,QAAM,UAAuB,QAAQ,IAAI,CAAC,QAAQ,IAAI,IAAI,MAAM,KAAK,CAAC;AACtE,QAAM,QAA4B,CAAC,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;AAC3D,UAAQ,SAAS,CAAC,EAAG,SAAS,CAAC,IAAI;AACnC,QAAM,qBAAqB,oBAAI,IAAY;AAE3C,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,SAAO,MAAM,SAAS,GAAG;AACvB,UAAM,CAAC,IAAI,EAAE,IAAI,MAAM,IAAI;AAC3B,uBAAmB,IAAI,GAAG,EAAE,IAAI,EAAE,EAAE;AAEpC,eAAW,CAAC,IAAI,EAAE,KAAK,YAAY;AACjC,YAAM,KAAK,KAAM;AACjB,YAAM,KAAK,KAAM;AACjB,UACE,MAAM,KACN,MAAM,KACN,KAAK,QACL,KAAK,QACL,CAAC,QAAQ,EAAE,EAAG,EAAE,KAChB,QAAQ,EAAE,EAAG,EAAE,EAAG,SAAS,SAC3B;AACA,gBAAQ,EAAE,EAAG,EAAE,IAAI;AACnB,cAAM,KAAK,CAAC,IAAI,EAAE,CAAC;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AAEA,SAAO,QAAQ;AAAA,IAAK,CAAC,MACnB,mBAAmB,IAAI,GAAG,EAAE,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE;AAAA,EAC1D;AACF;AASO,IAAM,iBAAiB,CAC5B,QACA,SACA,UACA,qBACY;AACZ,QAAM,UAAU,OAAO,WAAW,CAAC;AACnC,MAAI,QAAQ,UAAU,cAAc,MAAM,EAAG,QAAO;AAEpD,MACE,qBAAqB,UACrB,CAAC,iBAAiB,KAAK,CAAC,MAAM,EAAE,MAAM,SAAS,KAAK,EAAE,MAAM,SAAS,CAAC,GACtE;AACA,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,QAAQ,SAAS,CAAC,IAAI,SAAS,CAAC;AAC7C,MAAI,CAAC,QAAQ,KAAK,SAAS,WAAW,KAAK,SAAS,SAAU,QAAO;AAErE,MAAI,mBAAmB,SAAS,UAAU,OAAO,EAAG,QAAO;AAE3D,SAAO;AACT;AAEO,IAAM,cAAc,CACzB,QACA,SACA,aACW;AACX,QAAM,SAAiB,EAAE,UAAU,OAAO,IAAI,SAAS;AACvD,QAAM,UAAU,CAAC,GAAI,OAAO,WAAW,CAAC,GAAI,MAAM;AAClD,QAAM,YAAY,oCAAoC,SAAS,QAAQ;AACvE,QAAM,gBAAgB,SAAS,EAAE,GAAG,QAAQ,QAAQ,GAAG,SAAS;AAEhE,SAAO;AACT;;;AC1IO,IAAM,4BAA4B,CACvC,MACA,WACsC;AACtC,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,KAAK,SAAS,kBAAkB;AACnC,WAAO,IAAI,UAAU,qBAAqB;AAAA,EAC5C;AAEA,QAAM,UAAU,KAAK,QAAQ;AAE7B,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,SAAO,GAAG;AAAA,IACR,QAAQ;AAAA,IACR;AAAA,IACA,gBAAgB,cAAc,cAAc,CAAC;AAAA,EAC/C,CAAC;AACH;AAEO,IAAM,wBAA+C,CAC1D,MACA,QACA,aACG;AACH,QAAM,UAAU,0BAA0B,MAAM,MAAM;AACtD,MAAI,MAAM,OAAO,GAAG;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,EAAE,QAAQ,eAAe,SAAS,eAAe,IAAI,QAAQ;AACnE,QAAM,EAAE,OAAO,gBAAgB,IAAI;AAEnC,MACE,CAAC;AAAA,IACC,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GACA;AACA,WAAO,IAAI,UAAU,2BAA2B;AAAA,EAClD;AAGA,QAAM,WAA4B,EAAE,OAAO,SAAS;AACpD,QAAM,oBAAoB,CAAC,GAAG,gBAAgB,QAAQ;AAGtD,MAAI,mBAAmB,cAAc;AACrC,MAAI,kBAAkB;AACpB,uBAAmB,iBAAiB;AAAA,MAClC,CAAC,MAAM,EAAE,EAAE,SAAS,MAAM,SAAS,KAAK,EAAE,SAAS,MAAM,SAAS;AAAA,IACpE;AAAA,EACF;AAGA,MAAI,iBAAiB,cAAc;AACnC,MAAI,gBAAgB;AAClB,qBAAiB,eAAe;AAAA,MAC9B,CAAC,MAAM,EAAE,EAAE,SAAS,MAAM,SAAS,KAAK,EAAE,SAAS,MAAM,SAAS;AAAA,IACpE;AAAA,EACF;AAEA,QAAM,iBAAiB,KAAK,QAAQ,IAAI,CAAC,WAAW;AAClD,QAAI,OAAO,OAAO,cAAc,IAAI;AAClC,aAAO;AAAA,QACL,GAAG;AAAA,QACH,YAAY;AAAA,QACZ,GAAI,qBAAqB,UAAa,EAAE,WAAW,iBAAiB;AAAA,QACpE,GAAI,mBAAmB,UAAa,EAAE,SAAS,eAAe;AAAA,MAChE;AAAA,IACF;AACA,WAAO;AAAA,EACT,CAAC;AAID,QAAM,iBAAiB;AAAA,IACrB,KAAK,WAAW,EAAE,GAAG,KAAK,SAAS,kBAAkB,OAAU;AAAA,IAC/D;AAAA,EACF;AAIA,QAAM,iBAA4B;AAAA,IAChC;AAAA,MACE,GAAG;AAAA,MACH,SAAS;AAAA,MACT,GAAI,mBAAmB,UAAa,EAAE,SAAS,eAAe;AAAA,IAChE;AAAA,IACA,KAAK;AAAA,EACP;AAEA,SAAO,GAAG,cAAc;AAC1B;;;ACpHO,IAAM,yBAAyB,CACpC,MACA,iBACoB;AACpB,QAAM,UAAU,6BAA6B,KAAK,KAAK,IAAI;AAC3D,QAAM,aAAa,sBAAsB,cAAc,WAAW,OAAO;AAEzE,MAAI,eAAe,cAAc,YAAY;AAC3C,WAAO,GAAG,0BAA0B,MAAM,KAAK,KAAK,CAAC;AAAA,EACvD;AAEA,SAAO,GAAG;AAAA,IACR,GAAG;AAAA,IACH,YAAY;AAAA,MACV,MAAM;AAAA,MACN,UAAU;AAAA,MACV;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAMO,IAAM,qBAAqB,CAChC,MACA,WACmB;AACnB,QAAM,gBAAgB,KAAK;AAE3B,MAAI,cAAc,eAAe,cAAc,WAAW;AACxD,WAAO,IAAI,UAAU,uBAAuB;AAAA,EAC9C;AAEA,MAAI,cAAc,aAAa,QAAQ;AACrC,WAAO,IAAI,UAAU,aAAa;AAAA,EACpC;AAEA,MAAI,CAAC,KAAK,aAAa;AACrB,WAAO,IAAI,UAAU,YAAY;AAAA,EACnC;AAEA,QAAM,cAAc,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM;AAC1D,MAAI,CAAC,aAAa;AAChB,WAAO,IAAI,UAAU,cAAc;AAAA,EACrC;AAEA,QAAM,eAAe,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,YAAY,QAAQ;AAC3E,MAAI,CAAC,cAAc;AACjB,WAAO,IAAI,UAAU,gBAAgB;AAAA,EACvC;AAEA,SAAO,GAAG,YAAY;AACxB;AAeO,IAAM,qBAAqB,CAChC,MACA,cACA,mBACwB;AACxB,QAAM,eAAe,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,cAAc;AACrE,MAAI,CAAC,cAAc;AACjB,WAAO,IAAI,UAAU,gBAAgB;AAAA,EACvC;AAEA,MAAI,aAAa,OAAO,aAAa,IAAI;AACvC,WAAO,IAAI,UAAU,uBAAuB;AAAA,EAC9C;AAEA,QAAM,aAAa;AAAA,IACjB,aAAa;AAAA,IACb,aAAa,UAAU,CAAC;AAAA,EAC1B;AACA,MAAI,WAAW,WAAW,GAAG;AAC3B,WAAO,IAAI,UAAU,uBAAuB;AAAA,EAC9C;AAEA,SAAO,GAAG,EAAE,cAAc,WAAW,CAAC;AACxC;AAEO,IAAM,mBAAqC,CAChD,MACA,QACA,YACA,gBACA,wBACG;AACH,QAAM,SAAS,mBAAmB,MAAM,MAAM;AAC9C,MAAI,MAAM,MAAM,GAAG;AACjB,WAAO;AAAA,EACT;AACA,QAAM,eAAe,OAAO;AAE5B,QAAM,SAAS,mBAAmB,MAAM,cAAc,cAAc;AACpE,MAAI,MAAM,MAAM,GAAG;AACjB,WAAO;AAAA,EACT;AACA,QAAM,EAAE,cAAc,WAAW,IAAI,OAAO;AAM5C,QAAM,QACJ,wBAAwB,WAAW,WAAW,IAAI,WAAW,CAAC,IAAI;AAEpE,MAAI,CAAC,OAAO;AACV,UAAM,UAAU,sBAAsB,cAAc,UAAU;AAC9D,QAAI,MAAM,OAAO,GAAG;AAClB,aAAO;AAAA,IACT;AAEA,UAAM,aAAa,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,aAAa,aAAa,EAAE;AACxE,QAAI,CAAC,YAAY;AACf,aAAO,IAAI,UAAU,cAAc;AAAA,IACrC;AAEA,WAAO,GAAG;AAAA,MACR,GAAG;AAAA,MACH,SAAS,KAAK,QAAQ;AAAA,QAAI,CAAC,MACzB,EAAE,OAAO,aAAa,KAAK,QAAQ,QAAQ;AAAA,MAC7C;AAAA,MACA,aAAa,KAAK,eAAe;AAAA,QAC/B,GAAG,KAAK;AAAA,QACR,cAAc,EAAE,YAAY,QAAQ,gBAAgB,aAAa,GAAG;AAAA,MACtE;AAAA,MACA,YAAY;AAAA,QACV,MAAM;AAAA,QACN,UAAU,WAAW;AAAA,QACrB,YAAY,cAAc;AAAA,MAC5B;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,SAAS;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI,MAAM,MAAM,GAAG;AACjB,WAAO;AAAA,EACT;AAEA,QAAM,iBAAiB,KAAK,QAAQ,IAAI,CAAC,MAAM;AAC7C,QAAI,EAAE,OAAO,OAAO,MAAM,OAAO,GAAI,QAAO,OAAO,MAAM;AACzD,QAAI,EAAE,OAAO,OAAO,MAAM,OAAO,GAAI,QAAO,OAAO,MAAM;AACzD,WAAO;AAAA,EACT,CAAC;AAED,SAAO,uBAAuB,EAAE,GAAG,MAAM,SAAS,eAAe,GAAG,MAAM;AAC5E;;;ACnJO,IAAM,wBAAwB,CACnC,MACA,WACkC;AAClC,QAAM,gBAAgB,KAAK;AAE3B,MAAI,cAAc,eAAe,cAAc,YAAY;AACzD,WAAO,IAAI,UAAU,uBAAuB;AAAA,EAC9C;AAEA,MAAI,cAAc,aAAa,QAAQ;AACrC,WAAO,IAAI,UAAU,aAAa;AAAA,EACpC;AAEA,MAAI,CAAC,KAAK,aAAa;AACrB,WAAO,IAAI,UAAU,YAAY;AAAA,EACnC;AAIA,QAAM,eAAe,KAAK,YAAY;AACtC,MAAI,cAAc;AAChB,UAAM,OAAO,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM;AACnD,QAAI,CAAC,QAAQ,KAAK,aAAa,aAAa,gBAAgB;AAC1D,aAAO,IAAI,UAAU,aAAa;AAAA,IACpC;AACA,UAAM,SAAS,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK,QAAQ;AAC9D,QAAI,CAAC,QAAQ;AACX,aAAO,IAAI,UAAU,gBAAgB;AAAA,IACvC;AACA,UAAM,EAAE,cAAc,WAAW,GAAG,mBAAmB,IAAI,KAAK;AAChE,WAAO,GAAG,EAAE,QAAQ,QAAQ,cAAc,mBAAmB,CAAC;AAAA,EAChE;AAGA,QAAM,aAAa,kBAAkB,KAAK,YAAY,SAAS;AAC/D,MAAI,MAAM,UAAU,GAAG;AACrB,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM;AAC1D,MAAI,CAAC,aAAa;AAChB,WAAO,IAAI,UAAU,cAAc;AAAA,EACrC;AAEA,QAAM,gBAAgB,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,YAAY,QAAQ;AAC5E,MAAI,CAAC,eAAe;AAClB,WAAO,IAAI,UAAU,gBAAgB;AAAA,EACvC;AAEA,SAAO,GAAG;AAAA,IACR,QAAQ;AAAA,IACR,oBAAoB,EAAE,GAAG,KAAK,aAAa,WAAW,WAAW,MAAM;AAAA,EACzE,CAAC;AACH;AAEO,IAAM,oBAAuC,CAClD,MACA,QACA,aACG;AACH,QAAM,UAAU,sBAAsB,MAAM,MAAM;AAClD,MAAI,MAAM,OAAO,GAAG;AAClB,WAAO;AAAA,EACT;AAEA,QAAM;AAAA,IACJ,QAAQ;AAAA,IACR;AAAA,IACA,oBAAoB;AAAA,EACtB,IAAI,QAAQ;AAGZ,QAAM,cAAc,kBAAkB,eAAe,QAAQ;AAC7D,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO;AAAA,EACT;AAIA,MAAI,cAAc;AAChB,WAAO;AAAA,MACL;AAAA,QACE,GAAG;AAAA,QACH,SAAS,KAAK,QAAQ;AAAA,UAAI,CAAC,MACzB,EAAE,OAAO,cAAc,KAAK,YAAY,QAAQ;AAAA,QAClD;AAAA,QACA,aAAa;AAAA,MACf;AAAA,MACA,aAAa;AAAA,IACf;AAAA,EACF;AAEA,QAAM,iBAAiB,KAAK,QAAQ;AAAA,IAAI,CAAC,MACvC,EAAE,OAAO,cAAc,KAAK,YAAY,QAAQ;AAAA,EAClD;AAGA,QAAM,UAAU,6BAA6B,KAAK,KAAK,IAAI;AAC3D,QAAM,aAAa,sBAAsB,cAAc,YAAY,OAAO;AAE1E,MAAI,eAAe,cAAc,YAAY;AAE3C,UAAM,aAAa,KAAK,SAAS,KAAK,MAAM,MAAM;AAClD,QAAI,cAAc,mBAAmB,KAAK,KAAK,GAAG;AAChD,aAAO,GAAG;AAAA,QACR,GAAG;AAAA,QACH,SAAS;AAAA,QACT,aAAa;AAAA,QACb,YAAY,EAAE,MAAM,QAAQ,MAAM,UAAU,OAAO;AAAA,MACrD,CAAC;AAAA,IACH;AACA,WAAO,GAAG;AAAA,MACR,GAAG;AAAA,MACH,SAAS;AAAA,MACT,aAAa;AAAA,MACb,YAAY,mBAAmB,KAAK,KAAK;AAAA,IAC3C,CAAC;AAAA,EACH;AAGA,SAAO,GAAG;AAAA,IACR,GAAG;AAAA,IACH,SAAS;AAAA,IACT,aAAa;AAAA,IACb,YAAY;AAAA,MACV,MAAM;AAAA,MACN,UAAU;AAAA,MACV;AAAA,IACF;AAAA,EACF,CAAC;AACH;;;ACzJO,IAAM,yBAAyB,CACpC,MACA,WACmC;AACnC,QAAM,gBAAgB,KAAK;AAE3B,MAAI,cAAc,aAAa,QAAQ;AACrC,WAAO,IAAI,UAAU,aAAa;AAAA,EACpC;AAEA,MAAI,cAAc,eAAe,cAAc,aAAa;AAC1D,WAAO,IAAI,UAAU,uBAAuB;AAAA,EAC9C;AAEA,QAAM,cAAc,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM;AAC1D,MAAI,CAAC,YAAa,QAAO,IAAI,UAAU,cAAc;AAErD,QAAM,gBAAgB,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,YAAY,QAAQ;AAC5E,MAAI,CAAC,cAAe,QAAO,IAAI,UAAU,gBAAgB;AAGzD,QAAM,mBAAmB,KAAK,aAAa,uBAAuB,CAAC;AAEnE,SAAO,GAAG,EAAE,QAAQ,eAAe,iBAAiB,CAAC;AACvD;AAEO,IAAM,qBAAyC,CACpD,MACA,QACA,aACG;AACH,QAAM,UAAU,uBAAuB,MAAM,MAAM;AACnD,MAAI,MAAM,OAAO,GAAG;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,EAAE,QAAQ,eAAe,iBAAiB,IAAI,QAAQ;AAE5D,MACE,CAAC;AAAA,IACC;AAAA,IACA,cAAc;AAAA,IACd;AAAA,IACA;AAAA,EACF,GACA;AACA,WAAO,IAAI,UAAU,mBAAmB;AAAA,EAC1C;AAEA,QAAM,gBAAgB;AAAA,IACpB;AAAA,IACA,cAAc;AAAA,IACd;AAAA,EACF;AAEA,QAAM,iBAAiB,KAAK,QAAQ;AAAA,IAAI,CAAC,MACvC,EAAE,OAAO,cAAc,KAAK,gBAAgB;AAAA,EAC9C;AAEA,QAAM,aAAa,sBAAsB,cAAc,WAAW;AAElE,SAAO,GAAG;AAAA,IACR,GAAG;AAAA,IACH,SAAS;AAAA,IACT,YAAY;AAAA,MACV,MAAM;AAAA,MACN,UAAU;AAAA,MACV;AAAA,IACF;AAAA,EACF,CAAC;AACH;;;AC/CO,IAAM,qBAAqB,CAChC,MACA,WAC+B;AAC/B,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,KAAK,SAAS,WAAW;AAC5B,WAAO,IAAI,UAAU,cAAc;AAAA,EACrC;AAEA,QAAM,gBAAgB,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,YAAY,QAAQ;AAE5E,MAAI,CAAC,eAAe;AAClB,WAAO,IAAI,UAAU,gBAAgB;AAAA,EACvC;AAEA,SAAO,GAAG;AAAA,IACR,QAAQ;AAAA,IACR,SAAS,KAAK;AAAA,IACd,WAAW,KAAK,QAAQ;AAAA,IACxB,WAAW,cAAc,aAAa,CAAC;AAAA,IACvC,YAAY,cAAc,cAAc,CAAC;AAAA,IACzC,SAAS,cAAc,WAAW,CAAC;AAAA,EACrC,CAAC;AACH;AAEO,IAAM,wBAA+C,CAC1D,MACA,QACA,WACA,UACA,sBACG;AACH,QAAM,UAAU,mBAAmB,MAAM,MAAM;AAC/C,MAAI,MAAM,OAAO,GAAG;AAClB,WAAO;AAAA,EACT;AAEA,QAAM;AAAA,IACJ,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,QAAQ;AAIZ,QAAM,OAAO,mBAAmB,WAAW,SAAS;AAEpD,MAAI,CAAC,MAAM;AACT,WAAO,IAAI,UAAU,iBAAiB;AAAA,EACxC;AAEA,MACE,CAAC;AAAA,IACC;AAAA,IACA;AAAA,IACA,KAAK;AAAA,IACL,KAAK;AAAA,EACP,GACA;AACA,WAAO,IAAI,UAAU,sBAAsB;AAAA,EAC7C;AAGA,MACE,CAAC;AAAA,IACC,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GACA;AACA,WAAO,IAAI,UAAU,yBAAyB;AAAA,EAChD;AAGA,QAAM,gBACJ,KAAK,WAAW,YACZ,uBAAuB,WAAW,SAAS,IAC3C,wBAAwB,WAAW,SAAS;AAElD,MAAI,CAAC,eAAe;AAClB,WAAO,IAAI,UAAU,iBAAiB;AAAA,EACxC;AAGA,QAAM,mBAAmB,eAAe,WAAW,iBAAiB;AAGpE,QAAM,iBAAiB;AAAA,IACrB,GAAG;AAAA,IACH,EAAE,SAAS,cAAc,SAAS,SAAS;AAAA,EAC7C;AAEA,QAAM,iBAAiB,KAAK,QAAQ,IAAI,CAAC,WAAW;AAClD,QAAI,OAAO,OAAO,cAAc,IAAI;AAClC,aAAO;AAAA,QACL,GAAG;AAAA,QACH,WAAW;AAAA,QACX,SAAS;AAAA,MACX;AAAA,IACF;AACA,WAAO;AAAA,EACT,CAAC;AAED,QAAM,iBAAiB;AAAA,IACrB,GAAG;AAAA,IACH,WAAW,cAAc;AAAA,EAC3B;AAMA,QAAM,iBAA4B;AAAA,IAChC,EAAE,GAAG,MAAM,SAAS,gBAAgB,SAAS,eAAe;AAAA,IAC5D,KAAK;AAAA,EACP;AAEA,SAAO,GAAG,cAAc;AAC1B;;;AC5JA,IAAM,wBAAwB,CAAC,WAC7B,WAAW,cAAc,eACzB,WAAW,cAAc,qBACzB,WAAW,cAAc;AAG3B,IAAM,oBAAoB,CAAC,WACzB,WAAW,cAAc,kBACzB,WAAW,cAAc;AAI3B,IAAM,gBAAgB,CAAC,WACrB,WAAW,cAAc;AAMpB,IAAM,oBAAoB,CAAC,WAChC,sBAAsB,MAAM,KAC5B,kBAAkB,MAAM,KACxB,cAAc,MAAM;AAMf,IAAM,cAAc,CACzB,MACA,WAC0B;AAC1B,QAAM,gBAAgB,KAAK;AAE3B,MAAI,cAAc,aAAa,QAAQ;AACrC,WAAO,IAAI,UAAU,aAAa;AAAA,EACpC;AAEA,MAAI,CAAC,kBAAkB,cAAc,UAAU,GAAG;AAChD,WAAO,IAAI,UAAU,uBAAuB;AAAA,EAC9C;AAEA,SAAO,GAAG,cAAc,UAAU;AACpC;AAEO,IAAM,4BAAuD,CAClE,MACA,WACG;AACH,QAAM,OAAO,YAAY,MAAM,MAAM;AACrC,MAAI,MAAM,IAAI,GAAG;AACf,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,KAAK;AAEpB,MAAI,cAAc,MAAM,GAAG;AACzB,WAAO,cAAc,MAAM,QAAQ,MAAM;AAAA,EAC3C;AAEA,MAAI,kBAAkB,MAAM,GAAG;AAC7B,WAAO,kBAAkB,MAAM,QAAQ,MAAM;AAAA,EAC/C;AAGA,QAAM,aAAa,sBAAsB,MAAM;AAE/C,MAAI,eAAe,cAAc,YAAY;AAC3C,WAAOC,2BAA0B,IAAI;AAAA,EACvC;AAEA,SAAO,GAAG;AAAA,IACR,GAAG;AAAA,IACH,YAAY;AAAA,MACV,MAAM;AAAA,MACN,UAAU;AAAA,MACV;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,IAAM,oBAAoB,CACxB,MACA,QACA,WACoB;AAEpB,MAAI,iBAAiB,KAAK;AAC1B,MACE,WAAW,cAAc,kBACzB,gBAAgB,kBAChB;AACA,qBAAiB;AAAA,MACf,GAAG;AAAA,MACH,kBAAkB;AAAA,IACpB;AAAA,EACF;AAEA,QAAM,QAAQ,YAAY,KAAK,KAAK,IAAI;AACxC,QAAM,aAAa;AAAA,IACjB;AAAA,IACA;AAAA,EACF;AAEA,QAAM,cAAc;AAAA,IAClB,GAAG;AAAA,IACH,GAAI,mBAAmB,UAAa,EAAE,SAAS,eAAe;AAAA,EAChE;AAGA,MAAI,eAAe,cAAc,YAAY;AAC3C,WAAOA,2BAA0B,WAAW;AAAA,EAC9C;AAIA,MAAI,WAAW,cAAc,gBAAgB;AAC3C,WAAOA,2BAA0B,WAAW;AAAA,EAC9C;AAEA,SAAO,GAAG;AAAA,IACR,GAAG;AAAA,IACH,YAAY;AAAA,MACV,MAAM;AAAA,MACN,UAAU;AAAA,MACV;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,IAAM,gBAAgB,CACpB,MACA,QACA,WACoB;AACpB,QAAM,UAAU,6BAA6B,KAAK,KAAK,IAAI;AAC3D,QAAM,aAAa;AAAA,IACjB;AAAA,IACA;AAAA,EACF;AAEA,MAAI,eAAe,cAAc,YAAY;AAC3C,WAAOA,2BAA0B,IAAI;AAAA,EACvC;AAGA,SAAO,GAAG;AAAA,IACR,GAAG;AAAA,IACH,YAAY;AAAA,MACV,MAAM;AAAA,MACN,UAAU;AAAA,MACV;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,IAAMA,6BAA4B,CAChC,SACoB;AACpB,QAAM,WAAW,KAAK,MAAM,MAAM;AAClC,QAAM,aAAa,KAAK,SAAS;AAEjC,MAAI,cAAc,mBAAmB,KAAK,KAAK,GAAG;AAChD,WAAO,GAAG;AAAA,MACR,GAAG;AAAA,MACH,YAAY,EAAE,MAAM,QAAQ,MAAM,UAAU,OAAO;AAAA,IACrD,CAAC;AAAA,EACH;AAEA,SAAO,GAAG;AAAA,IACR,GAAG;AAAA,IACH,YAAY,mBAAmB,KAAK,KAAK;AAAA,EAC3C,CAAC;AACH;;;ACxGA,IAAM,UAAU,CACd,MACA,QACA,WACoB;AACpB,MAAI,CAAC,qBAAqB,IAAI,KAAK,KAAK,WAAW,eAAe,QAAQ;AACxE,WAAO;AAAA,EACT;AACA,SAAO,EAAE,MAAM,QAAQ,UAAU,KAAK,WAAW,SAAS;AAC5D;AAGA,IAAM,mBAAmB,CAAC,YACxB,QAAQ,QAAQ,CAAC,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC;AAKpD,IAAM,oCAET,CAAC,MAAM,WAAW;AACpB,QAAM,OAAO,QAAQ,MAAM,cAAc,gBAAgB,MAAM;AAC/D,MAAI,CAAC,KAAM,QAAO,CAAC;AAEnB,QAAM,UAAU,0BAA0B,KAAK,MAAM,KAAK,MAAM;AAChE,MAAI,MAAM,OAAO,EAAG,QAAO,CAAC;AAE5B,QAAM,EAAE,QAAQ,SAAS,eAAe,IAAI,QAAQ;AACpD,SAAO;AAAA,IACL,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR;AAAA,EACF;AACF;AAMO,IAAM,iCAET,CAAC,MAAM,WAAW;AACpB,QAAM,OAAO,QAAQ,MAAM,cAAc,aAAa,MAAM;AAC5D,MAAI,CAAC,KAAM,QAAO,CAAC;AAEnB,QAAM,UAAU,uBAAuB,KAAK,MAAM,KAAK,MAAM;AAC7D,MAAI,MAAM,OAAO,EAAG,QAAO,CAAC;AAE5B,QAAM,EAAE,QAAQ,iBAAiB,IAAI,QAAQ;AAC7C,SAAO,iBAAiB,OAAO,OAAO,EAAE;AAAA,IAAO,CAAC,aAC9C,eAAe,QAAQ,OAAO,SAAS,UAAU,gBAAgB;AAAA,EACnE;AACF;AAIA,IAAM,iBAAiB,OAA4B;AAAA,EACjD,WAAW,CAAC;AAAA,EACZ,WAAW,CAAC;AACd;AAEA,IAAM,yBAAyB,CAC7B,MACA,WACwB;AACxB,QAAM,OAAO,QAAQ,MAAM,cAAc,mBAAmB,MAAM;AAClE,MAAI,CAAC,KAAM,QAAO,eAAe;AAEjC,QAAM,UAAU,oBAAoB,KAAK,MAAM,KAAK,MAAM;AAC1D,MAAI,MAAM,OAAO,EAAG,QAAO,eAAe;AAE1C,QAAM,EAAE,QAAQ,YAAY,IAAI,QAAQ;AACxC,QAAM,QAAQ,YAAY;AAE1B,QAAM,YAAY,iBAAiB,OAAO,OAAO,EAAE;AAAA,IAAO,CAAC,aACzD;AAAA,MACE,OAAO;AAAA,MACP,OAAO,aAAa,CAAC;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AACA,QAAM,YAAY,MAAM,MAAM;AAAA,IAC5B,CAAC,SACC,SAAS,QAAQ,iBAAiB,OAAO,QAAQ,KAAK,EAAE,MAAM;AAAA,EAClE;AAGA,MAAI,UAAU,WAAW,KAAK,UAAU,WAAW,EAAG,QAAO,eAAe;AAC5E,SAAO,EAAE,WAAW,UAAU;AAChC;AAMO,IAAM,mCAET,CAAC,MAAM,WAAW,uBAAuB,MAAM,MAAM,EAAE;AAOpD,IAAM,gCAET,CAAC,MAAM,WAAW,uBAAuB,MAAM,MAAM,EAAE;AAE3D,IAAM,gBAAgB,OAA+B;AAAA,EACnD,SAAS,CAAC;AAAA,EACV,WAAW,CAAC;AACd;AAMO,IAAM,mCAET,CAAC,MAAM,WAAW;AACpB,QAAM,OAAO,QAAQ,MAAM,cAAc,gBAAgB,MAAM;AAC/D,MAAI,CAAC,KAAM,QAAO,cAAc;AAEhC,QAAM,UAAU,mBAAmB,KAAK,MAAM,KAAK,MAAM;AACzD,MAAI,MAAM,OAAO,EAAG,QAAO,cAAc;AAEzC,QAAM,EAAE,QAAQ,WAAW,WAAW,YAAY,QAAQ,IAAI,QAAQ;AAEtE,QAAM,YAAY,iBAAiB,OAAO,OAAO,EAAE;AAAA,IAAO,CAAC,aACzD;AAAA,MACE,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,UAAU,WAAW,EAAG,QAAO,cAAc;AAGjD,QAAM,iBAAiB,oBAAI,IAA0B;AACrD,QAAM,cAAc,CAAC,SAAwC;AAC3D,UAAM,MAAM,GAAG,KAAK,aAAa,IAAI,KAAK,cAAc;AACxD,QAAI,WAAW,eAAe,IAAI,GAAG;AACrC,QAAI,CAAC,UAAU;AACb,iBAAW;AAAA,QACT;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,MACP;AACA,qBAAe,IAAI,KAAK,QAAQ;AAAA,IAClC;AACA,WAAO;AAAA,EACT;AAEA,QAAM,UAAsC,CAAC;AAC7C,aAAW,WAAW,CAAC,GAAG,UAAU,SAAS,GAAG,UAAU,QAAQ,GAAG;AACnE,UAAM,OAAO,mBAAmB,WAAW,QAAQ,EAAE;AACrD,QAAI,CAAC,KAAM;AACX,UAAM,uBAAuB,YAAY,IAAI;AAC7C,QAAI,qBAAqB,SAAS,GAAG;AACnC,cAAQ,KAAK;AAAA,QACX,WAAW,QAAQ;AAAA,QACnB,QAAQ,KAAK;AAAA,QACb;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,EAAG,QAAO,cAAc;AAC/C,SAAO,EAAE,SAAS,UAAU;AAC9B;AAOO,IAAM,gCAET,CAAC,MAAM,WAAW;AACpB,QAAM,OAAO,QAAQ,MAAM,cAAc,YAAY,MAAM;AAC3D,MAAI,CAAC,KAAM,QAAO,CAAC;AAEnB,QAAM,UAAU,sBAAsB,KAAK,MAAM,KAAK,MAAM;AAC5D,MAAI,MAAM,OAAO,EAAG,QAAO,CAAC;AAE5B,QAAM,EAAE,OAAO,IAAI,QAAQ;AAC3B,SAAO,iBAAiB,OAAO,OAAO,EAAE;AAAA,IAAO,CAAC,aAC9C,KAAK,kBAAkB,QAAQ,QAAQ,CAAC;AAAA,EAC1C;AACF;AAEA,IAAM,gBAAgB,OAA0B;AAAA,EAC9C,cAAc,CAAC;AAAA,EACf,iBAAiB,CAAC;AACpB;AAMO,IAAM,8BAET,CAAC,MAAM,WAAW;AACpB,QAAM,OAAO,QAAQ,MAAM,cAAc,WAAW,MAAM;AAC1D,MAAI,CAAC,KAAM,QAAO,cAAc;AAEhC,QAAM,SAAS,mBAAmB,KAAK,MAAM,KAAK,MAAM;AACxD,MAAI,MAAM,MAAM,EAAG,QAAO,cAAc;AAExC,QAAM,SAAS,OAAO;AACtB,QAAM,gBAAgB,OAAO,UAAU,CAAC,GACrC,IAAI,CAAC,GAAG,UAAU,KAAK,EACvB,OAAO,CAAC,UAAU,gBAAgB,QAAQ,KAAK,CAAC;AACnD,QAAM,kBAAkB,KAAK,KAAK,QAC/B,OAAO,CAAC,WAAW,KAAK,mBAAmB,KAAK,MAAM,QAAQ,OAAO,EAAE,CAAC,CAAC,EACzE,IAAI,CAAC,WAAW,OAAO,EAAE;AAE5B,MAAI,aAAa,WAAW,KAAK,gBAAgB,WAAW,GAAG;AAC7D,WAAO,cAAc;AAAA,EACvB;AACA,SAAO,EAAE,cAAc,gBAAgB;AACzC;AAMO,IAAM,+BAET,CAAC,MAAM,WACT,qBAAqB,IAAI,KACzB,KAAK,YAAY,MAAM,UAAU,KAAK,WAAW,QAAQ,CAAC;;;ACpR5D,IAAM,sBAAsB,CAC1B,MACA,UACA,aAC+D;AAC/D,QAAM,OAAO,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK,WAAW,QAAQ;AACrE,MAAI,CAAC,MAAM,aAAc,QAAO;AAEhC,QAAM,CAAC,OAAO,MAAM,IAAI;AAAA,IACtB;AAAA,IACA;AAAA,IACA,KAAK;AAAA,EACP;AAEA,aAAW,UAAU,CAAC,OAAO,MAAM,GAAG;AACpC,QACE,OAAO,KAAK,SAAS,aACrB,OAAO,KAAK,kBACZ,OAAO,KAAK,iBAAiB,GAC7B;AACA,aAAO;AAAA,QACL,SAAS,OAAO,KAAK;AAAA,QACrB,iBAAiB,OAAO;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEO,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;AAGA,QAAM,eAA2B,CAAC;AAClC,MAAI,eAAe,KAAK,KAAK,IAAI,GAAG;AAClC,UAAM,CAAC,OAAO,MAAM,IAAI,wBAAwB,UAAU,UAAU,MAAM;AAC1E,eAAW,UAAU,CAAC,OAAO,MAAM,GAAG;AACpC,YAAM,WAAW,sBAAsB,OAAO,MAAM,OAAO,QAAQ;AACnE,UAAI,UAAU;AACZ,qBAAa,KAAK,QAAQ;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAEA,QAAM,iBAAiB,KAAK,QAAQ,IAAI,CAAC,WAAW;AAClD,QAAI,OAAO,OAAO,cAAc,IAAI;AAClC,YAAM,UAAU,EAAE,GAAG,QAAQ,SAAS,eAAe,MAAM;AAC3D,UAAI,aAAa,SAAS,KAAK,QAAQ,WAAW;AAChD,gBAAQ,YAAY,CAAC,GAAG,QAAQ,WAAW,GAAG,YAAY;AAAA,MAC5D;AACA,aAAO;AAAA,IACT;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,QAAM,gBAAgB,KAAK,KAAK,SAAS;AACzC,QAAM,YAAY,cAAc,KAAK,KAAK,IAAI;AAC9C,QAAM,QAAQ,kBAAkB,KAAK,KAAK,IAAI;AAC9C,QAAM,UAAU,6BAA6B,KAAK,KAAK,IAAI;AAE3D,MACE,cACA,mBAAmB,YAAY,KAC/B,CAAC,iBACD,CAAC,aACD,CAAC,OACD;AACA,kBAAc;AAAA,MACZ,GAAG;AAAA,MACH,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,SAAS;AAAA,IACX;AAAA,EACF,WAAW,iBAAiB,CAAC,YAAY;AAEvC,kBAAc;AAAA,MACZ,GAAG;AAAA,MACH,OAAO;AAAA,MACP,YAAY;AAAA,QACV,MAAM;AAAA,QACN,UAAU,YAAY;AAAA,QACtB,YAAY,cAAc;AAAA,MAC5B;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF,WAAW,iBAAiB,YAAY;AAEtC,UAAM,oBAAgC;AAAA,MACpC,MAAM;AAAA,MACN,UAAU,YAAY;AAAA,MACtB,YAAY,cAAc;AAAA,IAC5B;AACA,kBAAc;AAAA,MACZ,GAAG;AAAA,MACH,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,SAAS;AAAA,IACX;AAAA,EACF,WAAW,WAAW;AAEpB,QAAI,iBAAiB,oBAAoB,KAAK,SAAS,cAAc;AAGrE,UAAM,UAAU,oBAAoB,MAAM,UAAU,QAAQ;AAC5D,UAAM,cACJ,WAAW,iBACP,cAAc,eAAe,eAAe,QAAQ,OAAO,IAC3D;AAEN,QAAI,WAAW,kBAAkB,eAAe,KAAK,WAAW,GAAG;AAEjE,YAAM,mBAAqC;AAAA,QACzC,OAAO,YAAY,MAAM;AAAA,QACzB,iBAAiB,QAAQ;AAAA,MAC3B;AACA,uBAAiB;AAAA,QACf,GAAG;AAAA,QACH,eAAe,YAAY,MAAM;AAAA,QACjC;AAAA,MACF;AAGA,oBAAc;AAAA,QACZ,GAAG;AAAA,QACH,OAAO;AAAA,QACP,SAAS;AAAA,QACT,SAAS;AAAA,QACT,YAAY;AAAA,UACV,MAAM;AAAA,UACN,UAAU,YAAY;AAAA,UACtB,YAAY,cAAc;AAAA,QAC5B;AAAA,MACF;AAAA,IACF,OAAO;AAGL,oBAAc;AAAA,QACZ;AAAA,UACE,GAAG;AAAA,UACH,SAAS;AAAA,UACT,GAAI,mBAAmB,UAAa,EAAE,SAAS,eAAe;AAAA,QAChE;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF,WAAW,OAAO;AAEhB,UAAMC,iBAAgB,eAAe;AAAA,MACnC,CAAC,MAAM,EAAE,OAAO,YAAY;AAAA,IAC9B;AACA,UAAM,UAAU,cAAc,MAAM;AACpC,UAAM,cAAc,kBAAkB,MAAM;AAE5C,QAAI,YAAkC;AAEtC,QAAI,SAAS;AAGX,YAAM,qBACJA,kBACA;AAAA,QACEA,eAAc;AAAA,QACdA,eAAc,UAAU,CAAC;AAAA,MAC3B,EAAE,SAAS;AACb,YAAM,iBAAiB,KAAK,aAAa,aAAa,KAAK;AAE3D,UAAI,sBAAsB,eAAe;AACvC,oBAAY,cAAc;AAAA,MAC5B;AAAA,IACF,WAAW,aAAa;AAGtB,UAAIA,kBAAiB,eAAeA,cAAa,GAAG;AAClD,oBAAY,cAAc;AAAA,MAC5B;AAAA,IACF;AAEA,QAAI,WAAW;AACb,oBAAc;AAAA,QACZ,GAAG;AAAA,QACH,OAAO;AAAA,QACP,SAAS;AAAA,QACT,YAAY;AAAA,UACV,MAAM;AAAA,UACN,UAAU,YAAY;AAAA,UACtB,YAAY;AAAA,QACd;AAAA,MACF;AAAA,IACF,WAAW,SAAS;AAElB,oBAAc;AAAA,QACZ,GAAG;AAAA,QACH,OAAO;AAAA,QACP,SAAS;AAAA,QACT,YAAY;AAAA,UACV,MAAM;AAAA,UACN,UAAU,YAAY;AAAA,UACtB,YAAY,cAAc;AAAA,QAC5B;AAAA,MACF;AAAA,IACF,WAAW,cAAc,mBAAmB,YAAY,GAAG;AACzD,oBAAc;AAAA,QACZ,GAAG;AAAA,QACH,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,SAAS;AAAA,MACX;AAAA,IACF,OAAO;AACL,oBAAc;AAAA,QACZ,GAAG;AAAA,QACH,OAAO;AAAA,QACP,YAAY,mBAAmB,YAAY;AAAA,QAC3C,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF,OAAO;AACL,kBAAc;AAAA,MACZ,GAAG;AAAA,MACH,OAAO;AAAA,MACP,YAAY,mBAAmB,YAAY;AAAA,MAC3C,SAAS;AAAA,IACX;AAAA,EACF;AAIA,MAAI,YAAY,aAAa;AAC3B,UAAM,CAAC,OAAO,MAAM,IAAI,wBAAwB,UAAU,UAAU,MAAM;AAC1E,kBAAc;AAAA,MACZ,GAAG;AAAA,MACH,aAAa;AAAA,QACX,GAAG,YAAY;AAAA,QACf,qBAAqB,CAAC,MAAM,UAAU,OAAO,QAAQ;AAAA,MACvD;AAAA,IACF;AAAA,EACF;AAEA,SAAO,GAAG,WAAW;AACvB;;;ACpVO,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,aAAa,aAAa,OAAO,GAAG,eAAe;AACzD,aAAW,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAI7C,QAAM,gBAAgB;AAAA,IACpB;AAAA,IACA,KAAK,MAAM,MAAM,4BAA4B;AAAA,EAC/C;AAEA,QAAM,aAAyB;AAAA,IAC7B,MAAM;AAAA,IACN,UAAU,cAAc,CAAC,EAAG;AAAA,IAC5B,YAAY,cAAc;AAAA,EAC5B;AAGA,MAAI,cAAc,KAAK;AACvB,MACE,gBACC,KAAK,KAAK,SAAS,iBAClB,6BAA6B,KAAK,KAAK,IAAI,IAC7C;AACA,UAAM,kBAAkB,KAAK,OACzB,oBAAoB,KAAK,MAAM,WAAW,IAC1CA;AACJ,UAAM,QAAQ;AAAA,MACZ,YAAY,cAAc;AAAA,MAC1B;AAAA,IACF;AACA,kBAAc,EAAE,GAAG,aAAa,eAAe,MAAM;AAAA,EACvD;AAGA,MAAI,UAAU,KAAK;AACnB,MAAI,SAAS,aAAa,YAAY,KAAK,KAAK,IAAI,GAAG;AACrD,UAAM,cAAc,KAAK,OACrB,oBAAoB,KAAK,MAAM,SAAS,IACxCA;AACJ,UAAM,QAAQ,gBAAgB,QAAQ,UAAU,UAAU,WAAW;AACrE,cAAU,EAAE,GAAG,SAAS,WAAW,MAAM;AAAA,EAC3C;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,IACD,GAAI,gBAAgB,UAAa,EAAE,YAAY;AAAA,IAC/C,GAAI,YAAY,UAAa,EAAE,QAAQ;AAAA,EACzC;AAEA,SAAO,GAAG,QAAQ;AACpB;;;AC/FK,IAAM,mBAAqC,CAChD,MACA,QACA,eACG;AACH,QAAM,gBAAgB,KAAK;AAE3B,MAAI,cAAc,aAAa,QAAQ;AACrC,WAAO,IAAI,UAAU,aAAa;AAAA,EACpC;AAEA,MAAI,cAAc,eAAe,cAAc,WAAW;AACxD,WAAO,IAAI,UAAU,uBAAuB;AAAA,EAC9C;AAEA,MAAI,CAAC,KAAK,aAAa;AACrB,WAAO,IAAI,UAAU,uBAAuB;AAAA,EAC9C;AAEA,MACE,CAAC,KAAK,YAAY,mBAClB,KAAK,YAAY,qBACjB;AACA,WAAO,IAAI,UAAU,kBAAkB;AAAA,EACzC;AAEA,QAAM,cAAc,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM;AAC1D,MAAI,CAAC,YAAa,QAAO,IAAI,UAAU,cAAc;AAErD,QAAM,gBAAgB,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,YAAY,QAAQ;AAC5E,MAAI,CAAC,cAAe,QAAO,IAAI,UAAU,gBAAgB;AAGzD,MAAI,KAAK,YAAY,kBAAkB,cAAc,IAAI;AACvD,WAAO,IAAI,UAAU,8BAA8B;AAAA,EACrD;AAEA,QAAM,SAAS;AAAA,IACb,KAAK,YAAY;AAAA,IACjB;AAAA,IACA;AAAA,EACF;AAEA,MAAI,CAAC,QAAQ;AACX,WAAO,IAAI,UAAU,kBAAkB;AAAA,EACzC;AAEA,QAAM,EAAE,cAAc,cAAc,IAAI;AAExC,QAAM,iBAAiB,KAAK,QAAQ;AAAA,IAAI,CAAC,MACvC,EAAE,OAAO,cAAc,KAAK,gBAAgB;AAAA,EAC9C;AAGA,QAAM,WAAW,KAAK,MAAM,MAAM;AAClC,QAAM,aAAa,KAAK,SAAS;AAEjC,MAAI,cAAc,mBAAmB,KAAK,KAAK,GAAG;AAChD,WAAO,GAAG;AAAA,MACR,GAAG;AAAA,MACH,SAAS;AAAA,MACT,aAAa;AAAA,QACX,GAAG,KAAK;AAAA,QACR,eAAe;AAAA,QACf,qBAAqB;AAAA,MACvB;AAAA,MACA,YAAY,EAAE,MAAM,QAAQ,MAAM,UAAU,OAAO;AAAA,IACrD,CAAC;AAAA,EACH;AAEA,SAAO,GAAG;AAAA,IACR,GAAG;AAAA,IACH,SAAS;AAAA,IACT,aAAa;AAAA,MACX,GAAG,KAAK;AAAA,MACR,eAAe;AAAA,MACf,qBAAqB;AAAA,IACvB;AAAA,IACA,YAAwB,mBAAmB,KAAK,KAAK;AAAA,EACvD,CAAC;AACH;;;ACoCO,IAAM,kBAAkB,CAC7B,WACuB;AACvB,QAAM,iBAAiB,kBAAU;AACjC,QAAM,qBAAqB,qBAAa;AACxC,QAAM,sBAAsB,sBAAc;AAC1C,QAAM,oBAAoB,oBAAY;AACtC,QAAM,uBAAuB,uBAAe;AAC5C,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,QACZ,eAAe;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,MACF,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,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,IACA,mBAAmB,kBAAkB,QAAQ,YAAY,iBAAiB;AAAA,IAC1E,kBAAkB,iBAAiB,QAAQ,YAAY,gBAAgB;AAAA,IACvE,oBAAoB;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,0BAA0B;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,kBAAkB,iBAAiB,QAAQ,YAAY,gBAAgB;AAAA,IACvE,uBAAuB;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,uBAAuB;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,2BAA2B;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,mCAAmC;AAAA,MACjC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,CAAC,cAAc,GAAG,UAAU,MAAM;AAAA,IACpC;AAAA,IACA,gCAAgC;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,CAAC,cAAc,GAAG,UAAU,MAAM;AAAA,IACpC;AAAA,IACA,kCAAkC;AAAA,MAChC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,CAAC,cAAc,GAAG,UAAU,MAAM;AAAA,IACpC;AAAA,IACA,+BAA+B;AAAA,MAC7B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,CAAC,cAAc,GAAG,UAAU,MAAM;AAAA,IACpC;AAAA,IACA,kCAAkC;AAAA,MAChC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,CAAC,EAAE,SAAS,UAAU,MACpB,GAAG,QAAQ,MAAM,aAAa,UAAU,MAAM;AAAA,IAClD;AAAA,IACA,+BAA+B;AAAA,MAC7B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,CAAC,cAAc,GAAG,UAAU,MAAM;AAAA,IACpC;AAAA,IACA,6BAA6B;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,CAAC,EAAE,cAAc,gBAAgB,MAC/B,GAAG,aAAa,MAAM,YAAY,gBAAgB,MAAM;AAAA,IAC5D;AAAA,IACA,8BAA8B;AAAA,MAC5B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,CAAC,YAAY,GAAG,OAAO;AAAA,IACzB;AAAA,IACA,6BAA6B;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;ACtUA,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;AAAA,MACL,MAAM,MAAM,cAAc,oCAAoC;AAAA,IAChE;AAAA,EACF;AACA,MAAI,CAAC,qBAAqB,KAAK,IAAI,GAAG;AACpC,WAAO;AAAA,MACL,MAAM,QAAQ,gBAAgB,qCAAqC;AAAA,IACrE;AAAA,EACF;AACA,MAAI,CAAC,MAAM,QAAQ,KAAK,QAAQ,GAAG;AACjC,WAAO;AAAA,MACL,MAAM,YAAY,oBAAoB,2BAA2B;AAAA,IACnE;AAAA,EACF;AACA,MAAI,CAAC,MAAM,QAAQ,KAAK,eAAe,GAAG;AACxC,WAAO;AAAA,MACL;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,MAAI,CAAC,MAAM,QAAQ,KAAK,OAAO,GAAG;AAChC,WAAO;AAAA,MACL,MAAM,WAAW,mBAAmB,0BAA0B;AAAA,IAChE;AAAA,EACF;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;AAAA,QACL;AAAA,UACE;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,QAAI,CAAC,MAAM,QAAQ,KAAK,MAAM,KAAK,GAAG;AACpC,aAAO;AAAA,QACL;AAAA,UACE;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;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;AAAA,QACL;AAAA,UACE;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,MAAI,CAAC,KAAK,cAAc,OAAO,KAAK,eAAe,UAAU;AAC3D,WAAO;AAAA,MACL;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF,WACE,KAAK,WAAW,SAAS,YACzB,KAAK,WAAW,SAAS,QACzB;AACA,WAAO;AAAA,MACL;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,IAAM,eAAe,CAAC,MAAe,SAAoC;AACvE,QAAM,SAA4B,CAAC;AACnC,MAAI,CAAC,QAAQ,OAAO,SAAS,UAAU;AACrC,WAAO;AAAA,MACL,MAAM,MAAM,gBAAgB,WAAW,IAAI,oBAAoB;AAAA,IACjE;AACA,WAAO;AAAA,EACT;AACA,QAAM,IAAI;AACV,MAAI,OAAO,EAAE,SAAS,YAAY,CAAC,aAAa,IAAI,EAAE,IAAI,GAAG;AAC3D,WAAO;AAAA,MACL;AAAA,QACE,GAAG,IAAI;AAAA,QACP;AAAA,QACA,2BAA2B,IAAI;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AACA,MAAI,OAAO,EAAE,WAAW,YAAY,EAAE,SAAS,GAAG;AAChD,WAAO;AAAA,MACL;AAAA,QACE,GAAG,IAAI;AAAA,QACP;AAAA,QACA,qBAAqB,IAAI;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;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;AAAA,QACL;AAAA,UACE,GAAG,IAAI;AAAA,UACP;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF,WAAW,UAAU,IAAI,OAAO,EAAE,GAAG;AACnC,aAAO;AAAA,QACL;AAAA,UACE,GAAG,IAAI;AAAA,UACP;AAAA,UACA,wBAAwB,OAAO,EAAE;AAAA,QACnC;AAAA,MACF;AAAA,IACF,OAAO;AACL,gBAAU,IAAI,OAAO,EAAE;AAAA,IACzB;AAEA,QAAI,OAAO,OAAO,SAAS,YAAY,OAAO,KAAK,SAAS,GAAG;AAC7D,aAAO;AAAA,QACL;AAAA,UACE,GAAG,IAAI;AAAA,UACP;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,QAAI,CAAC,MAAM,QAAQ,OAAO,OAAO,GAAG;AAClC,aAAO;AAAA,QACL;AAAA,UACE,GAAG,IAAI;AAAA,UACP;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AACA,QAAI,OAAO,QAAQ,WAAW,UAAU;AACtC,aAAO;AAAA,QACL;AAAA,UACE,GAAG,IAAI;AAAA,UACP;AAAA,UACA,qBAAqB,QAAQ,cAAc,OAAO,QAAQ,MAAM;AAAA,QAClE;AAAA,MACF;AACA;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;AAAA,UACL;AAAA,YACE,GAAG,IAAI,YAAY,CAAC;AAAA,YACpB;AAAA,YACA,eAAe,CAAC,cAAc,QAAQ;AAAA,UACxC;AAAA,QACF;AACA;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,YACE,QACA,OAAO,SAAS,YACf,KAAiC,SAAS,UAC3C;AACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,QAAI,gBAAgB,GAAG;AACrB,aAAO;AAAA,QACL;AAAA,UACE,GAAG,IAAI;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF,WAAW,cAAc,GAAG;AAC1B,aAAO;AAAA,QACL;AAAA,UACE,GAAG,IAAI;AAAA,UACP;AAAA,UACA,eAAe,WAAW;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;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;AAAA,UACL;AAAA,YACE,GAAG,IAAI;AAAA,YACP;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF,WAAW,WAAW,IAAI,OAAO,MAAM,GAAG;AACxC,eAAO;AAAA,UACL;AAAA,YACE,GAAG,IAAI;AAAA,YACP;AAAA,YACA,4BAA4B,OAAO,MAAM;AAAA,UAC3C;AAAA,QACF;AAAA,MACF,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;AAAA,UACL;AAAA,YACE,GAAG,IAAI;AAAA,YACP;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA;AAAA,MACF;AAEA,YAAM,SAAS,SAAS;AACxB,UAAI,CAAC,kBAAkB,OAAO,MAAM,GAAG;AACrC,eAAO;AAAA,UACL;AAAA,YACE,GAAG,IAAI;AAAA,YACP;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF,WAAW,WAAW,IAAI,OAAO,MAAM,GAAG;AACxC,eAAO;AAAA,UACL;AAAA,YACE,GAAG,IAAI;AAAA,YACP;AAAA,YACA,4BAA4B,OAAO,MAAM;AAAA,UAC3C;AAAA,QACF;AAAA,MACF,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;AAAA,UACL;AAAA,YACE,GAAG,IAAI;AAAA,YACP;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,UAAI,CAAC,SAAS,UAAU,SAAS,WAAW,MAAM;AAChD,eAAO;AAAA,UACL;AAAA,YACE,GAAG,IAAI;AAAA,YACP;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;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;AAAA,YACL;AAAA,cACE,GAAG,IAAI;AAAA,cACP;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF,WAAW,kBAAkB,IAAI,OAAO,MAAM,GAAG;AAC/C,iBAAO;AAAA,YACL;AAAA,cACE,GAAG,IAAI;AAAA,cACP;AAAA,cACA,wCAAwC,OAAO,MAAM;AAAA,YACvD;AAAA,UACF;AAAA,QACF,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;AAAA,QACL;AAAA,UACE,GAAG,IAAI;AAAA,UACP;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF,WAAW,QAAQ,IAAI,KAAK,EAAE,GAAG;AAC/B,aAAO;AAAA,QACL;AAAA,UACE,GAAG,IAAI;AAAA,UACP;AAAA,UACA,sBAAsB,KAAK,EAAE;AAAA,QAC/B;AAAA,MACF;AAAA,IACF,OAAO;AACL,cAAQ,IAAI,KAAK,EAAE;AAAA,IACrB;AAEA,QAAI,CAAC,iBAAiB,KAAK,QAAQ,GAAG;AACpC,aAAO;AAAA,QACL;AAAA,UACE,GAAG,IAAI;AAAA,UACP;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF,WAAW,UAAU,OAAO,KAAK,CAAC,UAAU,IAAI,KAAK,QAAQ,GAAG;AAC9D,aAAO;AAAA,QACL;AAAA,UACE,GAAG,IAAI;AAAA,UACP;AAAA,UACA,wCAAwC,KAAK,QAAQ;AAAA,QACvD;AAAA,MACF;AAAA,IACF;AAEA,QAAI,KAAK,cAAc,CAAC,KAAK,WAAW,CAAC,KAAK,WAAW;AACvD,aAAO;AAAA,QACL;AAAA,UACE;AAAA,UACA;AAAA,UACA,uCAAuC,KAAK,OAAO,cAAc,KAAK,QAAQ;AAAA,UAC9E;AAAA,QACF;AAAA,MACF;AAAA,IACF;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;AAMf,QAAI,CAAC,iBAAiB,OAAO,QAAQ,GAAG;AACtC,aAAO;AAAA,QACL;AAAA,UACE;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF,WACE,MAAM,QAAQ,KAAK,KAAK,KACxB,CAAC,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,OAAO,QAAQ,GAChD;AACA,aAAO;AAAA,QACL;AAAA,UACE;AAAA,UACA;AAAA,UACA,0CAA0C,OAAO,QAAkB;AAAA,QACrE;AAAA,MACF;AAAA,IACF;AAEA,QACE,OAAO,OAAO,eAAe,YAC7B,CAAC,mBAAmB,IAAI,OAAO,UAAoB,GACnD;AACA,aAAO;AAAA,QACL;AAAA,UACE;AAAA,UACA;AAAA,UACA,8BAA8B,CAAC,GAAG,kBAAkB,EAAE,KAAK,IAAI,CAAC;AAAA,QAClE;AAAA,MACF;AAAA,IACF;AAAA,EACF,WAAW,WAAW,SAAS,QAAQ;AACrC,UAAM,OAAO;AAEb,QACE,OAAO,KAAK,SAAS,YACrB,CAAC,eAAe,IAAI,KAAK,IAAc,GACvC;AACA,aAAO;AAAA,QACL;AAAA,UACE;AAAA,UACA;AAAA,UACA,wBAAwB,CAAC,GAAG,cAAc,EAAE,KAAK,IAAI,CAAC;AAAA,QACxD;AAAA,MACF;AAAA,IACF;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;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,eAAW,SAAS,QAAQ;AAC1B,YAAM,QAAQ,YAAY,uBAAuB;AACjD,UAAI,CAAC,MAAM,MAAM,KAAK,CAAC,GAAG;AACxB,eAAO;AAAA,UACL;AAAA,YACE,eAAe,KAAK;AAAA,YACpB;AAAA,YACA,eAAe,KAAK;AAAA,UACtB;AAAA,QACF;AAAA,MACF;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;AAAA,UACL;AAAA,YACE,eAAe,CAAC;AAAA,YAChB;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;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;;;AC7dA,IAAM,YAAY,CAAC,MAAY,WAAuC;AACpE,QAAM,OAAO,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM;AACnD,SAAO,OAAO,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK,QAAQ,IAAI;AACnE;AAEA,IAAM,cAAc,CAClB,MACA,YACsB;AAAA,EACtB;AAAA,EACA;AAAA,EACA,UAAU,UAAU,MAAM,MAAM,GAAG,MAAM;AAAA,EACzC,SAAS,6BAA6B,MAAM,MAAM;AACpD;AAEO,IAAM,gBAAgB,CAC3B,MACA,YACmB;AAAA,EACnB,GAAG,YAAY,MAAM,MAAM;AAAA,EAC3B,gBAAgB,+BAA+B,MAAM,MAAM;AAC7D;AAEO,IAAM,kBAAkB,CAC7B,MACA,YACqB;AAAA,EACrB,GAAG,YAAY,MAAM,MAAM;AAAA,EAC3B,gBAAgB,iCAAiC,MAAM,MAAM;AAAA,EAC7D,qBAAqB,8BAA8B,MAAM,MAAM;AACjE;AAMO,IAAM,gBAAgB,CAC3B,MACA,WACkB;AAClB,QAAM,QAAQ,KAAK,aAAa,cAAc,SAAS,CAAC;AACxD,SAAO;AAAA,IACL,GAAG,YAAY,MAAM,MAAM;AAAA,IAC3B,iBAAiB,MAAM;AAAA,MACrB,CAAC,SACC,SAAS,QAAQ,KAAK,iBAAiB,MAAM,QAAQ,KAAK,EAAE,CAAC;AAAA,IACjE;AAAA,EACF;AACF;AAEO,IAAM,mBAAmB,CAC9B,MACA,YACsB;AAAA,EACtB,GAAG,YAAY,MAAM,MAAM;AAAA,EAC3B,gBAAgB,kCAAkC,MAAM,MAAM;AAChE;AAEO,IAAM,iBAAiB,CAC5B,MACA,YACoB;AAAA,EACpB,GAAG,YAAY,MAAM,MAAM;AAAA,EAC3B,aAAa,iCAAiC,MAAM,MAAM;AAC5D;AAEO,IAAM,uBAAuB,CAClC,MACA,YAC0B;AAAA,EAC1B,GAAG,YAAY,MAAM,MAAM;AAAA,EAC3B,gBAAgB,8BAA8B,MAAM,MAAM;AAAA,EAC1D,gBAAgB,CAAC,CAAC,KAAK,aAAa;AACtC;AAEO,IAAM,mBAAmB,CAC9B,MACA,YACsB;AAAA,EACtB,GAAG,YAAY,MAAM,MAAM;AAAA,EAC3B,SAAS,4BAA4B,MAAM,MAAM;AACnD;AAKO,IAAM,aAAa;AAOnB,IAAM,eAAe;AAErB,IAAM,uBAAuB;AAEpC,IAAM,qBAAqB;AAY3B,IAAM,iBAAiB,CAAC,SAAuB;AAC7C,QAAM,EAAE,SAAS,IAAI,KAAK,MAAM;AAChC,SAAO,WAAW,IAAI,KAAK,IAAI,IAAI,WAAW,KAAK,QAAQ,QAAQ,IAAI;AACzE;AAOA,IAAM,aAAa,CAAC,MAAY,WAA2B;AACzD,QAAM,QAAQ,eAAe,IAAI;AACjC,MAAI,UAAU,EAAG,QAAO;AACxB,MAAI,QAAQ;AACZ,MAAI,KAAK,aAAa;AACpB,aAAS,aAAa,SAAS,OAAO,SAAS;AAC/C,UAAM,cAAc,cAAc,MAAM,KAAK,OAAO,WAAW,CAAC,GAAG;AACnE,aAAS,eAAe,QAAQ,KAAK,IAAI,GAAG,WAAW;AAAA,EACzD;AACA,MAAI,YAAY,KAAK,KAAK,IAAI,GAAG;AAC/B,aAAS,uBAAuB,SAAS,OAAO,aAAa,CAAC,GAAG;AAAA,EACnE;AACA,SAAO;AACT;AAMO,IAAM,cAAc,CAAC,MAAY,WACtC,mBAAmB,MAAM,QAAQ,KAAK,EAAE,SAAS,WAAW,MAAM,MAAM;AAOnE,IAAM,gBAAgB,CAC3B,MACA,UACA,YACW;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,QAAQ;AACZ,MAAI,cAAc;AAClB,aAAW,UAAU,KAAK,SAAS;AACjC,UAAM,QAAQ,YAAY,MAAM,MAAM;AACtC,QAAI,OAAO,OAAO,UAAU;AAC1B,aAAO;AAAA,IACT,OAAO;AACL,eAAS;AACT,aAAO,cAAc,KAAK,IAAI,MAAM,KAAK,IAAI;AAC7C,oBAAc;AAAA,IAChB;AAAA,EACF;AACA,SAAO,OAAO,QAAQ,iBAAiB,OAAO,qBAAqB;AACrE;AASO,IAAM,wBAAwB,CACnC,MACA,UACA,YACoB;AACpB,QAAM,aAAa,CAAC,YAA0B;AAAA,IAC5C,GAAG;AAAA,IACH,SAAS,KAAK,QAAQ,IAAI,CAAC,MAAO,EAAE,OAAO,WAAW,SAAS,CAAE;AAAA,EACnE;AAEA,MAAI,YAAY,KAAK,KAAK,IAAI,GAAG;AAC/B,WAAO,CAAC,WAAW,cAAc,WAAW,MAAM,GAAG,UAAU,OAAO;AAAA,EACxE;AAGA,QAAM,OAAO,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ;AACvD,QAAM,WAAW,OACb,cAAc,MAAM,UAAU,OAAO,IAAI,YAAY,MAAM,IAAI,IAC/D;AACJ,SAAO,CAAC,WAAW,YAAY,MAAM,MAAM,IAAI;AACjD;AAOO,IAAM,0BAA0B,CACrC,MACA,QACA,QACA,cACkB;AAClB,QAAM,UAAU;AAAA,IACd,OAAO;AAAA,IACP,UAAU;AAAA,IACV,UAAU;AAAA,IACV;AAAA,IACA,KAAK,MAAM,MAAM;AAAA,EACnB;AACA,MAAI,CAAC,KAAK,OAAO,EAAG,QAAO;AAC3B,MAAI,CAAC,eAAe,KAAK,KAAK,IAAI,KAAK,CAAC,OAAO,WAAW;AACxD,WAAO,EAAE,GAAG,QAAQ,SAAS,QAAQ,MAAM;AAAA,EAC7C;AAEA,QAAM,QAAQ;AAAA,IACZ,UAAU;AAAA,IACV,UAAU;AAAA,IACV;AAAA,EACF,EACG,IAAI,CAAC,WAAW,sBAAsB,OAAO,MAAM,OAAO,QAAQ,CAAC,EACnE,OAAO,CAAC,aAAmC,aAAa,IAAI;AAC/D,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS,QAAQ;AAAA,IACjB,WAAW,CAAC,GAAG,OAAO,WAAW,GAAG,KAAK;AAAA,EAC3C;AACF;AAIA,IAAM,YAAY,CAAC,WACjB,KAAK,MAAM,IAAI,OAAO,QAAQ;AAOhC,IAAM,WAAW,CACf,SACA,SACA,OACA,YACa;AACb,MAAI,OAAiB;AACrB,MAAI,YAAY,QAAQ,UACpB,cAAc,QAAQ,MAAM,QAAQ,UAAU,OAAO,IACrD,OAAO;AAEX,aAAW,UAAU,SAAS;AAC5B,UAAM,QAAQ,MAAM,MAAM;AAC1B,QAAI,CAAC,MAAO;AACZ,UAAM,QAAQ,cAAc,OAAO,QAAQ,UAAU,OAAO;AAC5D,QAAI,QAAQ,WAAW;AACrB,kBAAY;AACZ,aAAO;AAAA,IACT;AAAA,EACF;AAGA,MAAI,SAAS,QAAQ,CAAC,QAAQ,QAAS,QAAO,QAAQ,CAAC,KAAK;AAC5D,SAAO;AACT;AAGO,IAAM,qBAAqB,CAChC,SACA,YAEA;AAAA,EACE;AAAA,EACA,QAAQ;AAAA,EACR,CAAC,aACC,UAAU,mBAAmB,QAAQ,MAAM,QAAQ,QAAQ,QAAQ,CAAC;AAAA,EACtE;AACF;AAGK,IAAM,eAAe,CAC1B,SACA,YAEA;AAAA,EACE;AAAA,EACA,QAAQ,oBAAoB;AAAA,IAAQ,CAAC,aACnC,QAAQ,eAAe,IAAI,CAAC,cAAc;AAAA,MACxC,YAAY,SAAS;AAAA,MACrB;AAAA,IACF,EAAE;AAAA,EACJ;AAAA,EACA,CAAC,WACC;AAAA,IACE;AAAA,MACE,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,EACF;AAAA,EACF;AACF;AAGK,IAAM,wBAAwB,CACnC,SACA,YAEA;AAAA,EACE;AAAA,EACA,QAAQ;AAAA,EACR,CAAC,aACC,UAAU,sBAAsB,QAAQ,MAAM,QAAQ,QAAQ,QAAQ,CAAC;AAAA,EACzE;AACF;AAOK,IAAM,4BAA4B;AASlC,IAAM,yBAAyB,CACpC,SACA,YACyB;AACzB,QAAM,EAAE,SAAS,UAAU,IAAI,QAAQ;AACvC,QAAM,UAAU,CAAC,WACf;AAAA,IACE;AAAA,MACE,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,EACF;AAEF,QAAM,UAAU,QAAQ;AAAA,IACtB,CAACC,YAAqCA,QAAO,WAAW;AAAA,EAC1D;AACA,QAAM,SAAS;AAAA,IACb;AAAA,IACA,QAAQ;AAAA,MAAQ,CAACA,YACf,UAAU;AAAA,QACR,CAAC,cAA6B;AAAA,UAC5B,WAAWA,QAAO;AAAA,UAClB;AAAA,UACA,mBAAmBA,QAAO,qBAAqB,CAAC,KAAK,CAAC;AAAA,QACxD;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,cAAc,OAAO,SAAS;AACnE,QAAM,YAAY,QAAQ,wBAAwB,CAAC,GAAG;AAAA,IACpD;AAAA,IACA;AAAA,EACF;AACA,SACE;AAAA,IACE,EAAE,GAAG,SAAS,SAAS,MAAM;AAAA,IAC7B,SAAS,IAAI,CAAC,uBAAuB,EAAE,GAAG,QAAQ,kBAAkB,EAAE;AAAA,IACtE;AAAA,IACA;AAAA,EACF,KAAK;AAET;AAMO,IAAM,oBAAoB,CAC/B,SACA,YAEA;AAAA,EACE,EAAE,GAAG,SAAS,SAAS,MAAM;AAAA,EAC7B,QAAQ;AAAA,EACR,CAAC,aACC,UAAU,kBAAkB,QAAQ,MAAM,QAAQ,QAAQ,QAAQ,CAAC;AAAA,EACrE;AACF;AAMF,IAAM,sBAAsB,CAAC,UAAgC;AAC3D,MACE,CAAC,qBAAqB,KAAK,KAC3B,MAAM,WAAW,eAAe,cAAc,cAC9C,CAAC,MAAM,aAAa,cACpB;AACA,WAAO;AAAA,EACT;AACA,QAAM,eAAe,MAAM,WAAW;AACtC,QAAM,WAAW,UAAU,OAAO,YAAY,GAAG,MAAM;AACvD,MAAI,OAAkB;AACtB,MAAI,YAAY,OAAO;AACvB,aAAW,YAAY,8BAA8B,OAAO,YAAY,GAAG;AACzE,UAAM,OAAO,UAAU,kBAAkB,OAAO,cAAc,QAAQ,CAAC;AACvE,QAAI,CAAC,KAAM;AACX,UAAM,QAAQ,cAAc,MAAM,UAAU,EAAE,gBAAgB,EAAE,CAAC;AACjE,QAAI,QAAQ,WAAW;AACrB,kBAAY;AACZ,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAMO,IAAM,kBAAkB,CAC7B,SACA,YAEA;AAAA,EACE;AAAA,EACA,QAAQ,QAAQ,aAAa;AAAA,IAAQ,CAAC,eACpC,QAAQ,QAAQ,gBAAgB,IAAI,CAAC,oBAAoB;AAAA,MACvD;AAAA,MACA;AAAA,IACF,EAAE;AAAA,EACJ;AAAA,EACA,CAAC,WAAW;AACV,UAAM,QAAQ;AAAA,MACZ;AAAA,QACE,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,OAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO,QAAQ,oBAAoB,KAAK,IAAI;AAAA,EAC9C;AAAA,EACA;AACF;AASK,IAAM,iBAAiB,CAC5B,MACA,SAEA;AAAA,EACE,KAAK,QAAQ,KAAK;AAAA,EAClB;AAAA,IACE;AAAA,IACA,KAAK;AAAA,IACL,KAAK,WAAW;AAAA,IAChB,KAAK,WAAW;AAAA,IAChB,KAAK,SAAS;AAAA,IACd,KAAK,gBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE;AAAA,IAC7C,KAAK,aAAa,cAAc,cAAc;AAAA,IAC9C;AAAA,EACF,EAAE,KAAK,GAAG;AACZ;AAGK,IAAM,aAAa,CACxB,QACA,UACkB,MAAM,KAAK,MAAM,OAAO,IAAI,MAAM,MAAM,CAAC;AAMtD,IAAM,eAAe,CAC1B,SACA,SACA,SACa;AACb,QAAM,SAAS,eAAe,QAAQ,MAAM,IAAI;AAChD,QAAM,UAAwB,QAAQ,UAAU,CAAC,MAAM,GAAG,OAAO,IAAI;AACrE,SAAO,WAAW,QAAQ,OAAO,KAAK;AACxC;;;AC7mBA,IAAM,uBAAuB,OAAoC;AAAA,EAC/D,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,QAAQ;AACV;AAMO,IAAM,cAAc,CACzB,MACA,WAC4B;AAC5B,SAAO,SAAS,IAAI,KAAK,qBAAqB,EAAE,IAAI;AACtD;AAKO,IAAM,mBAAmB,MAC9B,OAAO,KAAK,qBAAqB,CAAC;;;AC4FpC,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,eAAe,CACnB,MACA,QACA,aACY;AAAA,EACZ;AAAA,EACA,UAAU,sBAAsB,MAAM,OAAO,IAAI,OAAO;AAAA,EACxD,SAAS,KAAK,MAAM,MAAM;AAC5B;AAEA,IAAM,qBAAqB,CACzB,QACA,QACA,QACA,eACwE;AACxE,MAAI,OAIO;AAEX,aAAW,aAAa,YAAY;AAClC,UAAM,OAAO;AAAA,MACX,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,QAAI,CAAC,KAAM;AACX,UAAM,QAAQ,OAAO,SAAS,IAAI;AAClC,QAAI,CAAC,QAAQ,QAAQ,KAAK,OAAO;AAC/B,aAAO,EAAE,WAAW,OAAO,QAAQ,KAAK;AAAA,IAC1C;AAAA,EACF;AAEA,SAAO;AACT;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;AAQA,IAAM,sBAAsB,CAC1B,aACyB;AAAA,EACzB,sBAAsB,CAAC,YAAY,mBAAmB,SAAS,OAAO;AAAA,EACtE,gBAAgB,CAAC,YAAY,aAAa,SAAS,OAAO;AAAA,EAC1D,oBAAoB,MAAM;AAAA,EAC1B,yBAAyB,CAAC,YAAY,sBAAsB,SAAS,OAAO;AAAA,EAC5E,0BAA0B,CAAC,YACzB,uBAAuB,SAAS,OAAO;AAAA,EACzC,qBAAqB,CAAC,YAAY,kBAAkB,SAAS,OAAO;AAAA,EACpE,mBAAmB,CAAC,YAAY,gBAAgB,SAAS,OAAO;AAClE;AAWO,IAAM,iBAA8B;AAAA,EACzC,cAAc,CAAC,YAAY;AACzB,UAAM,EAAE,MAAM,kBAAkB,IAAI;AACpC,UAAM,OAAO,WAAW,eAAe,MAAM,MAAM,GAAG,iBAAiB;AACvE,YAAQ,QAAQ,kBAAkB,CAAC,GAAI,OAAO;AAAA,EAChD;AAAA,EAEA,iBAAiB,CAAC,YAAY;AAC5B,UAAM,EAAE,MAAM,gBAAgB,IAAI;AAClC,WAAO,WAAW,eAAe,MAAM,OAAO,GAAG,eAAe,KAAK;AAAA,EACvE;AAAA,EAEA,sBAAsB,CAAC,YACrB,aAAa,SAAS,QAAQ,gBAAgB,QAAQ;AAAA,EAExD,gBAAgB,CAAC,YAAY;AAC3B,UAAM,WAAW;AAAA,MACf;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,IACF;AACA,UAAM,WAAW;AAAA,MACf,eAAe,QAAQ,MAAM,mBAAmB;AAAA,MAChD,QAAQ;AAAA,IACV;AACA,WAAO,YAAY,WAAW,EAAE,YAAY,SAAS,IAAI,SAAS,IAAI;AAAA,EACxE;AAAA,EAEA,oBAAoB,CAAC,YACnB,aAAa,SAAS,QAAQ,iBAAiB,QAAQ,GAAG,MAAM;AAAA,EAElE,yBAAyB,CAAC,YACxB,aAAa,SAAS,QAAQ,gBAAgB,MAAM;AAAA,EAEtD,0BAA0B,CAAC,YAAY;AACrC,UAAM,EAAE,SAAS,UAAU,IAAI,QAAQ;AACvC,UAAM,SAAS,aAAa,SAAS,SAAS,SAAS;AACvD,UAAM,SAAS,eAAe,QAAQ,MAAM,iBAAiB;AAC7D,UAAM,WAAW,WAAW,QAAQ,SAAS;AAC7C,UAAM,UAAU,UAAU,WAAW,QAAQ,OAAO,oBAAoB;AACxE,WAAO,UAAU,YAAY,UACzB,EAAE,WAAW,OAAO,WAAW,UAAU,mBAAmB,QAAQ,IACpE;AAAA,EACN;AAAA,EAEA,qBAAqB,CAAC,YACpB;AAAA,IACE,EAAE,GAAG,SAAS,SAAS,MAAM;AAAA,IAC7B,QAAQ;AAAA,IACR;AAAA,EACF;AAAA,EAEF,mBAAmB,CAAC,YAAY;AAC9B,UAAM,EAAE,cAAc,gBAAgB,IAAI,QAAQ;AAClD,UAAM,aAAa,aAAa,SAAS,cAAc,MAAM;AAC7D,UAAM,iBAAiB;AAAA,MACrB,eAAe,QAAQ,MAAM,aAAa;AAAA,MAC1C;AAAA,IACF;AACA,WAAO,eAAe,QAAQ,mBAAmB,SAC7C,EAAE,YAAY,eAAe,IAC7B;AAAA,EACN;AACF;AAIA,IAAM,iBAAoC,EAAE,gBAAgB,EAAE;AAUvD,IAAM,iBAAoD;AAAA,EAC/D,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,SAAS,aAAa,MAAM,QAAQ,cAAc;AACxD,QAAI,YAAY,OAAO;AACvB,QAAI,WAAW,kBAAkB,CAAC,EAAG,OAAO;AAE5C,eAAW,MAAM,mBAAmB;AAClC,YAAM,aAAa;AAAA,QACjB,OAAO;AAAA,QACP,GAAG;AAAA,QACH,OAAO;AAAA,MACT;AACA,YAAM,SAAS,mBAAmB,QAAQ,QAAQ,GAAG,QAAQ,UAAU;AACvE,YAAM,QAAQ,SAAS,OAAO,QAAQ,OAAO,SAAS,MAAM;AAC5D,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,QAAQ,gBAAgB,IAAI;AAClD,QAAI,gBAAgB,WAAW,EAAG,QAAO;AACzC,UAAM,EAAE,OAAO,IAAI,iBAAiB,MAAM,MAAM;AAChD,QAAI,CAAC,OAAQ,QAAO,gBAAgB,CAAC;AAErC,UAAM,SAAS,aAAa,MAAM,QAAQ,cAAc;AACxD,UAAM,SAAS,mBAAmB,QAAQ,QAAQ,QAAQ,eAAe;AACzE,WAAO,SAAS,OAAO,YAAY,gBAAgB,CAAC;AAAA,EACtD;AAAA,EAEA,GAAG,oBAAoB,cAAc;AACvC;AAIA,IAAM,mBAAsC,EAAE,gBAAgB,IAAI;AAElE,IAAM,wBAAwB,CAC5B,QACA,QACA,iBACW;AACX,MAAI,aAAa,WAAW,EAAG,QAAO;AAEtC,MAAI,gBAAgB;AACpB,aAAW,cAAc,cAAc;AACrC,UAAM,iBAAiB;AAAA,MACrB,OAAO;AAAA,MACP;AAAA,MACA,OAAO;AAAA,IACT;AACA,UAAM,SAAS;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,QAAI,UAAU,OAAO,QAAQ,eAAe;AAC1C,sBAAgB,OAAO;AAAA,IACzB;AAAA,EACF;AAEA,SAAO;AACT;AAUO,IAAM,mBAAsD;AAAA,EACjE,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,SAAS,aAAa,MAAM,QAAQ,gBAAgB;AAC1D,UAAM,YAAY,qBAAqB,IAAI;AAE3C,QAAI,oBAAoB,OAAO;AAC/B,QAAI,WAAW,kBAAkB,CAAC,EAAG,OAAO;AAE5C,eAAW,MAAM,mBAAmB;AAClC,YAAM,aAAa;AAAA,QACjB,OAAO;AAAA,QACP,GAAG;AAAA,QACH,OAAO;AAAA,MACT;AACA,YAAM,SAAS,mBAAmB,QAAQ,QAAQ,GAAG,QAAQ,UAAU;AAEvE,YAAM,iBAAiB,SAAS,OAAO,QAAQ,OAAO,SAAS,MAAM;AACrE,YAAM,cAAc,SAAS,OAAO,SAAS;AAC7C,YAAM,cAAc,sBAAsB,QAAQ,aAAa,SAAS;AACxE,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,QAAQ,gBAAgB,IAAI;AAClD,QAAI,gBAAgB,WAAW,EAAG,QAAO;AACzC,UAAM,EAAE,OAAO,IAAI,iBAAiB,MAAM,MAAM;AAChD,QAAI,CAAC,OAAQ,QAAO,gBAAgB,CAAC;AAErC,UAAM,SAAS,aAAa,MAAM,QAAQ,gBAAgB;AAC1D,UAAM,YAAY,qBAAqB,IAAI;AAE3C,QAAI,oBAAoB,OAAO;AAC/B,QAAI,gBAAgC,gBAAgB,CAAC;AAErD,eAAW,aAAa,iBAAiB;AACvC,YAAM,OAAO,wBAAwB,MAAM,QAAQ,QAAQ,SAAS;AACpE,UAAI,CAAC,KAAM;AAEX,YAAM,iBAAiB,OAAO,SAAS,IAAI;AAC3C,YAAM,cAAc,sBAAsB,QAAQ,MAAM,SAAS;AACjE,YAAM,WAAW,iBAAiB,cAAc;AAEhD,UAAI,WAAW,mBAAmB;AAChC,4BAAoB;AACpB,wBAAgB;AAAA,MAClB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,GAAG,oBAAoB,gBAAgB;AACzC;AAIA,IAAM,iBAAoC,EAAE,gBAAgB,EAAE;AAG9D,IAAM,oBAAoB;AAG1B,IAAM,mBAAmB;AAMzB,IAAM,gBAAgB,CACpB,QACA,QACA,QACA,YACA,UACoD;AACpD,QAAM,sBAAsB,WAAW,QAAQ,CAAC,cAAc;AAC5D,UAAM,OAAO;AAAA,MACX,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,WAAO,OAAO,CAAC,EAAE,WAAW,QAAQ,KAAK,CAAC,IAAI,CAAC;AAAA,EACjD,CAAC;AACD,MAAI,oBAAoB,UAAU,MAAO,QAAO;AAEhD,SAAO,oBACJ,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,OAAO,SAAS,EAAE,MAAM,EAAE,EAAE,EACvD,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,EAChC,MAAM,GAAG,KAAK;AACnB;AAEA,IAAM,iBAAiB,CACrB,QACA,QACA,mBACA,iBACA,UACW;AACX,MAAI,SAAS,KAAK,kBAAkB,WAAW,GAAG;AAChD,WAAO,OAAO,SAAS,MAAM;AAAA,EAC/B;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,OAAO,SAAS,MAAM;AAEtC,aAAW,UAAU,OAAO;AAC1B,UAAM,gBAAgB;AAAA,MACpB,OAAO;AAAA,MACP;AAAA,MACA,OAAO;AAAA,IACT;AAEA,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,QAAQ;AAAA,QACZ;AAAA,QACA,UAAU;AAAA,QACV;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,MACV;AACA,UAAI,QAAQ,UAAW,aAAY;AAAA,IACrC;AAAA,EACF;AAEA,SAAO;AACT;AASO,IAAM,iBAAoD;AAAA,EAC/D,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,SAAS,aAAa,MAAM,QAAQ,cAAc;AACxD,UAAM,UAAU,KAAK,MAAM,MAAM;AACjC,UAAM,YAAY,KAAK;AAAA,MACrB,KAAK,MAAM,MAAM,WAAW,KAAK;AAAA,MACjC;AAAA,IACF;AAEA,QAAI,YAAY,OAAO;AACvB,QAAI,WAAW,kBAAkB,CAAC,EAAG,OAAO;AAE5C,eAAW,MAAM,mBAAmB;AAClC,YAAM,gBAAgB;AAAA,QACpB,OAAO;AAAA,QACP,GAAG;AAAA,QACH,OAAO;AAAA,MACT;AAEA,UAAI,cAAc,WAAW,GAAG;AAC9B,cAAM,QAAQ;AAAA,UACZ;AAAA,UACA;AAAA,UACA,KAAK;AAAA,UACL;AAAA,UACA;AAAA,QACF;AACA,YAAI,QAAQ,WAAW;AACrB,sBAAY;AACZ,qBAAW,GAAG,OAAO;AAAA,QACvB;AACA;AAAA,MACF;AAEA,YAAM,aAAa;AAAA,QACjB;AAAA,QACA;AAAA,QACA,GAAG;AAAA,QACH;AAAA,QACA;AAAA,MACF;AAEA,iBAAW,aAAa,YAAY;AAClC,cAAM,QAAQ;AAAA,UACZ;AAAA,UACA,UAAU;AAAA,UACV,KAAK;AAAA,UACL;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,QAAQ,gBAAgB,IAAI;AAClD,QAAI,gBAAgB,WAAW,EAAG,QAAO;AACzC,UAAM,EAAE,OAAO,IAAI,iBAAiB,MAAM,MAAM;AAChD,QAAI,CAAC,OAAQ,QAAO,gBAAgB,CAAC;AAErC,UAAM,SAAS,aAAa,MAAM,QAAQ,cAAc;AACxD,UAAM,UAAU,KAAK,MAAM,MAAM;AACjC,UAAM,YAAY,KAAK;AAAA,MACrB,KAAK,MAAM,MAAM,WAAW,KAAK;AAAA,MACjC;AAAA,IACF;AAEA,QAAI,YAAY,OAAO;AACvB,QAAI,gBAAgC,gBAAgB,CAAC;AAErD,eAAW,aAAa,iBAAiB;AACvC,YAAM,OAAO,wBAAwB,MAAM,QAAQ,QAAQ,SAAS;AACpE,UAAI,CAAC,KAAM;AAEX,YAAM,QAAQ;AAAA,QACZ;AAAA,QACA;AAAA,QACA,KAAK;AAAA,QACL;AAAA,QACA;AAAA,MACF;AACA,UAAI,QAAQ,WAAW;AACrB,oBAAY;AACZ,wBAAgB;AAAA,MAClB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,GAAG,oBAAoB,cAAc;AACvC;AASA,IAAM,eAAe,CACnB,QACA,MACA,SACA,WACA,QACA,UACA,UACc;AACd,QAAM,SAAS,KAAK,WAAW;AAC/B,MAAI,CAAC,UAAW,QAAO,OAAO,mBAAmB,EAAE,MAAM,OAAO,CAAC;AACjE,QAAM,UAAU,UAAU,UAAU,OAAO;AAC3C,SAAO,WAAW,OACd,OAAO,mBAAmB,EAAE,MAAM,OAAO,CAAC,IAC1C,MAAM,MAAM;AAClB;AAYO,IAAM,cAAc,CACzB,QACA,MACA,aACc;AACd,QAAM,SAAS,KAAK,WAAW;AAC/B,QAAM,SAAS,KAAK,WAAW;AAC/B,QAAM,WAAW;AAEjB,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,KAAK,MAAM,MAAM;AACjC,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;AAIA,MAAI,WAAW,cAAc;AAC3B,UAAM,UAAU,qBAAqB,MAAM,MAAM;AACjD,QAAI,QAAQ,eAAe,WAAW,GAAG;AACvC,aAAO,OAAO,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAAA,IACnD;AACA,UAAM,WACJ,SAAS,sBAAsB,OAAO,KACtC,SAAS,oBAAoB,OAAO,KACpC,QAAQ,eAAe,CAAC;AAC1B,WAAO,OAAO,WAAW,EAAE,MAAM,QAAQ,SAAS,CAAC;AAAA,EACrD;AAEA,MAAI,WAAW,eAAe;AAC5B,UAAM,UAAU,cAAc,MAAM,MAAM;AAC1C,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ,eAAe,SAAS;AAAA,MAChC,SAAS;AAAA,MACT,SAAS;AAAA,MACT,CAAC,aAAa,OAAO,YAAY,EAAE,MAAM,QAAQ,SAAS,CAAC;AAAA,IAC7D;AAAA,EACF;AAEA,MAAI,WAAW,qBAAqB;AAClC,UAAM,UAAU,gBAAgB,MAAM,MAAM;AAC5C,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ,eAAe,SAAS,KAC9B,QAAQ,oBAAoB,SAAS;AAAA,MACvC,SAAS;AAAA,MACT,SAAS;AAAA,MACT,CAAC,EAAE,YAAY,SAAS,MACtB,OAAO,kBAAkB,EAAE,MAAM,QAAQ,YAAY,SAAS,CAAC;AAAA,IACnE;AAAA,EACF;AAEA,MAAI,WAAW,aAAa;AAC1B,UAAM,UAAU,cAAc,MAAM,MAAM;AAC1C,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ,gBAAgB,SAAS;AAAA,MACjC,SAAS;AAAA,MACT,SAAS;AAAA,MACT,CAAC,eAAe,OAAO,UAAU,EAAE,MAAM,QAAQ,WAAW,CAAC;AAAA,IAC/D;AAAA,EACF;AAEA,MAAI,WAAW,kBAAkB;AAC/B,UAAM,UAAU,iBAAiB,MAAM,MAAM;AAC7C,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ,eAAe,SAAS;AAAA,MAChC,SAAS;AAAA,MACT,SAAS;AAAA,MACT,CAAC,aAAa,OAAO,eAAe,EAAE,MAAM,QAAQ,SAAS,CAAC;AAAA,IAChE;AAAA,EACF;AAEA,MAAI,WAAW,kBAAkB;AAC/B,UAAM,UAAU,eAAe,MAAM,MAAM;AAC3C,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ,YAAY,QAAQ,SAAS;AAAA,MACrC,SAAS;AAAA,MACT,SAAS;AAAA,MACT,CAAC,EAAE,WAAW,UAAU,kBAAkB,MACxC,OAAO,eAAe;AAAA,QACpB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACL;AAAA,EACF;AAEA,MAAI,WAAW,aAAa;AAC1B,UAAM,UAAU,iBAAiB,MAAM,MAAM;AAC7C,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ,QAAQ,aAAa,SAAS;AAAA,MACtC,SAAS;AAAA,MACT,SAAS;AAAA,MACT,CAAC,EAAE,YAAY,eAAe,MAC5B,OAAO,UAAU,EAAE,MAAM,QAAQ,YAAY,eAAe,CAAC;AAAA,IACjE;AAAA,EACF;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;;;AC31BO,IAAM,qBAAqB;AA0H3B,IAAM,kBAAkB,CAAC,YAAmC;AAAA,EACjE,SAAS;AAAA,EACT;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,IACxD,sBAAsB,CAAC,QAAQ,OAAO,qBAAqB,GAAG;AAAA;AAAA,IAG9D,YAAY,CAAC,QAAQ;AACnB,YAAM,OAAO,OAAO,WAAW,GAAG;AAClC,YAAM,gBAAgB,KAAK,EAAE;AAC7B;AAAA,QACE;AAAA,QACA,EAAE,MAAM,IAAI,MAAM,MAAM,KAAK,QAAQ,IAAI,MAAM,QAAQ,KAAK,GAAG;AAAA,QAC/D,KAAK;AAAA,MACP;AACA,aAAO;AAAA,IACT;AAAA,IAEA,YAAY,CAAC,QAAQ;AACnB,YAAM,OAAO,OAAO,WAAW,GAAG;AAClC;AAAA,QACE;AAAA,QACA;AAAA,UACE,SAAS,KAAK,QAAQ,IAAI,CAAC,YAAY;AAAA,YACrC,IAAI,OAAO;AAAA,YACX,MAAM,OAAO;AAAA,YACb,GAAI,OAAO,OAAO,EAAE,KAAK,OAAO,IAAI;AAAA,UACtC,EAAE;AAAA,QACJ;AAAA,QACA,KAAK;AAAA,MACP;AACA,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;AAAA,QACE;AAAA,QACA,EAAE,SAAS,KAAK,MAAM,IAAI,CAAC,SAAS,KAAK,EAAE,EAAE;AAAA,QAC7C,KAAK;AAAA,MACP;AACA,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;AAAA,IAGA,aAAa,CAAC,QAAQ;AACpB,YAAM,OAAO,OAAO,YAAY,GAAG;AACnC;AAAA,QACE;AAAA,QACA,EAAE,QAAQ,IAAI,QAAQ,UAAU,IAAI,SAAS;AAAA,QAC7C,KAAK;AAAA,MACP;AACA,aAAO;AAAA,IACT;AAAA,IAEA,mBAAmB,CAAC,QAAQ;AAC1B,YAAM,OAAO,OAAO,kBAAkB,GAAG;AACzC;AAAA,QACE;AAAA,QACA;AAAA,UACE,QAAQ,IAAI;AAAA,UACZ,YAAY,IAAI;AAAA,UAChB,UAAU,IAAI;AAAA,QAChB;AAAA,QACA,KAAK;AAAA,MACP;AACA,aAAO;AAAA,IACT;AAAA,IAEA,WAAW,CAAC,QAAQ;AAClB,YAAM,OAAO,OAAO,UAAU,GAAG;AACjC;AAAA,QACE;AAAA,QACA,EAAE,QAAQ,IAAI,QAAQ,YAAY,IAAI,WAAW;AAAA,QACjD,KAAK;AAAA,MACP;AACA,aAAO;AAAA,IACT;AAAA,IAEA,oBAAoB,CAAC,QAAQ;AAC3B,YAAM,OAAO,OAAO,mBAAmB,GAAG;AAC1C,aAAO,sBAAsB,EAAE,QAAQ,IAAI,OAAO,GAAG,KAAK,IAAI;AAC9D,aAAO;AAAA,IACT;AAAA;AAAA,IAGA,gBAAgB,CAAC,QAAQ;AACvB,YAAM,OAAO,OAAO,eAAe,GAAG;AACtC;AAAA,QACE;AAAA,QACA,EAAE,QAAQ,IAAI,QAAQ,UAAU,IAAI,SAAS;AAAA,QAC7C,KAAK;AAAA,MACP;AACA,aAAO;AAAA,IACT;AAAA,IAEA,gBAAgB,CAAC,QAAQ;AACvB,YAAM,OAAO,OAAO,eAAe,GAAG;AACtC;AAAA,QACE;AAAA,QACA;AAAA,UACE,QAAQ,IAAI;AAAA,UACZ,WAAW,IAAI;AAAA,UACf,UAAU,IAAI;AAAA,UACd,mBAAmB,IAAI;AAAA,QACzB;AAAA,QACA,KAAK;AAAA,MACP;AACA,aAAO;AAAA,IACT;AAAA;AAAA,IAGA,YAAY,CAAC,QAAQ;AACnB,YAAM,OAAO,OAAO,WAAW,GAAG;AAClC;AAAA,QACE;AAAA,QACA,EAAE,QAAQ,IAAI,QAAQ,UAAU,IAAI,SAAS;AAAA,QAC7C,KAAK;AAAA,MACP;AACA,aAAO;AAAA,IACT;AAAA,IAEA,WAAW,CAAC,QAAQ;AAClB,YAAM,OAAO,OAAO,UAAU,GAAG;AACjC;AAAA,QACE;AAAA,QACA;AAAA,UACE,QAAQ,IAAI;AAAA,UACZ,YAAY,IAAI;AAAA,UAChB,gBAAgB,IAAI;AAAA,UACpB,GAAI,IAAI,wBAAwB,UAAa;AAAA,YAC3C,qBAAqB,IAAI;AAAA,UAC3B;AAAA,QACF;AAAA,QACA,KAAK;AAAA,MACP;AACA,aAAO;AAAA,IACT;AAAA;AAAA,IAGA,4BAA4B,CAAC,QAAQ,OAAO,2BAA2B,GAAG;AAAA,IAC1E,yBAAyB,CAAC,QAAQ,OAAO,wBAAwB,GAAG;AAAA,IACpE,2BAA2B,CAAC,QAAQ,OAAO,0BAA0B,GAAG;AAAA,IACxE,wBAAwB,CAAC,QAAQ,OAAO,uBAAuB,GAAG;AAAA,IAClE,2BAA2B,CAAC,QAAQ,OAAO,0BAA0B,GAAG;AAAA,IACxE,wBAAwB,CAAC,QAAQ,OAAO,uBAAuB,GAAG;AAAA,IAClE,sBAAsB,CAAC,QAAQ,OAAO,qBAAqB,GAAG;AAAA,IAC9D,uBAAuB,CAAC,QAAQ,OAAO,sBAAsB,GAAG;AAAA,EAClE;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,QAAQ,MAAM;AAAA,EAChB;AACF;AAUA,IAAM,iBAAiB,CACrB,MACA,YACuB;AACvB,MAAI,CAAC,WAAW,QAAQ,WAAW,KAAK,MAAM,OAAQ,QAAO;AAE7D,QAAM,QAAQ,oBAAI,IAAoB;AACtC,OAAK,MAAM,QAAQ,CAAC,MAAM,UAAU;AAClC,UAAM,IAAI,KAAK,IAAI,QAAQ,KAAK,CAAW;AAAA,EAC7C,CAAC;AACD,QAAM,QAAQ,CAAC,OAAuB,MAAM,IAAI,EAAE,KAAK;AAEvD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,OAAO,KAAK,MAAM,IAAI,CAAC,UAAU,EAAE,GAAG,MAAM,IAAI,MAAM,KAAK,EAAE,EAAE,EAAE;AAAA,IACjE,iBAAiB,KAAK,gBAAgB;AAAA,MAAI,CAAC,WACzC,OAAO,SAAS,EAAE,GAAG,QAAQ,QAAQ,MAAM,OAAO,MAAM,EAAE,IAAI;AAAA,IAChE;AAAA,IACA,YAAY;AAAA,MACV,GAAG,KAAK;AAAA,MACR,UAAU,MAAM,KAAK,WAAW,QAAQ;AAAA,IAC1C;AAAA,EACF;AACF;AAKA,IAAM,mBAAmB,CACvB,QACA,YACqB;AACrB,QAAM,OAAO,OAAO,WAAW,EAAE,MAAM,QAAQ,MAAM,MAAM,QAAQ,KAAK,CAAC;AACzE,SAAO,QAAQ,SAAS,EAAE,GAAG,MAAM,IAAI,QAAQ,OAAO,IAAI;AAC5D;AAKA,IAAM,aAAa,CACjB,QACA,MACA,UACc;AACd,UAAQ,MAAM,QAAQ;AAAA,IACpB,KAAK;AACH,aAAO;AAAA,QACL;AAAA,QACA,MAAM;AAAA,MACR;AAAA,IACF,KAAK,cAAc;AACjB,YAAM,UAAU,MAAM;AACtB,aAAO,OAAO,WAAW,EAAE,MAAM,SAAS,QAAQ,QAAQ,CAAC;AAAA,IAC7D;AAAA,IACA,KAAK,iBAAiB;AACpB,YAAM,UAAU,MAAM;AACtB,aAAO,OAAO,cAAc,EAAE,MAAM,YAAY,QAAQ,WAAW,CAAC;AAAA,IACtE;AAAA,IACA,KAAK,aAAa;AAChB,YAAM,UAAU,MAAM;AACtB,aAAO,eAAe,OAAO,UAAU,EAAE,KAAK,CAAC,GAAG,QAAQ,OAAO;AAAA,IACnE;AAAA,IACA,KAAK,gBAAgB;AACnB,YAAM,UAAU,MAAM;AACtB,aAAO,OAAO,aAAa;AAAA,QACzB;AAAA,QACA,QAAQ,QAAQ;AAAA,QAChB,YAAY,QAAQ;AAAA,MACtB,CAAC;AAAA,IACH;AAAA,IACA,KAAK,eAAe;AAClB,YAAM,UAAU,MAAM;AACtB,aAAO,OAAO,YAAY;AAAA,QACxB;AAAA,QACA,QAAQ,QAAQ;AAAA,QAChB,UAAU,QAAQ;AAAA,QAClB,UAAU,QAAQ;AAAA,MACpB,CAAC;AAAA,IACH;AAAA,IACA,KAAK,iBAAiB;AACpB,YAAM,UAAU,MAAM;AACtB,aAAO,OAAO,cAAc,EAAE,MAAM,QAAQ,QAAQ,OAAO,CAAC;AAAA,IAC9D;AAAA,IACA,KAAK,cAAc;AACjB,YAAM,UAAU,MAAM;AACtB,aAAO,OAAO,WAAW;AAAA,QACvB;AAAA,QACA,QAAQ,QAAQ;AAAA,QAChB,UAAU,QAAQ;AAAA,MACpB,CAAC;AAAA,IACH;AAAA,IACA,KAAK,aAAa;AAChB,YAAM,UAAU,MAAM;AACtB,aAAO,OAAO,UAAU;AAAA,QACtB;AAAA,QACA,QAAQ,QAAQ;AAAA,QAChB,YAAY,QAAQ;AAAA,QACpB,gBAAgB,QAAQ;AAAA,QACxB,GAAI,QAAQ,wBAAwB,UAAa;AAAA,UAC/C,qBAAqB,QAAQ;AAAA,QAC/B;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IACA,KAAK,eAAe;AAClB,YAAM,UAAU,MAAM;AACtB,aAAO,OAAO,YAAY;AAAA,QACxB;AAAA,QACA,QAAQ,QAAQ;AAAA,QAChB,UAAU,QAAQ;AAAA,MACpB,CAAC;AAAA,IACH;AAAA,IACA,KAAK,qBAAqB;AACxB,YAAM,UAAU,MAAM;AACtB,aAAO,OAAO,kBAAkB;AAAA,QAC9B;AAAA,QACA,QAAQ,QAAQ;AAAA,QAChB,YAAY,QAAQ;AAAA,QACpB,UAAU,QAAQ;AAAA,MACpB,CAAC;AAAA,IACH;AAAA,IACA,KAAK,aAAa;AAChB,YAAM,UAAU,MAAM;AACtB,aAAO,OAAO,UAAU;AAAA,QACtB;AAAA,QACA,QAAQ,QAAQ;AAAA,QAChB,YAAY,QAAQ;AAAA,MACtB,CAAC;AAAA,IACH;AAAA,IACA,KAAK,kBAAkB;AACrB,YAAM,UAAU,MAAM;AACtB,aAAO,OAAO,eAAe;AAAA,QAC3B;AAAA,QACA,QAAQ,QAAQ;AAAA,QAChB,UAAU,QAAQ;AAAA,MACpB,CAAC;AAAA,IACH;AAAA,IACA,KAAK,kBAAkB;AACrB,YAAM,UAAU,MAAM;AACtB,aAAO,OAAO,eAAe;AAAA,QAC3B;AAAA,QACA,QAAQ,QAAQ;AAAA,QAChB,WAAW,QAAQ;AAAA,QACnB,UAAU,QAAQ;AAAA,QAClB,mBAAmB,QAAQ;AAAA,MAC7B,CAAC;AAAA,IACH;AAAA,IACA,KAAK,sBAAsB;AACzB,YAAM,UAAU,MAAM;AACtB,aAAO,OAAO,mBAAmB;AAAA,QAC/B;AAAA,QACA,QAAQ,QAAQ;AAAA,MAClB,CAAC;AAAA,IACH;AAAA,IACA;AACE,YAAM,IAAI;AAAA,QACR,iCAAiC,OAAQ,MAAsB,MAAM,CAAC;AAAA,MACxE;AAAA,EACJ;AACF;AAiBO,IAAM,gBAAgB,CAC3B,QACA,QACc;AACd,MAAI,IAAI,QAAQ,WAAW,GAAG;AAC5B,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AAEA,MAAI,IAAI,YAAY,UAAa,IAAI,UAAU,oBAAoB;AACjE,UAAM,IAAI;AAAA,MACR,mCAAmC,IAAI,OAAO,sBAAsB,kBAAkB;AAAA,IACxF;AAAA,EACF;AAEA,QAAM,aAAa,IAAI,QAAQ,CAAC;AAChC,MAAI,YAAY,WAAW,cAAc;AACvC,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAEA,MAAI,OAAkB;AAAA,IACpB;AAAA,IACA,WAAW;AAAA,EACb;AAEA,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,QAAQ,KAAK;AAC3C,UAAM,QAAQ,IAAI,QAAQ,CAAC;AAC3B,QAAI,CAAC,MAAO;AACZ,WAAO,WAAW,QAAQ,MAAM,KAAK;AAAA,EACvC;AAEA,SAAO;AACT;;;AC5lBO,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;;;ACeO,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,IACA,mBAAAC;AAAA,IACA,kBAAAC;AAAA,IACA,oBAAAC;AAAA,IACA,0BAAAC;AAAA,IACA,kBAAAC;AAAA,IACA,uBAAAC;AAAA,IACA,uBAAAC;AAAA,IACA,2BAAAC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,6BAAAC;AAAA,EACF,IAAI,gBAAgB,MAAM;AAE1B,MAAI,SAAqB;AAAA,IACvB,UAAU,CAAC,YAAYvB,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,IAC/D,YAAY,CAAC,YAAYC,mBAAkB,OAAO;AAAA,IAClD,WAAW,CAAC,YAAYC,kBAAiB,OAAO;AAAA,IAChD,aAAa,CAAC,YAAYC,oBAAmB,OAAO;AAAA,IACpD,mBAAmB,CAAC,YAAYC,0BAAyB,OAAO;AAAA,IAChE,WAAW,CAAC,YAAYC,kBAAiB,OAAO;AAAA,IAChD,gBAAgB,CAAC,YAAYC,uBAAsB,OAAO;AAAA,IAC1D,gBAAgB,CAAC,YAAYC,uBAAsB,OAAO;AAAA,IAC1D,oBAAoB,CAAC,YAAYC,2BAA0B,OAAO;AAAA,IAClE,4BAA4B,CAAC,YAC3B,kCAAkC,OAAO;AAAA,IAC3C,yBAAyB,CAAC,YACxB,+BAA+B,OAAO;AAAA,IACxC,2BAA2B,CAAC,YAC1B,iCAAiC,OAAO;AAAA,IAC1C,wBAAwB,CAAC,YAAY,8BAA8B,OAAO;AAAA,IAC1E,2BAA2B,CAAC,YAC1B,iCAAiC,OAAO;AAAA,IAC1C,wBAAwB,CAAC,YAAY,8BAA8B,OAAO;AAAA,IAC1E,sBAAsB,CAAC,YAAY,4BAA4B,OAAO;AAAA,IACtE,uBAAuB,CAAC,YAAY,6BAA6B,OAAO;AAAA,IACxE,sBAAsB,CAAC,YAAYC,6BAA4B,OAAO;AAAA,EACxE;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","shuffleMethod","ORIGINS_MODE_PREFIX","uuidMethod","shuffleMethod","getBoundingBox","lord","next","uuidMethod","shuffleMethod","sum","advanceToNextLordOrResult","currentPlayer","uuidMethod","shuffleMethod","option","createGameHandler","getModesHandler","getExtraRulesHandler","addPlayersHandler","addExtraRulesHandler","startGameHandler","chooseDominoHandler","placeDominoHandler","discardDominoHandler","getResultHandler","calculateScoreHandler","getValidPlacementsHandler","canPlaceDominoHandler","serializeGameHandler","deserializeGameHandler","getDynastyResultHandler","placeGiantHandler","sendGiantHandler","placeKnightHandler","constructBuildingHandler","useDragonHandler","placeFireTokenHandler","recruitCavemanHandler","skipOptionalActionHandler","calculatePlayerScoreHandler"]}
|