Thursday, June 25, 2026

MODIFICATION - Add comments, Import chess games, catalog them, list from first variation move and by frequency. / Chess and Music brainstorming

Also see hhttps://1a2b3c4d5e6f7g8h9i10j11k12l13m14n.blogspot.com/2026/06/modification-import-chess-games-catalog.html and https://1a2b3c4d5e6f7g8h9i10j11k12l13m14n.blogspot.com/2026/06/import-chess-games-catalog-them-list.html """ chessopenings3cleanup.py Interactive Opening Catalog + Continuation Analyzer - Loads existing opening catalog (JSON) - Processes ONE PGN at a time - Preserves PGN comments { } - Displays full interactive catalog - Allows manual reordering - Save with comments or without comments Requires: pip install python-chess """ import chess.pgn import os import json import re JSON_FILE = "personal_openings.json" START_PLY = 0 MAX_PLIES = 30 # ---------------------------- # LOAD / SAVE # ---------------------------- def load_data(): if os.path.exists(JSON_FILE): with open(JSON_FILE, "r", encoding="utf-8") as f: return json.load(f) return {} def save_data(data): with open(JSON_FILE, "w", encoding="utf-8") as f: json.dump(data, f, indent=4) def strip_comments(text): return re.sub(r"\s*\{.*?\}", "", text) def remove_comments_from_data(data): clean_data = {} for opening_key, variations in data.items(): clean_data[opening_key] = {} for line, freq in variations.items(): clean_line = strip_comments(line) if clean_line not in clean_data[opening_key]: clean_data[opening_key][clean_line] = freq else: clean_data[opening_key][clean_line] += freq return clean_data # ---------------------------- # FORMAT MOVES # ---------------------------- def format_continuation(san_moves, start_ply): lines = [] i = 0 ply = start_ply while i < len(san_moves) and ply < MAX_PLIES: move_number = (ply // 2) + 1 white = san_moves[i] i += 1 ply += 1 line = f"{move_number}. {white}" if i < len(san_moves) and ply < MAX_PLIES: black = san_moves[i] i += 1 ply += 1 line += f" {black}" lines.append(line) return lines # ---------------------------- # PROCESS PGN # ---------------------------- def process_pgn(filename, data): game_count = 0 with open(filename, "r", encoding="utf-8", errors="ignore") as pgn: while True: game = chess.pgn.read_game(pgn) if game is None: break game_count += 1 eco = game.headers.get("ECO", "").strip() opening = game.headers.get("Opening", "").strip() variation = game.headers.get("Variation", "").strip() white_elo = game.headers.get("WhiteElo", "") black_elo = game.headers.get("BlackElo", "") try: white_elo = int(white_elo) black_elo = int(black_elo) except ValueError: continue if white_elo < 2100 and black_elo < 2100: continue if not opening: opening = "Unknown Opening" key = f"{eco} | {opening}" if variation: key += f" | {variation}" board = game.board() san_moves = [] node = game ply_count = 0 while node.variations and ply_count < MAX_PLIES: next_node = node.variation(0) move_text = board.san(next_node.move) comment = next_node.comment.strip() if comment: move_text += f" {{{comment}}}" san_moves.append(move_text) board.push(next_node.move) node = next_node ply_count += 1 catalog_lines = format_continuation( san_moves, START_PLY ) catalog_str = " ".join(catalog_lines) if key not in data: data[key] = {} if catalog_str not in data[key]: data[key][catalog_str] = 1 else: data[key][catalog_str] += 1 print("\nGames processed:", game_count) # ---------------------------- # DISPLAY # ---------------------------- def display(data): print("\nOPENING CATALOG") print("=" * 100) items = sorted( data.items(), key=lambda item: sum(item[1].values()), reverse=True ) for i, (key, variations) in enumerate(items, start=1): print(f"\n{i:3} {key}") sorted_variations = sorted( variations.items(), key=lambda x: x[1], reverse=True ) for j, (cont, freq) in enumerate( sorted_variations[:5], start=1 ): print(f"\n [{j}] freq={freq}") print(f" {cont}") print("-" * 100) # ---------------------------- # REORDER # ---------------------------- def reorder(data): items = list(data.items()) while True: display(dict(items)) print("\nCommands:") print(" X=Y move item X to position Y") print(" s save WITH comments") print(" n save WITHOUT comments") print(" q quit") cmd = input("\nCommand: ").strip().lower() if cmd == "s": save_data(dict(items)) print("\nSaved with comments.") continue if cmd == "n": clean_data = remove_comments_from_data( dict(items) ) save_data(clean_data) print("\nSaved without comments.") continue if cmd == "q": return dict(items) if "=" in cmd: try: a, b = cmd.split("=") a = int(a) - 1 b = int(b) - 1 item = items.pop(a) items.insert(b, item) except: print("Invalid command") # ---------------------------- # MAIN # ---------------------------- def main(): data = load_data() print("\nChessOpenings3 Cleanup") print("----------------------") filename = input( "\nPGN filename (WITHOUT .pgn): " ).strip() if not filename: return filename += ".pgn" if not os.path.exists(filename): print("File not found:", filename) return process_pgn(filename, data) data = reorder(data) print("\nDone.") if __name__ == "__main__": main()

No comments:

Post a Comment