Gitea/workflows #1

Closed
jheaps wants to merge 47 commits from gitea/workflows into AddProject
3 changed files with 48 additions and 15 deletions
Showing only changes of commit 9da7b1986b - Show all commits
+23 -3
View File
@@ -88,16 +88,29 @@ html, body {
cursor: pointer; 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 { .gameResult {
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
color: #8cd5ed; color: #8cd5ed;
margin-top: 0.75rem;
} }
.copyPgnBtn { .copyPgnBtn {
display: block;
margin: 0.75rem auto 0;
background-color: #8cd5ed; background-color: #8cd5ed;
color: #262626; color: #262626;
border: 0; border: 0;
@@ -154,6 +167,13 @@ body.fullscreen-open {
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
margin-bottom: 0.75rem; 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 /* Always occupies its space (it's only hidden, not removed) so toggling "check" never
@@ -274,34 +274,42 @@ const Spectate = {
if (!card) return; 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) { if (!text) {
banner?.remove(); overlay?.remove();
card.querySelector(".copyPgnBtn")?.remove();
card.classList.remove("over"); card.classList.remove("over");
return; return;
} }
if (!banner) { if (!overlay) {
banner = document.createElement("div"); overlay = document.createElement("div");
overlay.className = "gameOverlay";
const banner = document.createElement("div");
banner.className = "gameResult"; banner.className = "gameResult";
card.appendChild(banner); overlay.appendChild(banner);
card.appendChild(overlay);
} }
banner.textContent = text; overlay.querySelector(".gameResult").textContent = text;
card.classList.add("over"); card.classList.add("over");
this.addCopyPgn(gameId, card); this.addCopyPgn(gameId, card);
}, },
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"); const btn = document.createElement("button");
btn.className = "copyPgnBtn"; btn.className = "copyPgnBtn";
btn.textContent = "Copy PGN"; btn.textContent = "Copy PGN";
btn.onclick = (event) => { event.stopPropagation(); this.copyPgn(gameId); }; 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 // Prefetch now (while the game is still in memory) so copy works during the
// brief window before the finished game is cleaned up. // brief window before the finished game is cleaned up.
+8 -3
View File
@@ -87,10 +87,12 @@ static void save_global_weights(); /* defined below; load rewrites stale files
static void load_global_weights(const char* path) { static void load_global_weights(const char* path) {
WinCounters loaded{}; WinCounters loaded{};
bool ok = false; bool ok = false;
bool fileExisted = false;
if (path && *path) { if (path && *path) {
std::ifstream f(path); std::ifstream f(path);
if (f) { if (f) {
fileExisted = true;
int version = 0; int version = 0;
if ((f >> version) && version == LEARNED_VERSION) { if ((f >> version) && version == LEARNED_VERSION) {
auto readTable = [&](double t[chess::PIECE_TYPE_NB][64]) -> bool { 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{}; g_counts = ok ? loaded : WinCounters{};
recompute_weights(); recompute_weights();
/* Stale / wrong-version / unreadable: wipe the file's contents (keep the file) by /* Only create a fresh file when none exists yet (first run): write it blank-but-versioned
* rewriting it blank-but-versioned, so the next load matches and we never reread garbage. */ * so there's a valid target to persist into. If a file IS present but couldn't be parsed
if (!ok) * (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(); save_global_weights();
} }