All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fathzer.games.perft.PerfTParser Maven / Gradle / Ivy

The newest version!
package com.fathzer.games.perft;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.function.UnaryOperator;

/**
 * A parser of text files containing PerfT tests data set.
 * 
Here is the file format:
    *
  • Lines starting with # are comments.
  • *
  • Empty or blank lines before first test data should be ignored.
  • *
  • A perfT test starts with a name line and ends at the next name line (or the end of file).
      *
    • A name line starts with 'name ' followed by an id of the test (This is configurable with {@link #withNamePrefix(String)}).
    • *
    • The line immediately after the name line contains the position in FEN format variant where half move count and move number are missing.
    • *
    • The position is prefixed by 'start ' (This is configurable with {@link #withStartPositionPrefix(String)}).
    • *
    • The other lines are result lines. They start with 'perft ' (This is configurable with {@link #withResultPrefix(String)}), followed by a depth and the number of leaves at that depth in the tree obtained by playing all possible moves.
    • *
    • The first result line is for depth 1. Second for depth 2, etc ... With no missing depth between 1 and the maximum depth for that test. * The maximum depth can vary from one test to another (This is configurable with {@link #withResultPrefix(String)}).
    • *
  • *
*/ public class PerfTParser { private String startPositionPrefix = "start"; private String resultPrefix = "perft"; private String namePrefix = "name"; private UnaryOperator startPositionCustomizer = s->s; /** Sets the prefix of name lines. * @param namePrefix the prefix to set ("name" is the default value) * @return this instance for fluent API */ public final PerfTParser withNamePrefix(String namePrefix) { this.namePrefix = namePrefix; return this; } /** Sets the prefix of start position lines. * @param startPositionPrefix the prefix to set ("start" is the default value) * @return this instance for fluent API */ public final PerfTParser withStartPositionPrefix(String startPositionPrefix) { this.startPositionPrefix = startPositionPrefix; return this; } /** Sets a customizer for start position lines. *
The customizer is applied to the position string before putting it in the result. *
Typically, in chess, start positions are often expressed in FEN format. *
The move number and half move count are useless in perfT tests and can be removed from the text file and added to their default * values on the fly by this customizer. * @param startPositionCustomizer the customizer to set * @return this instance for fluent API */ public final PerfTParser withStartPositionCustomizer(UnaryOperator startPositionCustomizer) { this.startPositionCustomizer = startPositionCustomizer; return this; } /** Sets the prefix of result lines. * @param resultPrefix the prefix to set ("perft" is the default value) * @return this instance for fluent API */ public final PerfTParser withResultPrefix(String resultPrefix) { this.resultPrefix = resultPrefix; return this; } /** Reads a list of {@link PerfTTestData} from an input stream. * @param stream The stream to read (warning, this method does not close the stream) * @param cs The charset of the stream * @return A list of {@link PerfTTestData} * @throws IOException If an I/O error occurs */ public List read(InputStream stream, Charset cs) throws IOException { final List tests = new ArrayList<>(); try (BufferedReader reader = new BufferedReader(new UnclosedReader(stream, cs))) { PerfTTestData current = null; String name = null; String start = null; int lineNumber = 0; for (String line = reader.readLine(); line!=null; line = reader.readLine()) { lineNumber++; if (line.startsWith(namePrefix)) { name = line.substring(namePrefix.length()).trim(); current = null; } else if (line.startsWith(startPositionPrefix)) { start = startPositionCustomizer.apply(line.substring(startPositionPrefix.length()).trim()); current = null; } else if (line.startsWith(resultPrefix)) { if (current==null) { if (start==null) { throw new IllegalArgumentException("Found "+resultPrefix+" before any start position"); } else { current = new PerfTTestData(name, start); name = null; start = null; tests.add(current); } } addResultLine(current, lineNumber, line); } } } return tests; } private void addResultLine(PerfTTestData current, int lineNumber, String line) throws IOException { final String[] fields = line.substring(resultPrefix.length()).trim().split(" "); try { final int depth = Integer.parseInt(fields[0]); if (depth!=current.getSize()+1) { throw new IllegalArgumentException("Seems depths are not sequential or don't start at 1"); } final long count = Long.parseLong(fields[1]); current.add(count); } catch (RuntimeException e) { throw new IOException("Problem while parsing line "+lineNumber,e); } } private static class UnclosedReader extends InputStreamReader { public UnclosedReader(InputStream in, Charset set) { super(in, set); } @Override public void close() throws IOException { // Don't close underlying stream } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy