feat: I/O json export import, tests should be 100%
Build & Test (NowChessSystems) TeamCity build finished
Build & Test (NowChessSystems) TeamCity build finished
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"metadata": {
|
||||
"event": "Game",
|
||||
"players": {
|
||||
"white": "White Player",
|
||||
"black": "Black Player"
|
||||
},
|
||||
"date": "2026-04-06",
|
||||
"result": "*"
|
||||
},
|
||||
"gameState": {
|
||||
"board": [{"square": "g8", "color": "Black", "piece": "Knight"}, {"square": "d8", "color": "Black", "piece": "Queen"}, {"square": "f8", "color": "Black", "piece": "Bishop"}, {"square": "b2", "color": "White", "piece": "Pawn"}, {"square": "c1", "color": "White", "piece": "Bishop"}, {"square": "c7", "color": "Black", "piece": "Pawn"}, {"square": "f7", "color": "Black", "piece": "Pawn"}, {"square": "b7", "color": "Black", "piece": "Pawn"}, {"square": "b1", "color": "White", "piece": "Knight"}, {"square": "h8", "color": "Black", "piece": "Rook"}, {"square": "a1", "color": "White", "piece": "Rook"}, {"square": "g2", "color": "White", "piece": "Pawn"}, {"square": "e1", "color": "White", "piece": "King"}, {"square": "c2", "color": "White", "piece": "Pawn"}, {"square": "h2", "color": "White", "piece": "Pawn"}, {"square": "a8", "color": "Black", "piece": "Rook"}, {"square": "f1", "color": "White", "piece": "Bishop"}, {"square": "d6", "color": "Black", "piece": "Pawn"}, {"square": "a2", "color": "White", "piece": "Pawn"}, {"square": "d1", "color": "White", "piece": "Queen"}, {"square": "e2", "color": "White", "piece": "Pawn"}, {"square": "c8", "color": "Black", "piece": "Bishop"}, {"square": "a7", "color": "Black", "piece": "Pawn"}, {"square": "b8", "color": "Black", "piece": "Knight"}, {"square": "d2", "color": "White", "piece": "Pawn"}, {"square": "e8", "color": "Black", "piece": "King"}, {"square": "f4", "color": "White", "piece": "Pawn"}, {"square": "g7", "color": "Black", "piece": "Pawn"}, {"square": "h7", "color": "Black", "piece": "Pawn"}, {"square": "e7", "color": "Black", "piece": "Pawn"}, {"square": "h1", "color": "White", "piece": "Rook"}, {"square": "g1", "color": "White", "piece": "Knight"}],
|
||||
"turn": "White",
|
||||
"castlingRights": {
|
||||
"whiteKingSide": true,
|
||||
"whiteQueenSide": true,
|
||||
"blackKingSide": true,
|
||||
"blackQueenSide": true
|
||||
},
|
||||
"enPassantSquare": null,
|
||||
"halfMoveClock": 0
|
||||
},
|
||||
"moveHistory": "[Event \"?\"]\n[White \"?\"]\n[Black \"?\"]\n[Result \"*\"]\n\n1. f4 d6 *",
|
||||
"moves": [
|
||||
{
|
||||
"from": "f2",
|
||||
"to": "f4",
|
||||
"type": {"type": "normal", "isCapture": false}
|
||||
},
|
||||
{
|
||||
"from": "d7",
|
||||
"to": "d6",
|
||||
"type": {"type": "normal", "isCapture": false}
|
||||
}
|
||||
],
|
||||
"capturedPieces": {
|
||||
"byWhite": ["Pawn"],
|
||||
"byBlack": ["Pawn"]
|
||||
},
|
||||
"timestamp": "2026-04-06T11:39:00.746137480Z[UTC]"
|
||||
}
|
||||
@@ -16,7 +16,11 @@ import de.nowchess.chess.command.{MoveCommand, MoveResult}
|
||||
import de.nowchess.chess.engine.GameEngine
|
||||
import de.nowchess.io.fen.{FenExporter, FenParser}
|
||||
import de.nowchess.io.pgn.{PgnExporter, PgnParser}
|
||||
import de.nowchess.io.{GameContextExport, GameContextImport}
|
||||
import de.nowchess.io.json.{JsonExporter, JsonParser}
|
||||
import de.nowchess.io.{GameContextExport, GameContextImport, GameFileService, FileSystemGameService}
|
||||
import java.nio.file.Paths
|
||||
import scalafx.stage.FileChooser
|
||||
import scalafx.stage.FileChooser.ExtensionFilter
|
||||
|
||||
/** ScalaFX chess board view that displays the game state.
|
||||
* Uses chess sprites and color palette.
|
||||
@@ -124,6 +128,22 @@ class ChessBoardView(val stage: Stage, private val engine: GameEngine) extends B
|
||||
style = "-fx-background-radius: 8; -fx-background-color: #B9DAC4;"
|
||||
}
|
||||
)
|
||||
},
|
||||
new HBox {
|
||||
spacing = 10
|
||||
alignment = Pos.Center
|
||||
children = Seq(
|
||||
new Button("JSON Export") {
|
||||
font = Font.font(comicSansFontFamily, 12)
|
||||
onAction = _ => doJsonExport()
|
||||
style = "-fx-background-radius: 8; -fx-background-color: #B9C4DA;"
|
||||
},
|
||||
new Button("JSON Import") {
|
||||
font = Font.font(comicSansFontFamily, 12)
|
||||
onAction = _ => doJsonImport()
|
||||
style = "-fx-background-radius: 8; -fx-background-color: #C4B9DA;"
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -289,6 +309,45 @@ class ChessBoardView(val stage: Stage, private val engine: GameEngine) extends B
|
||||
private def doPgnImport(): Unit =
|
||||
doImport(PgnParser, "PGN")
|
||||
|
||||
private def doJsonExport(): Unit =
|
||||
val fileChooser = new FileChooser {
|
||||
title = "Export Game as JSON"
|
||||
initialFileName = "chess_game.json"
|
||||
extensionFilters.add(new ExtensionFilter("JSON files (*.json)", "*.json"))
|
||||
extensionFilters.add(new ExtensionFilter("All files", "*.*"))
|
||||
}
|
||||
|
||||
val selectedFile = fileChooser.showSaveDialog(stage)
|
||||
if selectedFile != null then
|
||||
val result = FileSystemGameService.saveGameToFile(
|
||||
engine.context,
|
||||
selectedFile.toPath,
|
||||
JsonExporter
|
||||
)
|
||||
result match
|
||||
case Right(_) => showMessage(s"✓ Game saved to: ${selectedFile.getName}")
|
||||
case Left(err) => showMessage(s"⚠️ Error saving file: $err")
|
||||
|
||||
private def doJsonImport(): Unit =
|
||||
val fileChooser = new FileChooser {
|
||||
title = "Import Game from JSON"
|
||||
extensionFilters.add(new ExtensionFilter("JSON files (*.json)", "*.json"))
|
||||
extensionFilters.add(new ExtensionFilter("All files", "*.*"))
|
||||
}
|
||||
|
||||
val selectedFile = fileChooser.showOpenDialog(stage)
|
||||
if selectedFile != null then
|
||||
val result = FileSystemGameService.loadGameFromFile(
|
||||
selectedFile.toPath,
|
||||
JsonParser
|
||||
)
|
||||
result match
|
||||
case Right(gameContext) =>
|
||||
engine.loadPosition(gameContext)
|
||||
showMessage(s"✓ Game loaded from: ${selectedFile.getName}")
|
||||
case Left(err) =>
|
||||
showMessage(s"⚠️ Error: $err")
|
||||
|
||||
private def doExport(exporter: GameContextExport, formatName: String): Unit = {
|
||||
val exported = exporter.exportGameContext(engine.context)
|
||||
showCopyDialog(s"$formatName Export", exported)
|
||||
|
||||
Reference in New Issue
Block a user