diff --git a/.idea/php-test-framework.xml b/.idea/php-test-framework.xml new file mode 100644 index 0000000..5bb5da3 --- /dev/null +++ b/.idea/php-test-framework.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FenParser0x88.php b/FenParser0x88.php index 831391b..87c121c 100755 --- a/FenParser0x88.php +++ b/FenParser0x88.php @@ -1443,12 +1443,13 @@ class FenParser0x88 if (is_string($move) && strlen($move) == 4) { $move = $this->getFromAndToByLongNotation($move); + } else if (is_string($move)) { $move = $this->getFromAndToByNotation($move); } if(!$this->canMoveFromTo($move["from"], $move["to"])){ - throw new FenParser0x88Exception("Invalid move " . json_encode($move)); + throw new FenParser0x88Exception("Invalid move " . $this->getColor() . " - " . json_encode($move)); } $this->fen = null; @@ -1477,9 +1478,7 @@ class FenParser0x88 if(empty($validMoves[$from]) || !in_array($to, $validMoves[$from])){ return false; } - return true; - } function setNewColor() diff --git a/GameParser.php b/GameParser.php index 4ee75ee..ce07704 100755 --- a/GameParser.php +++ b/GameParser.php @@ -7,14 +7,23 @@ class GameParser private $game; private $fen; private $fenParser0x88; + + private $shortVersion; + public function __construct() { $this->fenParser0x88 = new FenParser0x88(); } - public function getParsedGame($game) + /** + * @param array $game + * @param bool $short for only from and to squares + * @return mixed + */ + public function getParsedGame($game, $short = false) { $this->game = $game; + $this->shortVersion = $short; $this->fen = $this->getStartFen(); $this->fenParser0x88->newGame($this->fen); @@ -48,6 +57,8 @@ class GameParser $this->fenParser0x88->setFen($fen); } $move = $this->fenParser0x88->getParsed($move); + + } private function parseVariations(&$variations) diff --git a/PgnParser.php b/PgnParser.php index 8faf2d4..abb3f36 100755 --- a/PgnParser.php +++ b/PgnParser.php @@ -15,8 +15,8 @@ class PgnParser if ($pgnFile) { $this->pgnFile = $this->sanitize($pgnFile); - if(!file_exists($this->pgnFile)){ - throw new Exception("File not found: ". $this->pgnFile); + if (!file_exists($this->pgnFile)) { + throw new Exception("File not found: " . $this->pgnFile); } } @@ -32,7 +32,7 @@ class PgnParser if (class_exists("LudoDBRegistry")) { $tempPath = LudoDBRegistry::get('FILE_UPLOAD_PATH'); - }else{ + } else { $tempPath = null; } @@ -68,7 +68,7 @@ class PgnParser $c = preg_replace('/"\]\s{0,10}\[/s', "]\n[", $c); $c = preg_replace('/"\]\s{0,10}([\.0-9]|{)/s', "\"]\n\n$1", $c); - $c = preg_replace("/{\s{0,6}\[%emt[^\}]*?\}/","",$c); + $c = preg_replace("/{\s{0,6}\[%emt[^\}]*?\}/", "", $c); $c = preg_replace("/\\$[0-9]+/s", "", $c); $c = str_replace("({", "( {", $c); @@ -84,7 +84,6 @@ class PgnParser $c = str_replace("0-0", "O-O", $c); - return $c; } @@ -105,7 +104,7 @@ class PgnParser $games = preg_split("/\n\n\[/s", $content, -1, PREG_SPLIT_DELIM_CAPTURE); for ($i = 1, $count = count($games); $i < $count; $i++) { $gameContent = trim("[" . $games[$i]); - if(strlen($gameContent) > 10){ + if (strlen($gameContent) > 10) { array_push($ret, $gameContent); } } @@ -134,13 +133,15 @@ class PgnParser return $this->pgnGames; } - - public function countGames(){ + + public function countGames() + { $games = $this->getUnparsedGames(); return count($games); } - public function getCleanPgn(){ + public function getCleanPgn() + { return $this->cleanPgn($this->pgnContent); } @@ -159,21 +160,62 @@ class PgnParser } public function getGames() + { + return $this->getParsedGames(false); + } + + public function getGamesShort() + { + return $this->getParsedGames(true); + } + + private function getParsedGames($short = false) { $games = $this->getUnparsedGames(); $ret = array(); for ($i = 0, $count = count($games); $i < $count; $i++) { - try{ - $g = $this->getParsedGame($games[$i]); + try { + $g = $short ? $this->getParsedGameShort($games[$i]) : $this->getParsedGame($games[$i]); $ret[] = $g; - }catch(Exception $e){ + } catch (Exception $e) { } } return $ret; } + private function getParsedGameShort($unParsedGame) + { + $this->pgnGameParser->setPgn($unParsedGame); + $ret = $this->pgnGameParser->getParsedData(); + if ($this->fullParsing()) { + $ret = $this->gameParser->getParsedGame($ret, true); + $moves = &$ret["moves"]; + $moves = $this->toShortVersion($moves); + } + return $ret; + } + + + private function toShortVersion($branch){ + foreach ($branch as &$move) { + $move["n"] = $move["from"] . $move["to"]; + unset($move["m"]); + unset($move["fen"]); + unset($move["from"]); + unset($move["to"]); + if(isset($move["variations"])){ + $move["v"] = array(); + foreach($move["variations"] as $variation){ + $move["v"][] = $this->toShortVersion($variation); + } + } + unset($move["variations"]); + } + return $branch; + } + private function getParsedGame($unParsedGame) { $this->pgnGameParser->setPgn($unParsedGame); diff --git a/test/ParserTest.php b/test/ParserTest.php index 9dba6f2..fd9d8c4 100755 --- a/test/ParserTest.php +++ b/test/ParserTest.php @@ -72,11 +72,11 @@ class ParserTest extends PHPUnit_Framework_TestCase // when $parser->move("e2e4"); - $parser->move("e7e5"); + $parser->move("c7c5"); // then - $this->assertEquals("e6", $parser->getEnPassantSquare()); + $this->assertEquals("c6", $parser->getEnPassantSquare()); $parser->move("e4e5"); @@ -2358,4 +2358,79 @@ Rc8 Ne6+ 72. Kf6 d2 73. c5+ Kd7 0-1'; // then $this->assertEquals(30, count($games)); } + + /** + * @test + */ + + public function shouldParseProblematic_4(){ + // given + $parser = new PgnParser("pgn/problematic4.pgn"); + + // when + $games = $parser->getGames(); + + // then + $this->assertEquals(1, count($games)); + } + + /** + * @test + */ + public function shouldBeAbleToImportWithoutFenForEachMove(){ + // given + $parser = new PgnParser("pgn/greatgames.pgn"); + + // when + $games = $parser->getGamesShort(); + $game = $games[0]; + // then + $this->assertEquals(10, count($games)); + $this->assertArrayNotHasKey("fen", $game["moves"][0], json_encode($game["moves"][0])); + $this->assertEquals("e2e4", $game["moves"][0]["n"], json_encode($game["moves"][0])); + + } + + + /** + * @test + */ + public function shouldBeAbleToHandleVariationWhenUsingShortVersion() + { + // given + $parser = new PgnParser("pgn/variation.pgn"); + + // when + $games = $parser->getGamesShort(); + $this->assertEquals(1, count($games), json_encode($games)); + $game = $games[0]; + $variations = $game["moves"][0]["v"]; + $msg = json_encode($variations); + + // then + $this->assertEquals(3, count($variations), $msg); + $this->assertEquals(2, count($variations[0]), $msg); + $this->assertEquals(1, count($variations[1]), $msg); + $this->assertEquals(1, count($variations[2]), $msg); + + $var1 = $variations[0]; + $this->assertEquals("d2d4", $var1[0]["n"]); + $this->assertEquals("d2d4", $var1[0]["n"]); + $var2 = $variations[1]; + $this->assertEquals("c2c4", $var2[0]["n"]); + $var2 = $variations[2]; + $this->assertEquals("f2f4", $var2[0]["n"]); + + + $var3 = $game["moves"][2]["v"][0]; + $this->assertEquals("b1c3", $var3[0]["n"], json_encode($game)); + + + + } + + + + + } diff --git a/test/pgn/problematic4.pgn b/test/pgn/problematic4.pgn new file mode 100644 index 0000000..1382a46 --- /dev/null +++ b/test/pgn/problematic4.pgn @@ -0,0 +1,15 @@ +[Event "e"] +[Site "s"] +[Date "????.??.??"] +[Round "r"] +[White "w"] +[Black "b"] +[Result "*"] +[FEN "5k2/8/4KP2/8/8/8/8/8 w - - 0 1"] +[SetUp "1"] +[WhiteElo "1500"] +[BlackElo "1500"] +[ECO ""] +[CurrentPosition "5k2/8/4KP2/8/8/8/8/8 w - - 0 1"] + +1.f7 Kg7 2.Ke7 Kh7 3.f8=Q * \ No newline at end of file diff --git a/test/pgn/variation.pgn b/test/pgn/variation.pgn new file mode 100644 index 0000000..719e49e --- /dev/null +++ b/test/pgn/variation.pgn @@ -0,0 +1,11 @@ +[Event "001 Art of Attack"] +[Site "?"] +[Date "????.??.??"] +[Round "?"] +[White "?"] +[Black "?"] +[Result "*"] +[SetUp "1"] +[PlyCount "5"] + +1. e4 (1. d4 Nf6) (1. c4) (1. f4) e5 2. Nf3 (2. Nc3) f5 \ No newline at end of file