Added PGNDatabase and PGNGame classes with support for PGN parsing
This commit is contained in:
		
							
								
								
									
										29
									
								
								src/dev/kske/chess/pgn/PGNDatabase.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/dev/kske/chess/pgn/PGNDatabase.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | package dev.kske.chess.pgn; | ||||||
|  |  | ||||||
|  | import java.io.File; | ||||||
|  | import java.io.FileNotFoundException; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Scanner; | ||||||
|  |  | ||||||
|  | import dev.kske.chess.exception.ChessException; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Project: <strong>Chess</strong><br> | ||||||
|  |  * File: <strong>PGNDatabase.java</strong><br> | ||||||
|  |  * Created: <strong>4 Oct 2019</strong><br> | ||||||
|  |  * Author: <strong>Kai S. K. Engelbart</strong> | ||||||
|  |  */ | ||||||
|  | public class PGNDatabase { | ||||||
|  |  | ||||||
|  | 	private final List<PGNGame>	games	= new ArrayList<>(); | ||||||
|  |  | ||||||
|  | 	public void load(File pgnFile) { | ||||||
|  | 		try (Scanner sc = new Scanner(pgnFile)) { | ||||||
|  | 			while (sc.hasNext()) | ||||||
|  | 				games.add(PGNGame.parse(sc)); | ||||||
|  | 		} catch (FileNotFoundException | ChessException e) { | ||||||
|  | 			e.printStackTrace(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										77
									
								
								src/dev/kske/chess/pgn/PGNGame.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/dev/kske/chess/pgn/PGNGame.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | |||||||
|  | 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: <strong>Chess</strong><br> | ||||||
|  |  * File: <strong>PGNGame.java</strong><br> | ||||||
|  |  * Created: <strong>22 Sep 2019</strong><br> | ||||||
|  |  * Author: <strong>Kai S. K. Engelbart</strong> | ||||||
|  |  */ | ||||||
|  | public class PGNGame { | ||||||
|  |  | ||||||
|  | 	private final Map<String, String>	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); | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user