Repository navigation
Expand file tree
/
Copy pathstate.py
More file actions
184 lines (162 loc) · 6.43 KB
/
Copy pathstate.py
File metadata and controls
184 lines (162 loc) · 6.43 KB
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
"""Shared session state and constants for the chess trainer.
Holds the mutable parameter dicts and the UI/colour constants that used to be
module-level globals in chessMain.py, so the modules split out of chessMain can
import them without importing chessMain itself (which would create cycles).
The dicts (playParameters, positionParameters) are never reassigned, only
mutated, so importers can `from state import playParameters` safely. Values that
get *reassigned* (num_moves_to_show, play_position, id_course, courses, the menu
labels) live here too but are accessed as attributes -- `state.<name>` -- so a
reassignment is visible to every importer.
"""
import pygame_menu
# --- Play / position parameter dicts (mutated in place, never reassigned) ---
playParameters = {
"whiteCPU": False,
"blackCPU": True,
"elo": None,
"elomax": True,
"white": "White",
"black": "Black",
"result": "",
"event": "Play",
"site": "Local",
# PGN Date/Round. Empty = "this is a new game" -> the save stamps today / "*".
# Loading a game copies its own values here so that re-saving it after adding
# comments or variations keeps the original date instead of restamping it.
"date": "",
"round": "",
# None = no game loaded / "append on save". Always None, never "": the
# sentinel is compared with `is None` and fed to PgnGameList.save_game,
# which would compare "" with an int.
"gameid": None,
}
positionParameters = {
"eco": None,
"color": "w",
"filename": None,
"base": "openings",
"player": None,
"lichess_player": None, # lichess nick, separate from the chess.com one
"advisor_players": None, # study advisor nick list, separate from downloads
"movesToAnalyze": 16,
"blunderValue": 80,
"ponderTime": 0.5,
"useBook": False,
"filename": "",
# Index of the currently loaded game inside the PGN file, or None when no
# game is loaded (save then appends instead of replacing). This is the copy
# save_load.py actually reads/writes -- see the note on playParameters.
"gameid": None,
}
# --- Colour / selector constants ---
COLOR_MAP = {
0: "w",
1: "b",
2: None,
}
REVERSE_COLOR_MAP = {v: k for k, v in COLOR_MAP.items()}
CIRCLE_COLOR = (15, 50, 180, 90)
# --- Menu theme ---
small_font_theme = pygame_menu.themes.THEME_BLUE.copy()
small_font_theme.title_font_size = 24
small_font_theme.widget_font_size = 18
# --- Reassigned session scalars (access as state.<name> so writes propagate) ---
num_moves_to_show = 4
play_position = 1 # 1 = skip initial stored moves, 0 = play them all
practice_order = "random" # "priority" | "random" -- ordering in Solve positions
# default Random: with real bases (especially openings) priority
# saturates the session on the same 3-4 positions with a very high wrong count.
# Selected BrainMaster course (set from the course-chooser menu).
id_course = None
courses = None
# --- Menu label widgets (created in chessMain.mainMenu, read by the displays) ---
current_base_label = None
current_base_label2 = None
current_base_label3 = None
current_filename_label = None
current_filename_label3 = None
current_filename_label4 = None
current_ChessComFile_label = None
# --- Persistence of the last menu selections --------------------------------
#
# Keys that are loaded from `config.user_prefs` at startup and saved every
# time a menu updater (`make_updater`/`make_selector_updater` in
# menu_helpers.py) modifies a value. In practice: the "Solve positions",
# "Study openings", "Play vs computer" etc. screens show, on restart, the
# last value chosen instead of the hard-coded defaults above.
#
# Form: (target, key)
# - target == "pp" -> positionParameters[key]
# - target == "play" -> playParameters[key]
# - target == "state" -> module-level scalar
#
# Intentionally does NOT include "gameid", "result", "courses", "id_course" -- they are
# volatile or loaded from BrainMaster, they make no sense as a "last choice".
_PERSIST_SPEC = [
("pp", "eco"),
("pp", "color"),
("pp", "filename"),
("pp", "filename_folder"), # general Load/Save: remember WHERE the file was picked
("pp", "openings_filename"), # Study openings: per-mode last file (always in openings/)
("pp", "endgames_filename"), # Endgame training: per-mode last file (always in endgames/)
("pp", "base"),
("pp", "player"),
("pp", "lichess_player"),
("pp", "advisor_players"),
("pp", "movesToAnalyze"),
("pp", "blunderValue"),
("pp", "ponderTime"),
("pp", "useBook"),
("play", "whiteCPU"),
("play", "blackCPU"),
("play", "elo"),
("play", "elomax"),
("play", "white"),
("play", "black"),
("play", "event"),
("play", "site"),
("state", "num_moves_to_show"),
("state", "play_position"),
("state", "practice_order"),
]
def _saving_enabled() -> bool:
"""Disable saving during load (avoids noise in config.json)."""
return _save_armed
_save_armed = False # armed only after load_user_prefs()
def load_user_prefs() -> None:
"""Load the last menu selections from `config.user_prefs` into the dicts
and the module variables. Types are already correct because JSON serializes
native int/float/str/bool/None (just as we write them)."""
global _save_armed
import config as _cfg
prefs = getattr(_cfg.config, "user_prefs", None) or {}
for target, key in _PERSIST_SPEC:
if key not in prefs:
continue
value = prefs[key]
if target == "pp":
positionParameters[key] = value
elif target == "play":
playParameters[key] = value
elif target == "state":
globals()[key] = value
_save_armed = True
def save_user_prefs() -> None:
"""Snapshot the current selections into `config.user_prefs` and flush
to disk. Called by every menu updater (idempotent)."""
if not _save_armed:
return
import config as _cfg
snapshot = {}
for target, key in _PERSIST_SPEC:
if target == "pp":
snapshot[key] = positionParameters.get(key)
elif target == "play":
snapshot[key] = playParameters.get(key)
elif target == "state":
snapshot[key] = globals().get(key)
_cfg.config.user_prefs = snapshot
_cfg.save_config()
# Load immediately: on the first import of state, the dicts are already populated
# with the user's last selection. From this moment save_user_prefs() is armed.
load_user_prefs()