add predict bar för overlay

This commit is contained in:
larssand
2026-03-14 19:36:59 +01:00
parent 0d71cd5a18
commit 3069878167
2 changed files with 55 additions and 0 deletions

View File

@@ -442,6 +442,7 @@ const TRANSLATIONS = {
"overlay.fullscreen": "Fullscreen",
"overlay.leaderboard_live": "Live leaderboard",
"overlay.rotating_panel": "Displaypanel",
"overlay.next_predicted_lap": "Nästa varv",
"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å.",
@@ -902,6 +903,7 @@ const TRANSLATIONS = {
"overlay.fullscreen": "Fullscreen",
"overlay.leaderboard_live": "Live leaderboard",
"overlay.rotating_panel": "Display panel",
"overlay.next_predicted_lap": "Next lap",
"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.",
@@ -3796,6 +3798,15 @@ function renderOverlayLeaderboard(rows) {
<div class="overlay-race-driver">
<strong>${escapeHtml(row.driverName)}</strong>
<span>${escapeHtml(row.transponder || "-")}</span>
<div class="overlay-prediction">
<div class="overlay-prediction-meta">
<label>${t("overlay.next_predicted_lap")}</label>
<span>${row.predictedRemainingMs !== null ? formatLap(row.predictedRemainingMs) : "-"}</span>
</div>
<div class="overlay-prediction-track">
<div class="overlay-prediction-fill" style="width:${Math.max(0, Math.min(100, Math.round((row.predictedProgress || 0) * 100)))}%"></div>
</div>
</div>
</div>
<div class="overlay-race-metric">
<label>${t("table.result")}</label>
@@ -4511,6 +4522,7 @@ function buildLeaderboard(session) {
const isFreePractice = sessionType === "free_practice";
const isOpenPractice = sessionType === "open_practice";
const isRollingPractice = isFreePractice || isOpenPractice;
const nowTs = Date.now();
const rows = Object.values(result.competitors).map((row) => {
const totalElapsedMs = getCompetitorElapsedMs(session, row);
const distanceToTargetMs = Math.abs(targetMs - totalElapsedMs);
@@ -4519,6 +4531,15 @@ function buildLeaderboard(session) {
const previousLapMs = passings.length >= 2 ? Number(passings[passings.length - 2].lapMs || 0) : null;
const lapDeltaMs =
row.lastLapMs && previousLapMs && row.lastLapMs > 0 && previousLapMs > 0 ? row.lastLapMs - previousLapMs : null;
const predictionBaseMs =
Number(row.lastLapMs || 0) > 0
? Number(row.lastLapMs)
: Number(row.bestLapMs || 0) > 0
? Number(row.bestLapMs)
: null;
const currentLapElapsedMs = row.lastTimestamp ? Math.max(0, nowTs - row.lastTimestamp) : 0;
const predictedRemainingMs = predictionBaseMs ? Math.max(0, predictionBaseMs - currentLapElapsedMs) : null;
const predictedProgress = predictionBaseMs ? Math.min(1.25, currentLapElapsedMs / predictionBaseMs) : 0;
return {
...row,
totalElapsedMs,
@@ -4526,6 +4547,8 @@ function buildLeaderboard(session) {
seedMetric,
previousLapMs,
lapDeltaMs,
predictedRemainingMs,
predictedProgress,
comparisonMs:
isRollingPractice
? row.bestLapMs || row.lastLapMs || Number.MAX_SAFE_INTEGER

View File

@@ -852,6 +852,38 @@ select:focus {
letter-spacing: 0.08em;
}
.overlay-prediction {
margin-top: 10px;
}
.overlay-prediction-meta {
display: flex;
justify-content: space-between;
gap: 10px;
margin-bottom: 6px;
}
.overlay-prediction-meta label,
.overlay-prediction-meta span {
color: var(--muted);
font-size: 0.72rem;
text-transform: uppercase;
letter-spacing: 0.08em;
}
.overlay-prediction-track {
height: 4px;
border-radius: 999px;
overflow: hidden;
background: rgba(255, 255, 255, 0.08);
}
.overlay-prediction-fill {
height: 100%;
border-radius: 999px;
background: linear-gradient(90deg, #ffffff, #e10600);
}
.overlay-race-metric strong,
.overlay-race-best strong {
font-family: Orbitron, sans-serif;