diff --git a/app/game-engine/src/turn/inMemoryTurnProcessor.ts b/app/game-engine/src/turn/inMemoryTurnProcessor.ts index c3c7f06..3cababc 100644 --- a/app/game-engine/src/turn/inMemoryTurnProcessor.ts +++ b/app/game-engine/src/turn/inMemoryTurnProcessor.ts @@ -6,8 +6,16 @@ import type { TurnGeneral } from './types.js'; export interface InMemoryTurnProcessorOptions { tickMinutes?: number; beforeExecuteGeneral?: (general: TurnGeneral) => Promise; + afterExecuteGeneral?: (general: TurnGeneral, result: TurnGeneralExecutionResult) => Promise; } +export type TurnGeneralExecutionResult = { + ok: boolean; + executedAt: Date; + nextTurnAt?: Date; + error?: unknown; +}; + const resolveTickMinutes = (world: InMemoryTurnWorld, override?: number): number => { if (override !== undefined) { return Math.max(1, override); @@ -21,11 +29,13 @@ export class InMemoryTurnProcessor implements TurnProcessor { private readonly world: InMemoryTurnWorld; private readonly tickMinutes: number; private readonly beforeExecuteGeneral?: (general: TurnGeneral) => Promise; + private readonly afterExecuteGeneral?: (general: TurnGeneral, result: TurnGeneralExecutionResult) => Promise; constructor(world: InMemoryTurnWorld, options: InMemoryTurnProcessorOptions = {}) { this.world = world; this.tickMinutes = resolveTickMinutes(world, options.tickMinutes); this.beforeExecuteGeneral = options.beforeExecuteGeneral; + this.afterExecuteGeneral = options.afterExecuteGeneral; } async run(targetTime: Date, budget: TurnRunBudget, checkpoint?: TurnCheckpoint): Promise { @@ -52,7 +62,24 @@ export class InMemoryTurnProcessor implements TurnProcessor { if (this.beforeExecuteGeneral) { await this.beforeExecuteGeneral(general); } - this.world.executeGeneralTurn(general); + let nextTurnAt: Date | undefined; + let executionError: unknown; + try { + nextTurnAt = this.world.executeGeneralTurn(general); + } catch (error) { + executionError = error; + } + if (this.afterExecuteGeneral) { + await this.afterExecuteGeneral(general, { + ok: executionError === undefined, + executedAt, + nextTurnAt, + error: executionError, + }); + } + if (executionError !== undefined) { + throw executionError; + } processedGenerals += 1; nextCheckpoint = { turnTime: executedAt.toISOString(),