package dev.kske.chess.pgn; import java.util.HashMap; import java.util.Map; import java.util.Scanner; import java.util.regex.MatchResult; import java.util.regex.Pattern; import dev.kske.chess.board.Board; import dev.kske.chess.exception.ChessException; /** * Project: Chess
* File: PGNGame.java
* Created: 22 Sep 2019
* Author: Kai S. K. Engelbart */ public class PGNGame { private final Map tagPairs = new HashMap<>(7); private final Board board = new Board(); public static PGNGame parse(Scanner sc) throws ChessException { PGNGame game = new PGNGame(); MatchResult matchResult; Pattern tagPairPattern = Pattern.compile("\\[(\\w+) \"(.*)\"]"), movePattern = Pattern.compile("\\d+\\. (\\S+)\\s(\\S+)"), nagPattern = Pattern.compile("(\\$\\d{1,3})*"), terminationMarkerPattern = Pattern.compile("1-0|0-1|1\\/2-1\\/2|\\*"); // Parse tag pairs while (true) { if (sc.findInLine(tagPairPattern) != null) { matchResult = sc.match(); if (matchResult.groupCount() == 2) game.setTag(matchResult.group(0), matchResult.group(1)); else break; } else break; sc.nextLine(); } // Parse movetext while (true) { // Skip NAG (Numeric Annotation Glyph) sc.skip(nagPattern); // TODO: Parse RAV (Recursive Annotation Variation) sc.findWithinHorizon(movePattern, 20); matchResult = sc.match(); if (matchResult.groupCount() > 0) for (int i = 1; i < matchResult.groupCount() + 1; i++) { game.board.move(matchResult.group(i)); System.out.println(game.board.toFEN()); } else break; } // Parse game termination marker if (sc.hasNext(terminationMarkerPattern)) { sc.next(terminationMarkerPattern); } else throw new ChessException("Game termination marker expected"); return game; } public String getTag(String tagName) { return tagPairs.get(tagName); } public boolean hasTag(String tagName) { return tagPairs.containsKey(tagName); } public void setTag(String tagName, String tagValue) { tagPairs.put(tagName, tagValue); } }