Skip to content

Commit

Permalink
Feature/pgn parser (#748)
Browse files Browse the repository at this point in the history
* Added Chess\PgnParser\FileLine

* Added Chess\PgnParser\AbstractParser

* Implemented Chess\Parser

* Refactored play_games()

* Renamed play_games() as classical_customized()
  • Loading branch information
programarivm authored Feb 19, 2025
1 parent 40cd5c4 commit 1892cf7
Show file tree
Hide file tree
Showing 54 changed files with 587 additions and 62 deletions.
36 changes: 36 additions & 0 deletions src/Parser/PgnLine.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Chess\Parser;

use Chess\Variant\Classical\PGN\Termination;

class PgnLine
{
public function isOneLinerMovetext(string $line): bool
{
return $this->startsMovetext($line) && $this->endsMovetext($line);
}

public function startsMovetext(string $line): bool
{
return $this->startsWith($line, '1.');
}

public function endsMovetext(string $line): bool
{
return $this->endsWith($line, Termination::WHITE_WINS) ||
$this->endsWith($line, Termination::BLACK_WINS) ||
$this->endsWith($line, Termination::DRAW) ||
$this->endsWith($line, Termination::UNKNOWN);
}

public function startsWith(string $haystack, string $needle): bool
{
return strncmp($haystack, $needle, strlen($needle)) === 0;
}

public function endsWith(string $haystack, string $needle): bool
{
return substr($haystack, -strlen($needle)) === $needle;
}
}
90 changes: 90 additions & 0 deletions src/Parser/PgnParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php

namespace Chess\Parser;

use Chess\Exception\UnknownNotationException;
use Chess\Movetext\SanMovetext;
use Chess\Parser\PgnLine;
use Chess\Variant\Classical\PGN\Tag;
use Chess\Variant\Classical\PGN\Move;

class PgnParser
{
protected string $filepath;

protected PgnLine $line;

protected object $result;

protected \Closure $callback;

public function __construct(string $filepath)
{
$this->filepath = $filepath;
$this->line = new PgnLine();
$this->result = (object) [
'total' => 0,
'valid' => 0,
];
}

public function getResult(): array
{
return $this->result;
}

public function parse(): void
{
$tags = [];
$movetext = '';
$file = new \SplFileObject($this->filepath);
$tag = new Tag();
$move = new Move();
while (!$file->eof()) {
$line = rtrim($file->fgets());
try {
$valid = $tag->validate($line);
$tags[$valid['name']] = $valid['value'];
} catch (UnknownNotationException $e) {
if ($this->line->isOneLinerMovetext($line)) {
if (!array_diff($tag->mandatory(), array_keys($tags)) &&
$validMovetext = (new SanMovetext($move, $line))->validate()
) {
if ($this->handle($tags, $validMovetext)) {
$this->result->valid++;
}
}
$tags = [];
$movetext = '';
$this->result->total++;
} elseif ($this->line->startsMovetext($line)) {
if (!array_diff($tag->mandatory(), array_keys($tags))) {
$movetext .= ' ' . $line;
}
} elseif ($this->line->endsMovetext($line)) {
$movetext .= ' ' . $line;
if ($validMovetext = (new SanMovetext($move, $movetext))->validate()) {
if ($this->handle($tags, $validMovetext)) {
$this->result->valid++;
}
}
$tags = [];
$movetext = '';
$this->result->total++;
} else {
$movetext .= ' ' . $line;
}
}
}
}

public function onValidate($callback): void
{
$this->callback = $callback;
}

protected function handle(array $tags, string $movetext): void
{
call_user_func($this->callback, $tags, $movetext);
}
}
450 changes: 450 additions & 0 deletions tests/data/classical/customized.pgn

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion tests/data/pgn/01.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/02.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/03.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/04.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/05.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/06.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/07.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/08.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/09.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/10.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/11.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/12.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/13.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/14.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/15.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/16.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/17.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/18.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/19.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/20.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/21.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/22.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/23.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/24.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/25.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/26.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/27.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/28.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/29.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/30.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/31.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/32.pgn

This file was deleted.

1 change: 0 additions & 1 deletion tests/data/pgn/33.pgn

This file was deleted.

Loading

0 comments on commit 1892cf7

Please sign in to comment.