Автоплеер для файла PGN
Файл PGN может содержать любое количество партий (экспорт с Личесса тоже подойдёт) и располагается на сервере в папке скрипта. После загрузки клиентской страницы index.html
, средствами AJAX вызывается серверный скрипт loader.php
, который парсит и читает файл PGN в скрытый раздел документа. В дальнейшем клиентский Javascript-плеер, основанный на chess.js
и chessboard.js
, прокручивает партии, запоминая в хранилище, на какой игре Вы остановились.
Я использовал кусочки прежнего кода из XMLHttpRequest и "обезьяньих шахмат".
Кроме того, хотелось обновить chess.js
, так как моя версия ещё не умеет загружать из партии комментарии, но у автора теперь только .ts-файл, конвертировал онлайн вот здесь в .js и убрал директиву export
(заменил на пустое место).
Обновил также неупакованные chessboard.js и jquery.js от производителей, все они во вложенной папке js
архива. В первом пришлось изменить одну строку
config.pieceTheme = './img/{piece}.png'
чтобы был относительный путь к картинкам с фигурами.
Предполагается, что мы будем вставлять новые партии в PGN в конец файла base.pgn
, тогда нумерация не собьётся.
Плеер не смутят лишние пустые строки или "незнакомые" (отсутствующие) теги PGN в заголовке, например, такой base.pgn
вполне корректен:
[Event "Мои великие победы: Мои великие победы (4)"] [Site "https://lichess.org/study/vWmLfY8d/uXt8SC5h"] [White "PerS"] [Black "NePers"] [Result "1-0"] [UTCDate "2021.02.13"] [UTCTime "09:11:17"] [Variant "Standard"] [ECO "C40"] [Opening "Elephant Gambit"] [Annotator "https://lichess.org/@/Old_Drunkard"] 1. e4 { [%eval 0.25] } 1... e5 { [%eval 0.31] } 2. Nf3 { [%eval 0.28] } 2... d5?! { [%eval 0.98] } { Inaccuracy. Nc6 was best. } (2... Nc6 3. Bb5 Nf6 4. d3 Bc5 5. Bxc6 dxc6 6. O-O Bd6 7. a4) 3. c3?? { [%eval -0.88] } { Blunder. exd5 was best. } { Типа я решил проверить, а что будет на c3 :) } (3. exd5 Qxd5 4. Nc3 Qc5 5. Bb5+ c6 6. Ba4 Be7 7. Bb3 Nf6) 3... dxe4 { [%eval -0.82] } 4. Nxe5 { [%eval -0.52] } 4... f6?? { [%eval 2.92] } { Blunder. Qe7 was best. } (4... Qe7 5. Nc4 Nc6 6. Be2 Be6 7. d4 exd3 8. Qxd3 Rd8 9. Qe3) 5. Qh5+ { [%eval 2.76] } 5... g6 { [%eval 2.86] } 6. Nxg6 { [%eval 2.75] } 6... Kf7?? { [%eval 9.48] } { Blunder. hxg6 was best. } (6... hxg6 7. Qxh8 Be6 8. Qh4 Qd5 9. Qg3 Nd7 10. d4 O-O-O 11. Nd2 g5 12. Qe3 f5 13. Bc4) 7. Ne5+ { [%eval 7.41] } 7... Kg7? { [%eval #3] } { Checkmate is now unavoidable. Ke7 was best. } (7... Ke7 8. Qf7+ Kd6 9. Nc4+ Kc6 10. Na5+ Kd6 11. Na3 Qe7 12. Nb5+ Kd7 13. Qd5+ Ke8 14. Nxb7) 8. Qf7+ { [%eval #2] } 8... Kh6 { [%eval #2] } 9. d3+ { [%eval #1] } 9... e3 { [%eval #1] } 10. Bxe3# { 1-0 White wins by checkmate. } 1-0 [Event "Детский мат"] 1. e4 e5 2. Bc4 Bc5 3. Qh5 Nf6 4. Qxf7# 1. e3 (1. f3 e5 2. g4 Qh4#)
"Вытягивать" основное содержимое партии в одну строку, как того требует формат, необязательно, главное не допускать пустых строк внутри списка ходов и комментариев.
Также предполагается, что все партии начинаются со стартовой позиции.
Серверный скрипт loader.php
довольно прост и не гарантирует безошибочного разбора всех на свете PGN-файлов:
<?php $name = './base.pgn'; $games = []; $headers = []; $lines = file($name,FILE_IGNORE_NEW_LINES); if ($lines === false) { echo '<div id="gamesCount">1</div>'. '<div id="headers0">[Event "Не могу прочитать файл"]</div>'. '<div id="game0">1. h4 </div>'; return; } $i = $k = 0; $cnt = count($lines); while ($i < $cnt) { while (empty(trim($lines[$i]))) { $i++; if ($i >= $cnt) break 2; } $headers[$k] = ''; while (preg_match("/^\[.+\]$/",trim($lines[$i])) === 1) { $headers[$k] .= htmlspecialchars(trim($lines[$i]),ENT_QUOTES,'UTF-8').'<br>'; $i++; if ($i >= $cnt) break 2; } while (empty(trim($lines[$i]))) { $i++; if ($i >= $cnt) break 2; } $games[$k] = ''; while (preg_match("/^\[.+\]$/",trim($lines[$i])) === 0) { if (empty(trim($lines[$i]))) break; $games[$k] .= htmlspecialchars(trim($lines[$i]),ENT_QUOTES,'UTF-8').' '; $i++; if ($i >= $cnt) break 2; } if ($i < $cnt) $k++; } if ($k < 1) { echo '<div id="gamesCount">1</div>'. '<div id="headers0">[Event "Неверный файл"]</div>'. '<div id="game0">1. g4 </div>'; return; } $cnt = count($games); $gamesContent = '<div id="gamesContent">'."\n"; for ($i = 0; $i < count($games); $i++) { if (!isset($games[$i]) or empty($games[$i]) or $games[$i] === "") { $cnt--; continue; } else if (!isset($headers[$i]) or empty($headers[$i])) $headers[$i] = ""; $gamesContent .= '<div id="headers'.$i.'">'."\n". $headers[$i]. '</div>'."\n". '<div id="game'.$i.'">'."\n". $games[$i]. '</div>'."\n"; } $gamesContent .= '</div>'; $gamesCount = '<div id="gamesCount">'.$cnt.'</div>'."\n"; echo "$gamesCount"; echo "$gamesContent"; ?>
Увидеть все клиентские файлы .html
, .js
и .css
легко из исходника страницы по прямым ссылкам, картинки находятся во вложенной папке img
под стандартными именами. Возможно, исходник будет ещё немного улучшаться, написал всё сегодня и довольно-таки левой ногой.
Для наполнения базы я использовал немного своих "великих побед" над безразрядниками :)
Открыть скрипт MyChessPGNPlayer в новом окне/вкладке
08.03.2023, 17:58 [369 просмотров]