bug fixes
This commit is contained in:
@@ -88,16 +88,29 @@ html, body {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Overlaid on the bottom of the card at game end, so it never adds to the card's height
|
||||
(which would shift the whole grid as games finish and are cleared). */
|
||||
.gameOverlay {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 0.6rem;
|
||||
padding: 0.9rem 1rem;
|
||||
background-color: rgba(20, 20, 22, 0.92);
|
||||
border-radius: 0 0 10px 10px;
|
||||
}
|
||||
|
||||
.gameResult {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
color: #8cd5ed;
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
|
||||
.copyPgnBtn {
|
||||
display: block;
|
||||
margin: 0.75rem auto 0;
|
||||
background-color: #8cd5ed;
|
||||
color: #262626;
|
||||
border: 0;
|
||||
@@ -154,6 +167,13 @@ body.fullscreen-open {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
margin-bottom: 0.75rem;
|
||||
/* Reserve two lines so the header doesn't reflow as the move count gains digits,
|
||||
the side-to-move text changes, or the check tag toggles. */
|
||||
line-height: 1.3;
|
||||
min-height: 2.6em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Always occupies its space (it's only hidden, not removed) so toggling "check" never
|
||||
|
||||
@@ -274,34 +274,42 @@ const Spectate = {
|
||||
|
||||
if (!card) return;
|
||||
|
||||
let banner = card.querySelector(".gameResult");
|
||||
// The result and Copy PGN button live in an overlay anchored over the board so showing
|
||||
// them at game end never changes the card's height (which would shift the whole grid).
|
||||
let overlay = card.querySelector(".gameOverlay");
|
||||
|
||||
if (!text) {
|
||||
banner?.remove();
|
||||
card.querySelector(".copyPgnBtn")?.remove();
|
||||
overlay?.remove();
|
||||
card.classList.remove("over");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!banner) {
|
||||
banner = document.createElement("div");
|
||||
if (!overlay) {
|
||||
overlay = document.createElement("div");
|
||||
overlay.className = "gameOverlay";
|
||||
|
||||
const banner = document.createElement("div");
|
||||
banner.className = "gameResult";
|
||||
card.appendChild(banner);
|
||||
overlay.appendChild(banner);
|
||||
|
||||
card.appendChild(overlay);
|
||||
}
|
||||
|
||||
banner.textContent = text;
|
||||
overlay.querySelector(".gameResult").textContent = text;
|
||||
card.classList.add("over");
|
||||
this.addCopyPgn(gameId, card);
|
||||
},
|
||||
|
||||
addCopyPgn(gameId, card) {
|
||||
if (card.querySelector(".copyPgnBtn")) return;
|
||||
const overlay = card.querySelector(".gameOverlay");
|
||||
|
||||
if (!overlay || overlay.querySelector(".copyPgnBtn")) return;
|
||||
|
||||
const btn = document.createElement("button");
|
||||
btn.className = "copyPgnBtn";
|
||||
btn.textContent = "Copy PGN";
|
||||
btn.onclick = (event) => { event.stopPropagation(); this.copyPgn(gameId); };
|
||||
card.appendChild(btn);
|
||||
overlay.appendChild(btn);
|
||||
|
||||
// Prefetch now (while the game is still in memory) so copy works during the
|
||||
// brief window before the finished game is cleaned up.
|
||||
|
||||
@@ -87,10 +87,12 @@ static void save_global_weights(); /* defined below; load rewrites stale files
|
||||
static void load_global_weights(const char* path) {
|
||||
WinCounters loaded{};
|
||||
bool ok = false;
|
||||
bool fileExisted = false;
|
||||
|
||||
if (path && *path) {
|
||||
std::ifstream f(path);
|
||||
if (f) {
|
||||
fileExisted = true;
|
||||
int version = 0;
|
||||
if ((f >> version) && version == LEARNED_VERSION) {
|
||||
auto readTable = [&](double t[chess::PIECE_TYPE_NB][64]) -> bool {
|
||||
@@ -110,9 +112,12 @@ static void load_global_weights(const char* path) {
|
||||
g_counts = ok ? loaded : WinCounters{};
|
||||
recompute_weights();
|
||||
|
||||
/* Stale / wrong-version / unreadable: wipe the file's contents (keep the file) by
|
||||
* rewriting it blank-but-versioned, so the next load matches and we never reread garbage. */
|
||||
if (!ok)
|
||||
/* Only create a fresh file when none exists yet (first run): write it blank-but-versioned
|
||||
* so there's a valid target to persist into. If a file IS present but couldn't be parsed
|
||||
* (old format, corrupt, or a partial write), leave its bytes untouched — never destroy
|
||||
* accumulated training data on startup. We just play from neutral weights this session;
|
||||
* the next training apply() overwrites the file with a clean, current-format save. */
|
||||
if (!ok && !fileExisted)
|
||||
save_global_weights();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user