diff --git a/src/Chess/Application/Query/GetGameState/GameStateDTO.php b/src/Chess/Application/Query/GetGameState/GameStateDTO.php new file mode 100644 index 0000000..112372c --- /dev/null +++ b/src/Chess/Application/Query/GetGameState/GameStateDTO.php @@ -0,0 +1,19 @@ + $pieces + */ + public function __construct( + public readonly string $gameId, + public readonly string $currentTurn, + public readonly bool $isOver, + public readonly array $pieces, + ) { + } +} diff --git a/src/Chess/Application/Query/GetGameState/GetGameStateHandler.php b/src/Chess/Application/Query/GetGameState/GetGameStateHandler.php new file mode 100644 index 0000000..d575d3d --- /dev/null +++ b/src/Chess/Application/Query/GetGameState/GetGameStateHandler.php @@ -0,0 +1,49 @@ +repository->findById(GameId::fromString($query->gameId)); + + if (null === $game) { + throw new \DomainException(\sprintf('Game "%s" not found.', $query->gameId)); + } + + $pieces = []; + foreach (['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] as $file) { + foreach (range(1, 8) as $rank) { + $square = new Square($file, $rank); + $piece = $game->board()->pieceAt($square); + if (null !== $piece) { + $pieces[$square->toString()] = [ + 'type' => $piece->type()->name, + 'color' => $piece->color()->name, + ]; + } + } + } + + return new GameStateDTO( + gameId: $game->id()->toString(), + currentTurn: $game->currentTurn()->name, + isOver: $game->isOver(), + pieces: $pieces, + ); + } +} diff --git a/src/Chess/Application/Query/GetGameState/GetGameStateQuery.php b/src/Chess/Application/Query/GetGameState/GetGameStateQuery.php new file mode 100644 index 0000000..8d22c41 --- /dev/null +++ b/src/Chess/Application/Query/GetGameState/GetGameStateQuery.php @@ -0,0 +1,13 @@ +game; + } + }; + + $handler = new GetGameStateHandler($repository); + $dto = $handler(new GetGameStateQuery($game->id()->toString())); + + self::assertInstanceOf(GameStateDTO::class, $dto); + self::assertSame($game->id()->toString(), $dto->gameId); + self::assertSame('White', $dto->currentTurn); + self::assertFalse($dto->isOver); + self::assertCount(32, $dto->pieces); + } + + public function testItThrowsWhenGameNotFound(): void + { + $repository = new class implements GameRepositoryInterface { + public function save(Game $game): void + { + } + + public function findById(GameId $id): ?Game + { + return null; + } + }; + + $this->expectException(\DomainException::class); + + $handler = new GetGameStateHandler($repository); + $handler(new GetGameStateQuery('unknown-id')); + } + + public function testPiecesContainCorrectDataForWhiteKing(): void + { + $game = Game::start(); + + $repository = new class($game) implements GameRepositoryInterface { + public function __construct(private readonly Game $game) + { + } + + public function save(Game $game): void + { + } + + public function findById(GameId $id): Game + { + return $this->game; + } + }; + + $handler = new GetGameStateHandler($repository); + $dto = $handler(new GetGameStateQuery($game->id()->toString())); + + self::assertArrayHasKey('e1', $dto->pieces); + self::assertSame('King', $dto->pieces['e1']['type']); + self::assertSame('White', $dto->pieces['e1']['color']); + } +}