import { GAME_CONFIG, seedStr, updateResetCountdown, fetchConfig, fetchGridForSeed, fetchAndApplyScores, fetchAndApplyActivePlayers, updateEconomyDisplay, loadEconScores, loadVictoryPoints, loadDbInfo, loadElementBonus, refreshFromServer, refreshGridDisplay, loadPlayfieldMask, draw, } from "./game.js"; import { tryRestoreSession, showAuthOverlay, hideAuthOverlay, } from "./auth.js"; // ── DOM refs ────────────────────────────────────────────────────────────────── const hint = document.getElementById("hint"); const cooldownEl = document.getElementById("cooldownConfig"); const burgerBtn = document.getElementById("burgerBtn"); const closeMenuBtn = document.getElementById("closeMenuBtn"); const infoColumn = document.getElementById("infoColumn"); // ── Polling ─────────────────────────────────────────────────────────────────── let configPollTimer = 0; let scorePollTimer = 0; let resetTimer = null; function scheduleConfigPoll() { clearTimeout(configPollTimer); const ms = Math.max(5_000, GAME_CONFIG.configReloadIntervalSeconds * 1_000); configPollTimer = window.setTimeout(async () => { try { const changed = await fetchConfig(); if (changed) await refreshFromServer(); } catch { /* ignore */ } scheduleConfigPoll(); }, ms); } const ECON_TICK_SECONDS = 5; function scheduleScorePoll() { clearTimeout(scorePollTimer); scorePollTimer = window.setTimeout(async () => { await fetchAndApplyScores(); await fetchAndApplyActivePlayers(); await loadEconScores(); await loadElementBonus(); scheduleScorePoll(); }, ECON_TICK_SECONDS * 1_000); } // ── Burger / mobile menu ────────────────────────────────────────────────────── function openMenu() { infoColumn.classList.add("infoColumn--open"); } function closeMenu() { infoColumn.classList.remove("infoColumn--open"); } burgerBtn.addEventListener("click", openMenu); closeMenuBtn.addEventListener("click", closeMenu); // Close when clicking outside the panel (on the galaxy overlay) document.addEventListener("click", (ev) => { if ( infoColumn.classList.contains("infoColumn--open") && !infoColumn.contains(ev.target) && ev.target !== burgerBtn ) { closeMenu(); } }); // ── Boot ────────────────────────────────────────────────────────────────────── async function boot() { // Load the SVG playfield mask before any drawing or data fetch await loadPlayfieldMask(); const restored = await tryRestoreSession(); if (!restored) { showAuthOverlay(); } else { hideAuthOverlay(); } try { await fetchConfig(); await fetchGridForSeed(seedStr); await fetchAndApplyScores(); await fetchAndApplyActivePlayers(); await loadEconScores(); await loadVictoryPoints(); await loadDbInfo(); await loadElementBonus(); updateEconomyDisplay(); } catch { hint.textContent = "API unavailable — start the Node server (docker-compose up --build)."; cooldownEl.textContent = "?"; } draw(); if (resetTimer) clearInterval(resetTimer); resetTimer = setInterval(updateResetCountdown, 1_000); updateResetCountdown(); scheduleConfigPoll(); scheduleScorePoll(); // Refresh VP every 30 s so new awards are reflected promptly setInterval(loadVictoryPoints, 30_000); // Refresh grid every second so all clients see new tiles promptly setInterval(refreshGridDisplay, 1_000); } // ── Start ───────────────────────────────────────────────────────────────────── boot();