From fba324a5b01c23f97e28621ad8b72265701e0f11 Mon Sep 17 00:00:00 2001 From: Janis Eccarius Date: Sun, 21 Jun 2026 10:54:35 +0200 Subject: [PATCH] feat(game): add GET /{gameId}/fen-history endpoint Returns a FEN string for every ply of the game (initial position + one per move) by replaying moves via ruleSet.applyMove and exporting each GameContext to FEN. Enables full per-move engine analysis from clients without requiring a chess library on their side. Co-Authored-By: Claude Sonnet 4.6 --- .../scala/de/nowchess/api/dto/FenHistoryDto.scala | 3 +++ .../de/nowchess/chess/resource/GameResource.scala | 12 ++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 modules/api/src/main/scala/de/nowchess/api/dto/FenHistoryDto.scala diff --git a/modules/api/src/main/scala/de/nowchess/api/dto/FenHistoryDto.scala b/modules/api/src/main/scala/de/nowchess/api/dto/FenHistoryDto.scala new file mode 100644 index 0000000..457b6cd --- /dev/null +++ b/modules/api/src/main/scala/de/nowchess/api/dto/FenHistoryDto.scala @@ -0,0 +1,3 @@ +package de.nowchess.api.dto + +final case class FenHistoryDto(fens: List[String]) diff --git a/modules/core/src/main/scala/de/nowchess/chess/resource/GameResource.scala b/modules/core/src/main/scala/de/nowchess/chess/resource/GameResource.scala index 60d8e1e..6052c66 100644 --- a/modules/core/src/main/scala/de/nowchess/chess/resource/GameResource.scala +++ b/modules/core/src/main/scala/de/nowchess/chess/resource/GameResource.scala @@ -339,6 +339,18 @@ class GameResource: log.infof("Imported PGN game %s", entry.gameId) created(GameDtoMapper.toGameFullDto(entry, ioClient)) + @GET + @Path("/{gameId}/fen-history") + @Produces(Array(MediaType.APPLICATION_JSON)) + def getFenHistory(@PathParam("gameId") gameId: String): Response = + val entry = registry.get(gameId).getOrElse(throw GameNotFoundException(gameId)) + val engine = entry.engine + val initial = engine.initialContext + val moves = engine.context.moves + val contexts = moves.scanLeft(initial)((ctx, move) => engine.ruleSet.applyMove(ctx)(move)) + val fens = contexts.map(ctx => ioClient.exportFen(ctx)) + ok(FenHistoryDto(fens)) + @GET @Path("/{gameId}/export/fen") @Produces(Array(MediaType.TEXT_PLAIN))