|
import io |
|
import logging |
|
import chess.pgn |
|
import tempfile |
|
import os |
|
import time |
|
import glob |
|
import gradio as gr |
|
|
|
|
|
def extract_game(png_input): |
|
if isinstance(png_input, io.IOBase): |
|
file = png_input |
|
elif isinstance(png_input, str): |
|
file = io.StringIO(png_input) |
|
elif isinstance(png_input, gr.utils.NamedString): |
|
file = png_input.name |
|
else: |
|
raise ValueError("Input must be a string or a file-like object.") |
|
|
|
game = read_pgn(file) |
|
return game |
|
|
|
|
|
def pgn_string_to_game(pgn_text: str) -> chess.pgn.Game: |
|
pgn_io = io.StringIO(pgn_text) |
|
game = chess.pgn.read_game(pgn_io) |
|
return game |
|
|
|
|
|
|
|
def read_pgn(pgn_filepath) -> str: |
|
with open(pgn_filepath) as f: |
|
game = chess.pgn.read_game(f) |
|
return game |
|
|
|
|
|
def export_pgn(game, tmp_dir="tmp_pgn"): |
|
os.makedirs(tmp_dir, exist_ok=True) |
|
|
|
with tempfile.NamedTemporaryFile( |
|
delete=False, suffix=".pgn", dir=tmp_dir, mode="w", encoding="utf-8" |
|
) as tmp: |
|
exporter = chess.pgn.FileExporter(tmp) |
|
game.accept(exporter) |
|
return tmp.name |
|
|
|
|
|
def cleanup_tmp_pgn(tmp_dir="tmp_pgn", expire_seconds=300): |
|
if not os.path.exists(tmp_dir): |
|
return |
|
|
|
now = time.time() |
|
pgn_files = glob.glob(os.path.join(tmp_dir, "*.pgn")) |
|
|
|
for file_path in pgn_files: |
|
try: |
|
if now - os.path.getmtime(file_path) > expire_seconds: |
|
os.remove(file_path) |
|
logging.info(f"Deleted: {file_path}") |
|
except Exception as e: |
|
logging.warning(f"Error deleting {file_path}: {e}") |
|
|
|
|
|
def format_pv(pv_moves, board): |
|
temp_board = board.copy() |
|
san_moves = [] |
|
for move in pv_moves: |
|
san_moves.append(temp_board.san(move)) |
|
temp_board.push(move) |
|
return " ".join(san_moves) |
|
|
|
|
|
def add_variation(node, variation): |
|
board = node.board() |
|
current = node |
|
|
|
for move in variation: |
|
|
|
if move in board.legal_moves: |
|
current = current.add_variation(move) |
|
board.push(move) |
|
else: |
|
break |
|
|