diff --git a/schach/pom.xml b/schach/pom.xml index ab9e214..a120fc0 100644 --- a/schach/pom.xml +++ b/schach/pom.xml @@ -33,80 +33,56 @@ chesslib 1.3.4 + - org.junit.jupiter - junit-jupiter - 5.10.2 - test - - - - org.mockito - mockito-core - 5.11.0 - test - + org.junit.jupiter + junit-jupiter + 5.10.2 + test + - - - - org.apache.maven.plugins - maven-pmd-plugin - 3.21.0 - - - rulesets/java/quickstart.xml - - - - - verify - - check - - - - - - - maven-clean-plugin - 3.4.0 - - - maven-site-plugin - 3.12.1 - - - maven-project-info-reports-plugin - 3.6.1 - - - maven-resources-plugin - 3.3.1 - - - maven-compiler-plugin - 3.13.0 - - - maven-surefire-plugin - 3.3.0 - - - maven-jar-plugin - 3.4.2 - - - maven-install-plugin - 3.1.2 - - - maven-deploy-plugin - 3.1.2 - - + + + + maven-clean-plugin + 3.4.0 + + + maven-site-plugin + 3.12.1 + + + maven-project-info-reports-plugin + 3.6.1 + + + maven-resources-plugin + 3.3.1 + + + maven-compiler-plugin + 3.13.0 + + + maven-surefire-plugin + 3.3.0 + + + maven-jar-plugin + 3.4.2 + + + maven-install-plugin + 3.1.2 + + + maven-deploy-plugin + 3.1.2 + + + @@ -116,4 +92,4 @@ - + \ No newline at end of file diff --git a/schach/src/main/java/de/hs_mannheim/informatik/chess/model/ChessEngine.java b/schach/src/main/java/de/hs_mannheim/informatik/chess/model/ChessEngine.java index 91f3e98..c78fde2 100644 --- a/schach/src/main/java/de/hs_mannheim/informatik/chess/model/ChessEngine.java +++ b/schach/src/main/java/de/hs_mannheim/informatik/chess/model/ChessEngine.java @@ -1,11 +1,10 @@ package de.hs_mannheim.informatik.chess.model; -import java.io.BufferedReader; -import java.io.FileReader; + import java.io.IOException; -import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.time.LocalDate; import java.util.ArrayList; import java.util.List; import java.util.logging.ConsoleHandler; @@ -21,10 +20,8 @@ import com.github.bhlangonijr.chesslib.move.Move; import com.github.bhlangonijr.chesslib.pgn.PgnHolder; import com.github.bhlangonijr.chesslib.game.*; import com.github.bhlangonijr.chesslib.move.MoveList; -import java.time.LocalDate; import com.github.bhlangonijr.chesslib.Side; - public class ChessEngine { private Board board; private List moves = new ArrayList<>(); @@ -32,457 +29,496 @@ public class ChessEngine { private static final Logger logger = Logger.getLogger(ChessEngine.class.getName()); private int quicksaveWhiteTimeLeft = -1; private int quicksaveBlackTimeLeft = -1; - - private int currentMoveIndex = 0; private Timer whiteTimer; private Timer blackTimer; private final GameMode mode; - private String quicksaveFen = null; private List quicksaveMoves = null; private int quicksaveMoveIndex = 0; - private Opening detectedOpening = null; - + public ChessEngine() { - this.mode = null; - logging(); - board = new Board(); - } - - public ChessEngine(GameMode mode) { - this.mode = mode; - whiteTimer = new Timer(mode.minutes, mode.seconds); - blackTimer = new Timer(mode.minutes, mode.seconds); + this.mode = null; logging(); - board = new Board(); - } - public boolean move(MoveDTO move) { - String from = "" + (char)('A' + move.getFromCol()) + (8 - move.getFromRow()); - String to = "" + (char)('A' + move.getToCol()) + (8 - move.getToRow()); - Move libMove = new Move(Square.valueOf(from), Square.valueOf(to)); - if (board.legalMoves().contains(libMove)) { - board.doMove(libMove); + board = new Board(); + } - // Replay? Dann abschneiden - if (currentMoveIndex < moves.size()) { - logger.info("Replay-Modus: Züge nach " + currentMoveIndex + " werden entfernt."); - moves = new ArrayList<>(moves.subList(0, currentMoveIndex)); - } - moves.add(libMove); - currentMoveIndex++; - logger.info("Zug erfolgreich durchgeführt: " + libMove); + public ChessEngine(GameMode mode) { + this.mode = mode; + whiteTimer = new Timer(mode.minutes, mode.seconds); + blackTimer = new Timer(mode.minutes, mode.seconds); + logging(); + board = new Board(); + } - // Opening-Erkennung nach jedem erfolgreichen Zug - String playedMovesUci = movesToUciString(moves); - detectedOpening = Opening.detect(playedMovesUci); + public boolean move(MoveDTO move) { + String from = "" + (char) ('A' + move.getFromCol()) + (8 - move.getFromRow()); + String to = "" + (char) ('A' + move.getToCol()) + (8 - move.getToRow()); + Move libMove = new Move(Square.valueOf(from), Square.valueOf(to)); + if (board.legalMoves().contains(libMove)) { + board.doMove(libMove); - if (detectedOpening != null) { - logger.info("Aktuelles Opening erkannt: " + detectedOpening.getEco() + " - " + detectedOpening.getName()); - // Optional: Speichere das Opening in ein Feld, falls benötigt - } - return true; - } - logger.warning("Ungültiger Zug: " + libMove); - return false; - } + if (currentMoveIndex < moves.size()) { + if (logger.isLoggable(Level.INFO)) { + logger.info("Replay-Modus: Züge nach " + currentMoveIndex + " werden entfernt."); + } + moves = new ArrayList<>(moves.subList(0, currentMoveIndex)); + } + moves.add(libMove); + currentMoveIndex++; + if (logger.isLoggable(Level.INFO)) { + logger.info("Zug erfolgreich durchgeführt: " + libMove); + } - public String getOpeningName() { - if (detectedOpening != null) { - return detectedOpening.getEco() + " - " + detectedOpening.getName(); - } else { - return "unbekannt"; - } - } - - private String movesToUciString(List moves) { - StringBuilder sb = new StringBuilder(); - for (Move m : moves) { - sb.append(m.toString()).append(" "); - } - return sb.toString().trim(); - } - - public List getLegalDestinations(String from) { - logger.info("Hole legale Züge von: " + from); - List destinations = new ArrayList<>(); - try { - Square fromSq = Square.valueOf(from.toUpperCase()); - for (Move move : board.legalMoves()) { - if (move.getFrom().equals(fromSq)) { - int fromRow = 8 - fromSq.getRank().ordinal() - 1; - int fromCol = fromSq.getFile().ordinal(); - int toRow = 8 - move.getTo().getRank().ordinal() - 1; - int toCol = move.getTo().getFile().ordinal(); - destinations.add(new MoveDTO(fromRow, fromCol, toRow, toCol)); - } - } - logger.info("Es wurden " + destinations.size() + " Ziele gefunden."); - } catch (Exception e) { - logger.severe("Fehler beim Holen der legalen Ziele: " + e.getMessage()); - } - return destinations; - } - - public List getMoveListStringsGrouped() { - logger.info("Gruppiere Züge für Anzeige."); - List result = new ArrayList<>(); - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < moves.size(); i++) { - if (i % 2 == 0) sb.append((i/2 + 1) + ". "); - sb.append(moves.get(i).toString()).append(" "); - if (i % 2 == 1 || i == moves.size() - 1) { - result.add(sb.toString().trim()); - sb = new StringBuilder(); - } - } - return result; - } - - public void quicksave() { - this.quicksaveFen = board.getFen(); - this.quicksaveMoves = new ArrayList<>(moves); - this.quicksaveMoveIndex = currentMoveIndex; - if (whiteTimer != null) quicksaveWhiteTimeLeft = whiteTimer.getSecondsLeft(); - if (blackTimer != null) quicksaveBlackTimeLeft = blackTimer.getSecondsLeft(); - } - public boolean quickload() { - if (quicksaveFen == null) return false; - board = new Board(); - board.loadFromFen(quicksaveFen); - moves = new ArrayList<>(quicksaveMoves); - currentMoveIndex = quicksaveMoveIndex; - if (whiteTimer != null && quicksaveWhiteTimeLeft != -1) whiteTimer.setSecondsLeft(quicksaveWhiteTimeLeft); - if (blackTimer != null && quicksaveBlackTimeLeft != -1) blackTimer.setSecondsLeft(quicksaveBlackTimeLeft); - return true; - } - - public void clearQuicksave() { - quicksaveFen = null; - quicksaveMoves = null; - quicksaveMoveIndex = 0; - } + String playedMovesUci = movesToUciString(moves); + detectedOpening = Opening.detect(playedMovesUci); - - public PieceDTO getPieceAt(String square) { - logger.info("Hole Figur an Feld: " + square); - Piece piece = board.getPiece(Square.valueOf(square.toUpperCase())); - return convertPieceToDTO(piece); - } - - public boolean moveWithPromotion(MoveDTO move, String promotionPiece) { - String from = "" + (char)('A' + move.getFromCol()) + (8 - move.getFromRow()); - String to = "" + (char)('A' + move.getToCol()) + (8 - move.getToRow()); + if (detectedOpening != null && logger.isLoggable(Level.INFO)) { + logger.info("Aktuelles Opening erkannt: " + detectedOpening.getEco() + " - " + detectedOpening.getName()); + } + return true; + } + if (logger.isLoggable(Level.WARNING)) { + logger.warning("Ungültiger Zug: " + libMove); + } + return false; + } - // Die Farbe bestimmen! - boolean isWhite = (8 - move.getFromRow()) < (8 - move.getToRow()); - Piece promotion; - switch (promotionPiece) { - case "ROOK": promotion = isWhite ? Piece.WHITE_ROOK : Piece.BLACK_ROOK; break; - case "KNIGHT": promotion = isWhite ? Piece.WHITE_KNIGHT : Piece.BLACK_KNIGHT; break; - case "BISHOP": promotion = isWhite ? Piece.WHITE_BISHOP : Piece.BLACK_BISHOP; break; - default: promotion = isWhite ? Piece.WHITE_QUEEN : Piece.BLACK_QUEEN; - } + public String getOpeningName() { + if (detectedOpening != null) { + return detectedOpening.getEco() + " - " + detectedOpening.getName(); + } else { + return "unbekannt"; + } + } - Move libMove = new Move(Square.valueOf(from), Square.valueOf(to), promotion); + private String movesToUciString(List moves) { + StringBuilder sb = new StringBuilder(); + for (Move m : moves) { + sb.append(m.toString()).append(" "); + } + return sb.toString().trim(); + } - if (board.legalMoves().contains(libMove)) { - board.doMove(libMove); + public List getLegalDestinations(String from) { + if (logger.isLoggable(Level.INFO)) { + logger.info("Hole legale Züge von: " + from); + } + List destinations = new ArrayList<>(); + try { + Square fromSq = Square.valueOf(from.toUpperCase(java.util.Locale.ROOT)); + for (Move move : board.legalMoves()) { + if (move.getFrom().equals(fromSq)) { + int fromRow = 8 - fromSq.getRank().ordinal() - 1; + int fromCol = fromSq.getFile().ordinal(); + int toRow = 8 - move.getTo().getRank().ordinal() - 1; + int toCol = move.getTo().getFile().ordinal(); + destinations.add(new MoveDTO(fromRow, fromCol, toRow, toCol)); + } + } + if (logger.isLoggable(Level.INFO)) { + logger.info("Es wurden " + destinations.size() + " Ziele gefunden."); + } + } catch (Exception e) { + if (logger.isLoggable(Level.SEVERE)) { + logger.severe("Fehler beim Holen der legalen Ziele: " + e.getMessage()); + } + } + return destinations; + } - if (currentMoveIndex < moves.size()) { - moves = new ArrayList<>(moves.subList(0, currentMoveIndex)); - } - moves.add(libMove); - currentMoveIndex++; - logger.info("Promotionszug durchgeführt: " + libMove); - return true; - } - logger.warning("Ungültiger Promotionszug: " + libMove); - return false; - } - - public BoardDTO getBoardAsDTO() { - logger.info("Erstelle DTO-Abbild des Boards"); - PieceDTO[][] dtoBoard = new PieceDTO[8][8]; - for (int rank = 8; rank >= 1; rank--) { - for (int file = 0; file < 8; file++) { - Square square = Square.valueOf("" + (char)('A' + file) + rank); - Piece piece = board.getPiece(square); - dtoBoard[8-rank][file] = convertPieceToDTO(piece); - } - } - return new BoardDTO(dtoBoard); - } - - private String pieceToUnicode(Piece piece) { - switch (piece) { - case WHITE_KING: return "♔"; - case WHITE_QUEEN: return "♕"; - case WHITE_ROOK: return "♖"; - case WHITE_BISHOP: return "♗"; - case WHITE_KNIGHT: return "♘"; - case WHITE_PAWN: return "♙"; - case BLACK_KING: return "♚"; - case BLACK_QUEEN: return "♛"; - case BLACK_ROOK: return "♜"; - case BLACK_BISHOP: return "♝"; - case BLACK_KNIGHT: return "♞"; - case BLACK_PAWN: return "♟"; - default: return " "; - } - } - - public void setPositionToMoveIndex(int idx) { - logger.info("Setze Board auf Zug-Index: " + idx); - board = new Board(); - board.loadFromFen(initialFen); // Statt new Board() -> initialFen! - for (int i = 0; i < idx; i++) { - board.doMove(moves.get(i)); - } - currentMoveIndex = idx; - - String playedMovesUci = movesToUciString(moves.subList(0, idx)); - detectedOpening = Opening.detect(playedMovesUci); - } - public int getCurrentMoveIndex() { - logger.info("Hole aktuellen Zug-Index: " + currentMoveIndex); - return currentMoveIndex; - } - - public int getMoveListSize() { - logger.info("Hole Anzahl gespielter Züge: " + moves.size()); - return moves.size(); - } - - private PieceDTO convertPieceToDTO(Piece piece) { - if (piece == null || piece.equals(Piece.NONE)) return null; - String color = piece.name().startsWith("WHITE") ? "WHITE" : "BLACK"; - String type = piece.name().substring(piece.name().indexOf('_') + 1); // "PAWN", "KING"... - String symbol = pieceToUnicode(piece); - return new PieceDTO(type, color, symbol); - } - - public void setPositionFromFEN(String fen) { - board.loadFromFen(fen); - initialFen = fen; - } + public List getMoveListStringsGrouped() { + if (logger.isLoggable(Level.INFO)) { + logger.info("Gruppiere Züge für Anzeige."); + } + List result = new ArrayList<>(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < moves.size(); i++) { + if (i % 2 == 0) { + sb.append((i / 2 + 1)).append(". "); + } + sb.append(moves.get(i).toString()).append(" "); + if (i % 2 == 1 || i == moves.size() - 1) { + result.add(sb.toString().trim()); + sb = new StringBuilder(); + } + } + return result; + } - - public boolean isMated() { - boolean mated = board.isMated(); - logger.info("isMated() = " + mated); - return mated; - } - - public boolean isStalemate() { - boolean stale = board.isStaleMate(); - logger.info("isStalemate() = " + stale); - return stale; - } - - public boolean isDraw() { - boolean draw = board.isDraw(); - logger.info("isDraw() = " + draw); - return draw; - } - - public String getCurrentPlayer() { - String player = board.getSideToMove().toString(); - logger.info("Am Zug: " + player); - return player; - } - - public void logging() { - - // Eigener Handler nur für diese Klasse - ConsoleHandler handler = new ConsoleHandler(); - handler.setLevel(Level.ALL); - handler.setFormatter(new SimpleFormatter() { - @Override - public synchronized String format(LogRecord lr) { - return String.format("[%s] %s%n%n", lr.getLevel().getLocalizedName(), lr.getMessage()); - } - }); - logger.setUseParentHandlers(false); - logger.addHandler(handler); - - logger.info("ChessEngine wurde initialisiert."); - } - - public List loadGamesFromPgn(String path) throws IOException { + public void quicksave() { + this.quicksaveFen = board.getFen(); + this.quicksaveMoves = new ArrayList<>(moves); + this.quicksaveMoveIndex = currentMoveIndex; + if (whiteTimer != null) { + quicksaveWhiteTimeLeft = whiteTimer.getSecondsLeft(); + } + if (blackTimer != null) { + quicksaveBlackTimeLeft = blackTimer.getSecondsLeft(); + } + } - PgnHolder pgnHolder = new PgnHolder(path); - try { + public boolean quickload() { + if (quicksaveFen == null) { + return false; + } + board = new Board(); + board.loadFromFen(quicksaveFen); + moves = new ArrayList<>(quicksaveMoves); + currentMoveIndex = quicksaveMoveIndex; + if (whiteTimer != null && quicksaveWhiteTimeLeft != -1) { + whiteTimer.setSecondsLeft(quicksaveWhiteTimeLeft); + } + if (blackTimer != null && quicksaveBlackTimeLeft != -1) { + blackTimer.setSecondsLeft(quicksaveBlackTimeLeft); + } + return true; + } + + public void clearQuicksave() { + quicksaveFen = null; + quicksaveMoves = null; + quicksaveMoveIndex = 0; + } + + public PieceDTO getPieceAt(String square) { + if (logger.isLoggable(Level.INFO)) { + logger.info("Hole Figur an Feld: " + square); + } + Piece piece = board.getPiece(Square.valueOf(square.toUpperCase(java.util.Locale.ROOT))); + return convertPieceToDTO(piece); + } + + public boolean moveWithPromotion(MoveDTO move, String promotionPiece) { + String from = "" + (char) ('A' + move.getFromCol()) + (8 - move.getFromRow()); + String to = "" + (char) ('A' + move.getToCol()) + (8 - move.getToRow()); + + boolean isWhite = (8 - move.getFromRow()) < (8 - move.getToRow()); + Piece promotion; + switch (promotionPiece) { + case "ROOK": + promotion = isWhite ? Piece.WHITE_ROOK : Piece.BLACK_ROOK; + break; + case "KNIGHT": + promotion = isWhite ? Piece.WHITE_KNIGHT : Piece.BLACK_KNIGHT; + break; + case "BISHOP": + promotion = isWhite ? Piece.WHITE_BISHOP : Piece.BLACK_BISHOP; + break; + default: + promotion = isWhite ? Piece.WHITE_QUEEN : Piece.BLACK_QUEEN; + break; + } + + Move libMove = new Move(Square.valueOf(from), Square.valueOf(to), promotion); + + if (board.legalMoves().contains(libMove)) { + board.doMove(libMove); + + if (currentMoveIndex < moves.size()) { + moves = new ArrayList<>(moves.subList(0, currentMoveIndex)); + } + moves.add(libMove); + currentMoveIndex++; + if (logger.isLoggable(Level.INFO)) { + logger.info("Promotionszug durchgeführt: " + libMove); + } + return true; + } + if (logger.isLoggable(Level.WARNING)) { + logger.warning("Ungültiger Promotionszug: " + libMove); + } + return false; + } + + public BoardDTO getBoardAsDTO() { + if (logger.isLoggable(Level.INFO)) { + logger.info("Erstelle DTO-Abbild des Boards"); + } + PieceDTO[][] dtoBoard = new PieceDTO[8][8]; + for (int rank = 8; rank >= 1; rank--) { + for (int file = 0; file < 8; file++) { + Square square = Square.valueOf("" + (char) ('A' + file) + rank); + Piece piece = board.getPiece(square); + dtoBoard[8 - rank][file] = convertPieceToDTO(piece); + } + } + return new BoardDTO(dtoBoard); + } + + private String pieceToUnicode(Piece piece) { + switch (piece) { + case WHITE_KING: + return "♔"; + case WHITE_QUEEN: + return "♕"; + case WHITE_ROOK: + return "♖"; + case WHITE_BISHOP: + return "♗"; + case WHITE_KNIGHT: + return "♘"; + case WHITE_PAWN: + return "♙"; + case BLACK_KING: + return "♚"; + case BLACK_QUEEN: + return "♛"; + case BLACK_ROOK: + return "♜"; + case BLACK_BISHOP: + return "♝"; + case BLACK_KNIGHT: + return "♞"; + case BLACK_PAWN: + return "♟"; + default: + return " "; + } + } + + public void setPositionToMoveIndex(int idx) { + if (logger.isLoggable(Level.INFO)) { + logger.info("Setze Board auf Zug-Index: " + idx); + } + board = new Board(); + board.loadFromFen(initialFen); + for (int i = 0; i < idx; i++) { + board.doMove(moves.get(i)); + } + currentMoveIndex = idx; + + String playedMovesUci = movesToUciString(moves.subList(0, idx)); + detectedOpening = Opening.detect(playedMovesUci); + } + + public int getCurrentMoveIndex() { + if (logger.isLoggable(Level.INFO)) { + logger.info("Hole aktuellen Zug-Index: " + currentMoveIndex); + } + return currentMoveIndex; + } + + public int getMoveListSize() { + if (logger.isLoggable(Level.INFO)) { + logger.info("Hole Anzahl gespielter Züge: " + moves.size()); + } + return moves.size(); + } + + private PieceDTO convertPieceToDTO(Piece piece) { + if (piece == null || piece.equals(Piece.NONE)) { + return null; + } + String color = piece.name().startsWith("WHITE") ? "WHITE" : "BLACK"; + String type = piece.name().substring(piece.name().indexOf('_') + 1); + String symbol = pieceToUnicode(piece); + return new PieceDTO(type, color, symbol); + } + + public void setPositionFromFEN(String fen) { + board.loadFromFen(fen); + initialFen = fen; + } + + public boolean isMated() { + boolean mated = board.isMated(); + if (logger.isLoggable(Level.INFO)) { + logger.info("isMated() = " + mated); + } + return mated; + } + + public boolean isStalemate() { + boolean stale = board.isStaleMate(); + if (logger.isLoggable(Level.INFO)) { + logger.info("isStalemate() = " + stale); + } + return stale; + } + + public boolean isDraw() { + boolean draw = board.isDraw(); + if (logger.isLoggable(Level.INFO)) { + logger.info("isDraw() = " + draw); + } + return draw; + } + + public String getCurrentPlayer() { + String player = board.getSideToMove().toString(); + if (logger.isLoggable(Level.INFO)) { + logger.info("Am Zug: " + player); + } + return player; + } + + public void logging() { + ConsoleHandler handler = new ConsoleHandler(); + handler.setLevel(Level.ALL); + handler.setFormatter(new SimpleFormatter() { + @Override + public synchronized String format(LogRecord lr) { + return String.format("[%s] %s%n%n", lr.getLevel().getLocalizedName(), lr.getMessage()); + } + }); + logger.setUseParentHandlers(false); + logger.addHandler(handler); + + if (logger.isLoggable(Level.INFO)) { + logger.info("ChessEngine wurde initialisiert."); + } + } + + public List loadGamesFromPgn(String path) throws IOException { + PgnHolder pgnHolder = new PgnHolder(path); + try { pgnHolder.loadPgn(); } catch (Exception e) { e.printStackTrace(); - } - List games = pgnHolder.getGames(); - return games; - } - - public void initTimers(int min, int sec) { - if (whiteTimer == null) { - whiteTimer = new Timer(min, sec); - } else if (quicksaveWhiteTimeLeft != -1) { - whiteTimer = new Timer(min, sec); - whiteTimer.setSecondsLeft(quicksaveWhiteTimeLeft); - } else { - whiteTimer = new Timer(min, sec); - } - - if (blackTimer == null) { - blackTimer = new Timer(min, sec); - } else if (quicksaveBlackTimeLeft != -1) { - blackTimer = new Timer(min, sec); - blackTimer.setSecondsLeft(quicksaveBlackTimeLeft); - } else { - blackTimer = new Timer(min, sec); - } - } - - public void saveAsPgn(Game game, String path, String dateiname) { - // Sicher alle Strings holen (nie null) - String event = safe(game.getRound().getEvent().getName()); - String site = safe(game.getRound().getEvent().getSite()); - String round = "" + game.getRound().getNumber(); - // Datum für PGN-Format (YYYY.MM.DD) - String date = safe(game.getRound().getEvent().getStartDate()).replace("-", "."); - String wName = safe(game.getWhitePlayer().getName()); - String bName = safe(game.getBlackPlayer().getName()); - String result = safe(game.getResult().getDescription()); - - // PGN-Header zusammenbauen - StringBuilder header = new StringBuilder(); - header.append("[Event \"" + event + "\"]\n"); - header.append("[Site \"" + site + "\"]\n"); - header.append("[Date \"" + date + "\"]\n"); - header.append("[Round \"" + round + "\"]\n"); - header.append("[White \"" + wName + "\"]\n"); - header.append("[Black \"" + bName + "\"]\n"); - header.append("[Result \"" + result + "\"]\n\n"); - - // Züge als SAN holen - StringBuilder moves = new StringBuilder(); - String[] sanArray = game.getHalfMoves().toSanArray(); - - for (int i = 0; i < sanArray.length; i++) { - if (i % 2 == 0) { - moves.append((i / 2 + 1)).append(". "); - } - moves.append(sanArray[i]).append(" "); - // Optional: Zeilenumbruch für Lesbarkeit - // if (i > 0 && i % 8 == 0) moves.append("\n"); - } - moves.append(result); // Ergebnis am Ende! - - String file = header + moves.toString(); - - // Datei schreiben - try { - Files.writeString(Path.of(path, dateiname), file, StandardCharsets.UTF_8); - } catch (IOException e) { - e.printStackTrace(); - } - } - - // Hilfsfunktion für Null-Sicherheit - private String safe(String s) { - return s == null ? "?" : s; - } - - public Game getCurrentGame() { - return getCurrentGame(this.board, this.moves, this.currentMoveIndex); - } - - public Game getCurrentGame(Board board, java.util.List moves, int currentMoveIndex) { - // Event und Turnierdaten setzen - Event event = new Event(); - event.setName("Generated Game"); - event.setSite("Local"); - event.setStartDate(LocalDate.now().toString()); // Format: yyyy-MM-dd - - // Runde anlegen - Round round = new Round(event); - round.setNumber(1); - - // Spiel initialisieren - Game game = new Game("1", round); // "1" ist die Game-ID - - // Spieler setzen (deine MyPlayer-Klasse) - game.setWhitePlayer(new MyPlayer("White")); - game.setBlackPlayer(new MyPlayer("Black")); - - // Ergebnis setzen - if (board.isMated()) { - game.setResult(board.getSideToMove() == Side.WHITE ? GameResult.BLACK_WON : GameResult.WHITE_WON); - } else if (board.isStaleMate() || board.isDraw()) { - game.setResult(GameResult.DRAW); - } else { - game.setResult(GameResult.ONGOING); - } - - // Züge übernehmen - MoveList moveList = new MoveList(); - for (Move move : moves) { - moveList.add(move); - } - game.setHalfMoves(moveList); - - // Position auf aktuellen Zug setzen (letzter gespielter Halbzug) - if (currentMoveIndex > 0 && currentMoveIndex <= moveList.size()) { - game.setPosition(currentMoveIndex - 1); - } else { - game.setPosition(moveList.size() - 1); - } - - // FEN setzen: JETZT das aktuelle Board-FEN verwenden! - game.setBoard(new Board()); - game.getBoard().loadFromFen(board.getFen()); - - return game; - } - - - public void undoLastMove() { - if (currentMoveIndex > 0 && moves.size() > 0) { - board.undoMove(); // 1. Brett zurücksetzen - moves.remove(currentMoveIndex - 1); // 2. Zug aus Move-Liste löschen - currentMoveIndex--; // 3. Index anpassen - - // 4. Erkennung Opening neu machen! - String playedMovesUci = movesToUciString(moves.subList(0, currentMoveIndex)); - detectedOpening = Opening.detect(playedMovesUci); - } - } - - - public void loadMoves(List moveList) { - board = new Board(); // Neues leeres Brett - moves.clear(); - currentMoveIndex = 0; - - for (Move move : moveList) { - board.doMove(move); - moves.add(move); - currentMoveIndex++; - } - - } - - public Timer getWhiteTimer() { return whiteTimer; } - - public Timer getBlackTimer() { return blackTimer; } - - - public GameMode getGameMode() { - // TODO Auto-generated method stub - return mode; + } + return pgnHolder.getGames(); } - + public void initTimers(int min, int sec) { + if (whiteTimer == null) { + whiteTimer = new Timer(min, sec); + } else if (quicksaveWhiteTimeLeft != -1) { + whiteTimer = new Timer(min, sec); + whiteTimer.setSecondsLeft(quicksaveWhiteTimeLeft); + } else { + whiteTimer = new Timer(min, sec); + } + + if (blackTimer == null) { + blackTimer = new Timer(min, sec); + } else if (quicksaveBlackTimeLeft != -1) { + blackTimer = new Timer(min, sec); + blackTimer.setSecondsLeft(quicksaveBlackTimeLeft); + } else { + blackTimer = new Timer(min, sec); + } + } + + public void saveAsPgn(Game game, String path, String dateiname) { + String event = safe(game.getRound().getEvent().getName()); + String site = safe(game.getRound().getEvent().getSite()); + String round = "" + game.getRound().getNumber(); + String date = safe(game.getRound().getEvent().getStartDate()).replace("-", "."); + String wName = safe(game.getWhitePlayer().getName()); + String bName = safe(game.getBlackPlayer().getName()); + String result = safe(game.getResult().getDescription()); + + StringBuilder header = new StringBuilder(); + header.append("[Event \"" + event + "\"]\n"); + header.append("[Site \"" + site + "\"]\n"); + header.append("[Date \"" + date + "\"]\n"); + header.append("[Round \"" + round + "\"]\n"); + header.append("[White \"" + wName + "\"]\n"); + header.append("[Black \"" + bName + "\"]\n"); + header.append("[Result \"" + result + "\"]\n\n"); + + StringBuilder movesSb = new StringBuilder(); + String[] sanArray = game.getHalfMoves().toSanArray(); + + for (int i = 0; i < sanArray.length; i++) { + if (i % 2 == 0) { + movesSb.append((i / 2 + 1)).append(". "); + } + movesSb.append(sanArray[i]).append(" "); + } + movesSb.append(result); + + String file = header + movesSb.toString(); + + try { + Files.writeString(Path.of(path, dateiname), file, StandardCharsets.UTF_8); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private String safe(String s) { + return s == null ? "?" : s; + } + + public Game getCurrentGame() { + return getCurrentGame(this.board, this.moves, this.currentMoveIndex); + } + + public Game getCurrentGame(Board board, List moves, int currentMoveIndex) { + Event event = new Event(); + event.setName("Generated Game"); + event.setSite("Local"); + event.setStartDate(LocalDate.now().toString()); + + Round round = new Round(event); + round.setNumber(1); + + Game game = new Game("1", round); + + game.setWhitePlayer(new MyPlayer("White")); + game.setBlackPlayer(new MyPlayer("Black")); + + if (board.isMated()) { + game.setResult(board.getSideToMove() == Side.WHITE ? GameResult.BLACK_WON : GameResult.WHITE_WON); + } else if (board.isStaleMate() || board.isDraw()) { + game.setResult(GameResult.DRAW); + } else { + game.setResult(GameResult.ONGOING); + } + + MoveList moveList = new MoveList(); + for (Move move : moves) { + moveList.add(move); + } + game.setHalfMoves(moveList); + + if (currentMoveIndex > 0 && currentMoveIndex <= moveList.size()) { + game.setPosition(currentMoveIndex - 1); + } else { + game.setPosition(moveList.size() - 1); + } + + game.setBoard(new Board()); + game.getBoard().loadFromFen(board.getFen()); + + return game; + } + + public void undoLastMove() { + if (currentMoveIndex > 0 && !moves.isEmpty()) { + board.undoMove(); + moves.remove(currentMoveIndex - 1); + currentMoveIndex--; + + String playedMovesUci = movesToUciString(moves.subList(0, currentMoveIndex)); + detectedOpening = Opening.detect(playedMovesUci); + } + } + + public void loadMoves(List moveList) { + board = new Board(); + moves.clear(); + currentMoveIndex = 0; + + for (Move move : moveList) { + board.doMove(move); + moves.add(move); + currentMoveIndex++; + } + } + + public Timer getWhiteTimer() { + return whiteTimer; + } + + public Timer getBlackTimer() { + return blackTimer; + } + + public GameMode getGameMode() { + return mode; + } } - - -