File size: 2,155 Bytes
299b8c0
4eef17c
63103fa
 
4eef17c
 
 
299b8c0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63103fa
 
 
299b8c0
63103fa
 
 
 
 
4eef17c
 
 
 
 
 
63103fa
 
4eef17c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63103fa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
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


# Load 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:
        # Ensure move is legal in current position
        if move in board.legal_moves:
            current = current.add_variation(move)
            board.push(move)
        else:
            break  # Stop if PV deviates from legal moves