diff --git a/src/app.js b/src/app.js index 23dad75..55a1a7d 100644 --- a/src/app.js +++ b/src/app.js @@ -242,6 +242,7 @@ const TRANSLATIONS = { "timing.total_passings": "Totala passeringar", "timing.started": "Startad", "timing.remaining": "Nedräkning", + "timing.elapsed": "Körtid", "timing.race_finished": "Race is finished", "timing.no_active": "Ingen aktiv session vald.", "timing.leaderboard": "Live leaderboard", @@ -437,6 +438,8 @@ const TRANSLATIONS = { "overlay.mode_leaderboard": "Leaderboard", "overlay.mode_speaker": "Speaker", "overlay.mode_results": "Resultat", + "overlay.fastest_lap": "Snabbaste varv", + "overlay.fullscreen": "Fullscreen", "overlay.event_markers": "Eventmarkörer", "guide.host_title": "Hur Managed AMMC körs", "guide.host_1": "1. AMMC körs alltid på samma maskin som `npm start` eller `node server.js` körs på.", @@ -697,6 +700,7 @@ const TRANSLATIONS = { "timing.total_passings": "Total passings", "timing.started": "Started", "timing.remaining": "Countdown", + "timing.elapsed": "Elapsed", "timing.race_finished": "Race is finished", "timing.no_active": "No active session selected.", "timing.leaderboard": "Live Leaderboard", @@ -892,6 +896,8 @@ const TRANSLATIONS = { "overlay.mode_leaderboard": "Leaderboard", "overlay.mode_speaker": "Speaker", "overlay.mode_results": "Results", + "overlay.fastest_lap": "Fastest Lap", + "overlay.fullscreen": "Fullscreen", "overlay.event_markers": "Event markers", "guide.host_title": "How Managed AMMC Runs", "guide.host_1": "1. AMMC always runs on the same machine where `npm start` or `node server.js` is running.", @@ -1829,6 +1835,10 @@ function handleSessionTimerTick() { return { changed: false }; } + if (isUntimedSession(active)) { + return { changed: false }; + } + const timing = getSessionTiming(active); if (timing.remainingMs > 0) { return { changed: false }; @@ -3074,6 +3084,8 @@ function renderTiming() { const result = active ? ensureSessionResult(active.id) : null; const leaderboard = active ? buildLeaderboard(active) : []; const sessionTiming = active ? getSessionTiming(active) : null; + const clockLabel = active && sessionTiming?.untimed ? t("timing.elapsed") : t("timing.remaining"); + const clockValue = sessionTiming?.untimed ? formatElapsedClock(sessionTiming?.elapsedMs ?? 0) : formatCountdown(sessionTiming?.remainingMs ?? 0); const showFinishedBanner = Boolean(active && active.status === "finished" && active.finishedByTimer); const selectedRow = leaderboard.find((row) => row.key === selectedLeaderboardKey) || null; if (selectedLeaderboardKey && !selectedRow) { @@ -3127,7 +3139,7 @@ function renderTiming() {
${t("table.start_mode")}: ${escapeHtml(getStartModeLabel(active.startMode))} • ${t("timing.seeding_mode")}: ${ active.seedBestLapCount > 0 ? `${active.seedBestLapCount}` : "-" }
-${t("timing.remaining")}: ${formatCountdown(sessionTiming?.remainingMs ?? 0)}
+${clockLabel}: ${clockValue}
${t("timing.total_passings")}: ${result.passings.length}
${ active.type === "free_practice" @@ -3448,6 +3460,9 @@ function renderOverlay() { const leaderboard = active ? buildLeaderboard(active).slice(0, 12) : []; const result = active ? ensureSessionResult(active.id) : null; const sessionTiming = active ? getSessionTiming(active) : null; + const overlayClock = sessionTiming?.untimed + ? formatElapsedClock(sessionTiming?.elapsedMs ?? 0) + : formatCountdown(sessionTiming?.remainingMs ?? 0); const recent = active && result ? result.passings.slice(-8).reverse() : []; const event = active ? state.events.find((item) => item.id === active.eventId) : null; const branding = resolveEventBranding(event); @@ -3455,6 +3470,8 @@ function renderOverlay() { const qualifyingRows = event ? buildQualifyingStandings(event) : []; const finalRows = event ? buildFinalStandings(event) : []; const topRow = leaderboard[0] || null; + const fastestRow = + [...leaderboard].filter((row) => Number.isFinite(row.bestLapMs)).sort((left, right) => left.bestLapMs - right.bestLapMs)[0] || null; const modeLabel = getOverlayModeLabel(overlayViewMode); dom.view.innerHTML = ` @@ -3470,7 +3487,8 @@ function renderOverlay() {${escapeHtml(branding.brandName)} • ${escapeHtml(getStartModeLabel(active.startMode))} • ${escapeHtml(modeLabel)}
@@ -3546,7 +3564,24 @@ function renderOverlay() { ` : `