Mobilprofilen visar nu per vald klassom det finns depå,mellantids

decoders
This commit is contained in:
larssand
2026-08-25 20:04:14 +02:00
parent abf887dccd
commit 84302a770d
7 changed files with 81 additions and 2 deletions

View File

@@ -1242,7 +1242,7 @@ const TRANSLATIONS = {
"guide.decoder_roles_7": "7. Öppna TCP 9000 och de valfria portarna 9001-9003 i backend-hostens brandvägg om webbläsaren kör på en annan maskin. Port 8081 används för webb/API.",
"guide.decoder_roles_8": "8. Kontrollera i Tidtagning att varje aktiverad roll står som Ansluten. Om main är offline räknas inga varv; om en extrakanal är offline fortsätter vanlig varvräkning.",
"guide.decoder_roles_9": "9. Tidtagning visar live-sammanställning och depåstoppslogg. Race Setup visar samma data per heat, och resultat-PDF inkluderar stoppantal, total depåtid samt varje depå in/ut.",
"guide.decoder_roles_10": "10. Träningsstatistik visar mellantid och depåstopp per personlig förarprofil och vald klass. Vid förarbyte i depån tillhör stoppet föraren och bilen som registrerades vid Depå in.",
"guide.decoder_roles_10": "10. Träningsstatistik och den personliga mobilprofilen visar sanerade mellantids- och depåaggregat per vald klass. Mobilprofilen visar inte transpondrar eller rå depålogg. Vid förarbyte tillhör stoppet föraren och bilen vid Depå in.",
"guide.host_1": "1. AMMC körs alltid på samma maskin som backend körs på (`npm.cmd start` i Windows eller `npm start` i Linux).",
"guide.host_2": "2. Om du bara surfar in från en laptop/webbläsare startas ingen process där. Webbläsaren styr bara backend via HTTP.",
"guide.host_3": "3. Kör backend på Linux-servern -> Linux-binären används: `AMMC/linux_x86-64/ammc-amb`.",
@@ -2274,7 +2274,7 @@ const TRANSLATIONS = {
"guide.decoder_roles_7": "7. Allow TCP 9000 and optional ports 9001-9003 through the backend host firewall when the browser runs on another machine. Port 8081 serves the web UI/API.",
"guide.decoder_roles_8": "8. Verify in Timing that every enabled role is Connected. If main is offline no laps are counted; an offline optional channel does not stop normal lap counting.",
"guide.decoder_roles_9": "9. Timing shows a live summary and pit-stop log. Race Setup shows the same data per heat, and result PDFs include stop count, total pit time, and every pit entry/exit.",
"guide.decoder_roles_10": "10. Training statistics show split and pit data per personal driver profile and selected class. During a pit driver change, the stop remains attributed to the driver and car recorded at Pit entry.",
"guide.decoder_roles_10": "10. Training statistics and the personal mobile profile show sanitized split/pit aggregates per selected class. The mobile profile does not expose transponders or the raw pit log. During a driver change, the stop remains attributed to the driver and car at Pit entry.",
"guide.host_1": "1. AMMC always runs on the backend host (`npm.cmd start` on Windows or `npm start` on Linux).",
"guide.host_2": "2. If you only browse from a laptop/browser, no process is started there. The browser only controls the backend over HTTP.",
"guide.host_3": "3. Run the backend on Linux -> the Linux binary is used: `AMMC/linux_x86-64/ammc-amb`.",

View File

@@ -58,6 +58,10 @@ const messages = {
bestThree: "Bästa 3 sammanhängande",
bestFive: "Bästa 5 min",
fiveAverage: "Avg pace, bästa 5 min",
splitPassings: "Mellantidspasseringar",
bestSplit: "Bästa mellantid",
pitStops: "Depåstopp",
totalPit: "Total depåtid",
},
en: {
loading: "Loading training profile...",
@@ -108,6 +112,10 @@ const messages = {
bestThree: "Best 3 consecutive",
bestFive: "Best 5 min",
fiveAverage: "Average pace, best 5 min",
splitPassings: "Split passings",
bestSplit: "Best split",
pitStops: "Pit stops",
totalPit: "Total pit time",
},
};
@@ -167,6 +175,7 @@ function renderProfile(data) {
let activeClass = classProfiles.find((item) => String(item.classId || "") === selectedClassId) || classProfiles[0] || null;
if (activeClass && selectedClassId !== activeClass.classId) selectedClassId = activeClass.classId;
const stats = activeClass?.stats || data.stats;
const channelStats = activeClass?.channelStats || data.channelStats || {};
const nextMilestone = activeClass?.nextMilestone || data.nextMilestone;
const recommendation = activeClass?.recommendation || data.recommendation;
const goals = activeClass?.goals || data.goals || [];
@@ -275,6 +284,10 @@ function renderProfile(data) {
<div><span>${escapeHtml(t("bestThree"))}</span><strong>${stats.bestThreeConsecutive ? `3/${formatRaceResultTime(stats.bestThreeConsecutive.totalMs)}` : "-"}</strong></div>
<div><span>${escapeHtml(t("bestFive"))}</span><strong>${stats.bestFiveMinuteResult ? `${stats.bestFiveMinuteResult.lapCount}/${formatRaceResultTime(stats.bestFiveMinuteResult.totalMs)}` : "-"}</strong></div>
<div><span>${escapeHtml(t("fiveAverage"))}</span><strong>${stats.bestFiveMinuteResult ? formatLap(stats.bestFiveMinuteResult.averageLapMs) : "-"}</strong></div>
<div><span>${escapeHtml(t("splitPassings"))}</span><strong>${Number(channelStats.splitCount || 0)}</strong></div>
<div><span>${escapeHtml(t("bestSplit"))}</span><strong>${channelStats.splitCount ? formatLap(channelStats.bestSplitMs) : "-"}</strong></div>
<div><span>${escapeHtml(t("pitStops"))}</span><strong>${Number(channelStats.pitStopCount || 0)}</strong></div>
<div><span>${escapeHtml(t("totalPit"))}</span><strong>${channelStats.pitStopCount ? formatRaceResultTime(channelStats.totalPitMs) : "-"}</strong></div>
</div>
</section>