807 lines
38 KiB
Markdown
807 lines
38 KiB
Markdown
# RC RaceCore
|
|
|
|
RC timing app med sponsor-eventflöde (delade bilar/transpondrar mellan olika heat/finaler), AMMC WebSocket och lokal SQLite-lagring på Windows.
|
|
|
|
## Arkitektur
|
|
|
|
- JavaScript-modulöversikt: `docs/javascript-architecture.md`
|
|
- Säkerhets- och prestandaaudit: `docs/security-performance-audit.md`
|
|
- Primär engelsk README: `README.md`
|
|
|
|
## Snabbinstallation På Windows 11
|
|
|
|
Öppna **PowerShell** på den nya Windows-datorn och följ stegen nedan.
|
|
|
|
1. Kontrollera om Git är installerat:
|
|
|
|
```powershell
|
|
git --version
|
|
```
|
|
|
|
2. Om `git` inte känns igen installerar du det och öppnar sedan PowerShell på nytt:
|
|
|
|
```powershell
|
|
winget install --id Git.Git --exact --source winget
|
|
```
|
|
|
|
3. Hämta RC RaceCore och gå till projektmappen:
|
|
|
|
```powershell
|
|
Set-Location $HOME
|
|
git clone https://git.dio.nu/Public/Live_RC.git Live_RC
|
|
Set-Location .\Live_RC
|
|
```
|
|
|
|
4. Kör hela installationen. Den installerar/kontrollerar Node.js, installerar npm-dependencies, verifierar SQLite och startar servern i bakgrunden:
|
|
|
|
```powershell
|
|
.\windows\install.bat
|
|
```
|
|
|
|
5. Kontrollera servern och öppna `http://localhost:8081`:
|
|
|
|
```powershell
|
|
npm.cmd run status
|
|
Invoke-RestMethod -Uri "http://127.0.0.1:8081/api/health"
|
|
```
|
|
|
|
Om `winget` saknas installerar du [Git för Windows](https://git-scm.com/download/win). Repot kan även hämtas som ZIP utan Git. Se den kompletta delen [Installation](#installation) för ZIP-installation, LAN-åtkomst, uppdateringar och felsökning.
|
|
|
|
## Skärmbilder
|
|
|
|
Aktuella layouter för racedrift, livevisning, träning och systemkonfiguration. Klicka på en bild för att öppna den i full upplösning.
|
|
|
|
<table>
|
|
<tr>
|
|
<td width="50%"><a href="docs/screenshots/overview-active-session.jpg"><img src="docs/screenshots/overview-active-session.jpg" alt="Översikt med aktiv session" /></a><br><strong>Översikt med aktiv session</strong></td>
|
|
<td width="50%"><a href="docs/screenshots/race-setup-wizard.jpg"><img src="docs/screenshots/race-setup-wizard.jpg" alt="Race Setup-wizard" /></a><br><strong>Race Setup-wizard</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td width="50%"><a href="docs/screenshots/overlay.jpg"><img src="docs/screenshots/overlay.jpg" alt="Komplett live-overlay" /></a><br><strong>Komplett live-overlay</strong></td>
|
|
<td width="50%"><a href="docs/screenshots/leaderboard-overlay.jpg"><img src="docs/screenshots/leaderboard-overlay.jpg" alt="Leaderboard-overlay" /></a><br><strong>Leaderboard-overlay</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td width="50%"><a href="docs/screenshots/training-overview.jpg"><img src="docs/screenshots/training-overview.jpg" alt="Träningsöversikt" /></a><br><strong>Träningsöversikt</strong></td>
|
|
<td width="50%"><a href="docs/screenshots/training-extra-stats.jpg"><img src="docs/screenshots/training-extra-stats.jpg" alt="Fördjupad träningsstatistik med tempo-heatmap och stintanalys" /></a><br><strong>Fördjupad träningsstatistik</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td width="50%"><a href="docs/screenshots/judging-current.jpg"><img src="docs/screenshots/judging-current.jpg" alt="Domare och racekorrigeringar" /></a><br><strong>Domare och racekorrigeringar</strong></td>
|
|
<td width="50%"><a href="docs/screenshots/race-audio-settings.jpg"><img src="docs/screenshots/race-audio-settings.jpg" alt="Raceljud och utrop" /></a><br><strong>Raceljud och utrop</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td width="50%"><a href="docs/screenshots/decoder-settings.jpg"><img src="docs/screenshots/decoder-settings.jpg" alt="Decoderinställningar" /></a><br><strong>Decoderinställningar</strong></td>
|
|
<td width="50%"></td>
|
|
</tr>
|
|
</table>
|
|
|
|
## Publik Overlay Och OBS
|
|
|
|
Appen har nu en separat publik overlay-route så att du inte behöver exponera hela admin-UI:t externt.
|
|
|
|
- Publik overlay-route: `/public-overlay/<mode>`
|
|
- OBS-läge: `/public-overlay/obs`
|
|
- OBS-overlay konfigureras från menyn `Overlay`:
|
|
- antal rader
|
|
- layout: `leaderboard`, `grid`, `lowerthird`
|
|
- tema: `panel`, `transparent`, `chroma`
|
|
- vilka kolumner och block som ska visas
|
|
- Använd `Kopiera OBS-url` för att få en färdig browser-source-länk till OBS.
|
|
|
|
Om du vill ha ett enkelt skydd för publika overlays, sätt denna miljövariabel på servern:
|
|
|
|
```bash
|
|
PUBLIC_OVERLAY_TOKEN=din-hemliga-token
|
|
```
|
|
|
|
Tokenen skyddar bara overlay-routen. Exponera inte port `8081` direkt mot internet eftersom administrations-API:erna saknar autentisering. Använd betrott race-LAN, VPN eller en autentiserad reverse proxy. Om webbgränssnittet avsiktligt körs från en annan origin anges den i `RC_ALLOWED_ORIGINS` (kommaseparerat). Se [`docs/security-performance-audit.md`](docs/security-performance-audit.md).
|
|
|
|
Då måste den publika overlay-länken innehålla:
|
|
|
|
```text
|
|
/public-overlay/obs?token=din-hemliga-token
|
|
```
|
|
|
|
Rekommenderad deploy:
|
|
- publicera bara `/public-overlay/*` via reverse proxy
|
|
- håll huvudappen/admin internt
|
|
|
|
## Vad som ingår
|
|
- Event-lägen:
|
|
- `Race (driver transponders)`
|
|
- `Track Event (shared cars)`
|
|
- UI-separering:
|
|
- `Event` = sponsor-event med delade bilar/transpondrar
|
|
- `Race Setup` = otidsstyrd Open Practice eller riktiga race med personlig transponder per förare
|
|
- Grupperad meny följer arbetsordningen: `Start`, `Skapa`, `Kör och följ`, `Register` samt `System och hjälp`.
|
|
- `Översikt -> Kom igång` länkar direkt till systeminställningar, förarregister, race/practice, Tidtagning och Overlay.
|
|
- Race Day-drift:
|
|
- fokuserad heat-kö med Pågår, Nästa och Därefter
|
|
- förkontroll av decoder, deltagare, transpondrar, dubbla ID, varvfönster, grid och ljud
|
|
- samma start-, stopp- och pauslogik som den befintliga Tidtagning-vyn
|
|
- automatisk konsistent SQLite-backup före varje sessionstart, full dataimport och datarensning
|
|
- de 30 senaste serverbackuperna visas under `Inställningar -> Lagring`
|
|
- Lagring/import:
|
|
- full export/import av race-data för backup eller flytt till annan maskin
|
|
- register-export/import för bara klasser, förare och bilar
|
|
- CSV-export och säker sammanslagande CSV-import för förare och bilar via Excel eller LibreOffice
|
|
- export/import av ett enskilt racepaket via `Race Setup -> Hantera -> Race actions`
|
|
- `Race Setup` innehåller nu även:
|
|
- `Snabbstart Open Practice`: ange bara ett namn, skapa en otidsstyrd session för alla transpondrar och fortsätt direkt till Tidtagning
|
|
- ingen klass, registrerad förare, preset, kval, final eller tidslängd krävs för Snabbstart Open Practice
|
|
- grupperade sektioner för `Deltagare` och `Lag` i `Hantera`
|
|
- en fyrstegs `Create Race Wizard` för nya race
|
|
- `Hantera` uppdelad i `Setup`, `Format`, `Generering` och `Live / resultat`
|
|
- Grundläge reagerar nu på valt preset, inklusive renare endurance-vy
|
|
- `Grundläge / Avancerat` för `Raceformat`
|
|
- en sammanfattningspanel till höger
|
|
- ett presetstyrt sammanfattningskort som växlar mellan endurance- och vanligt race-fokus
|
|
- statusbrickor för `Setup`, `Format`, `Generering` och `Live / resultat`
|
|
- sammanfattningsvarningar när deltagare, sessioner, lag eller varvfönster saknas
|
|
- klickbara sammanfattningsvarningar som hoppar till rätt del av Hantera
|
|
- klickbara stegkort som fungerar som snabbnavigering i `Hantera`
|
|
- kompaktare stegkort med levande räknare för t.ex. förare, lag, sessioner och aktiv/resultat-status
|
|
- separata `Race actions` för generering, reseeding och bump-up
|
|
- omgjord inbyggd `Guide` med översiktskort och tvåkolumnslayout
|
|
- välj exakt vilka förare som är med i racet
|
|
- practice-ranking
|
|
- kval-ranking med `poäng` eller `bästa resultat`
|
|
- inbyggd guide för hur man skapar race steg för steg
|
|
- beskrivningar direkt i alla fält under `Raceformat`
|
|
- `Follow-up tid` efter ordinarie racetid innan heatet stängs
|
|
- `Min varvtid` och `Max varvtid` för att filtrera shortcuts/felträffar och styra bättre statistik/stintlogik
|
|
- seedmetoder för practice/kval: bästa N varv som summa, snitt eller konsekutiva varv
|
|
- valbar kval-poängtabell och tie-break-regler
|
|
- presets i `Raceformat` för kort teknisk bana, klubbrace, IFMAR-liknande upplägg och endurance
|
|
- schemaavvikelse på `Översikt` mellan planerad och faktisk körtid
|
|
- sessionstyp `Free Practice` för löpande varvtider utan seedning
|
|
- auto-generering av kvalheat från practice-ranking eller klasslista
|
|
- reseeding av kommande kvalheat från aktuell ranking
|
|
- auto-generering av `A/B/C...` finaler från ranking
|
|
- sparad manuell grid per session via dragbar grid-editor
|
|
- auto-reseed hoppar över heat där manuell grid har låsts tills du återställer den
|
|
- tydlig `Lås/Lås upp grid` i grid-editorn per session
|
|
- final-ranking över flera leg med räknade finalheat
|
|
- valbar `bump-up` mellan finaler
|
|
- reserverade bump-platser i högre finaler
|
|
- visuell finalmatris med reserverade bump-platser
|
|
- dragbar grid-editor för positionsstart
|
|
- utskrift/export av heatsheets per kval/final
|
|
- overlay-vy för extern leaderboard-skärm
|
|
- flera overlay-lägen: leaderboard, speaker och results
|
|
- speaker-overlay med eventmarkörer och separata speaker-cues
|
|
- live speaker-panel i `Timing` för att slå av/på cues under pågående session
|
|
- speaker-cues och klubbbranding för sidomeny, overlay, publik träningsprofil och PDF styrs från `Inställningar`
|
|
- uppladdad klubblogotyp används i sidomeny, overlay, publik träningsprofil och PDF
|
|
- branding per event/race med egen logo, tagline, footer och PDF-tema i `Hantera`
|
|
- extra speaker-cues för `session start`, `new best lap` och `top 3 change`
|
|
- valbart PDF-tema: `classic`, `minimal`, `motorsport`
|
|
- utskrift av startlistor och resultat med vald branding
|
|
- servergenererad PDF-export för startlistor, heatsheets och resultat med inbäddad logo
|
|
- genererade kval/finaler ärver tid och starttyp från raceformatet
|
|
- finish-ljud som siren i stället för browser-röst
|
|
- Sessioner: `practice`, `qualification`, `heat`, `final`
|
|
- Sponsor-verktyg:
|
|
- Skapa rundor automatiskt (`qualification`, `heat`, `final`)
|
|
- Auto-assign förare -> bil per session
|
|
- Live timing från AMMC WebSocket (`msg: "PASSING"`)
|
|
- Hanterad AMMC från webbgränssnittet:
|
|
- backend kan starta/stoppa lokal `ammc-amb` på Windows, Linux och macOS
|
|
- läser bundlade binärer från `AMMC/windows64`, `AMMC/linux_x86-64`, `AMMC/apple_m`
|
|
- Redigering i UI:
|
|
- Klasser, eventnamn/datum, förare och bilar kan redigeras direkt
|
|
- förare och bilar har valfria brandfält för team, sponsor, märke eller modell
|
|
- `Förare` och `Bilar` kan sökas på namn, transponder eller brand direkt i UI
|
|
- startlistor och heatsheets tar med förarens brand i print, CSV och PDF-export
|
|
- Live race-kontroll:
|
|
- Nedräkning under pågående session
|
|
- Auto-finish vid tidslut med status `Race is finished`
|
|
- Leaderboard-sortering: varv först, därefter närmast måltid för sessionen (t.ex. 5 min = 300s)
|
|
- Konfigurerbart browserljud för start, mål och passing (`blipp` eller tala förarnamn)
|
|
- Valbar systemröst, talhastighet/tonhöjd och separat fonetiskt uttalsnamn per förare
|
|
- Sessioninställningar för `Mass start`, `Position start`, `Staggered`
|
|
- `Timing` visar grid/startordning för aktiv `Position start`-session
|
|
- leaderboard visar både `gap till ledaren`, `gap till bilen framför` och `eget delta` mot förra varvet
|
|
- `Senaste passeringar` visar nu även ogiltiga varv med status `För kort varv` eller `Över maxvarv`
|
|
- manuella korrigeringar i `Tidtagning -> Detaljer`: `+1/-1 varv`, `+1/+5/-1 sek`, `Nollställ korrigering`
|
|
- Practice/Kval kan seedas på bästa `2` eller `3` varv i sessionsinställningar
|
|
- Persistens:
|
|
- Frontend state i browser (`localStorage`)
|
|
- Samma state + passeringar sparas i lokal SQLite via Node-backend
|
|
- Inbyggd `Guide`-meny i appen med steg-för-steg för:
|
|
- Sponsor-event (10 personer / 4 bilar)
|
|
- Vanligt race
|
|
- ogiltiga varv, follow-up och manuella korrigeringar
|
|
- AMMC + npm setup på Windows och Linux
|
|
- Språkval i UI: `SV` / `EN`
|
|
|
|
## Träning Och Belöningar
|
|
|
|
Menyn `Träning` ger förarna utveckling och delmål även mellan tävlingarna:
|
|
|
|
Grundvyn är en klubböversikt med totaler och en separat rad per förare och klass. Välj en förare i listan för att öppna den avsiktligt enkla personliga vyn med fyra nyckeltal, nästa varvmål, dagens träningspass och aktiva belöningar. Administration av mål, mobildelning och detaljhistorik finns kvar i utfällbara sektioner när de behövs.
|
|
|
|
När Open Practice, Free Practice eller Practice pågår får vald förare ett kompakt livekort med aktuella giltiga varv, bästa varv, snitt och senaste varv. Sessionen är fortfarande gemensam för alla; endast mobilens personliga timer och profillänk är unik per förare och klass. Primärknappen högst upp skapar eller öppnar länken.
|
|
|
|
En person kan ha flera förarposter för exempelvis 2WD och 4WD och länka dem till samma `Träningsprofil` under `Förare`. Personen får då en profil och en mobillänk, men all prestandastatistik väljs och beräknas separat per klass. Flera transpondrar inom samma klass summeras däremot i den klassens statistik.
|
|
|
|
Förarprofilen kan även lagra `Klubb` och `Land`. Värdena ärvs när ytterligare klassposter länkas till samma träningsprofil och följer med full JSON- och förar-CSV-export. De lämnas inte ut av den publika profillänken.
|
|
|
|
- beständig logg med totalt antal giltiga varv synkad från sparade sessionsresultat
|
|
- träningsdagar, antal sessioner, personbästa, total-/30-varvssnitt, kontrollerad varvserie och spridning
|
|
- automatisk ny stint efter ett glapp på mer än 2 minuter mellan passeringar
|
|
- bästa 3 sammanhängande varv samt bästa femminutersresultat med dess avg pace
|
|
- femminutersresultatet räknar slutvarvet om det startade före `5:00` (`300 s`), även när målgången sker efter tidsgränsen
|
|
- daglig historik för de senaste träningsdagarna och förbättring mot tidigare personbästa
|
|
- personlig utvecklingstrend som jämför de senaste 30 giltiga varven med föregående 30, alltid separat per klass
|
|
- automatiska achievements för första passet, varvmängd, träningsdagar, kontrollerade varvserier och fullföljd femminutersstint
|
|
- tre frivilliga dagsutmaningar för giltiga varv, kontrollerade varv i följd och fullföljd femminutersstint
|
|
- en positiv personlig summering som ger kredit för dagens mängd, personbästa, tempo, jämnhet och uthållighet utan att ranka förare
|
|
- klubbfeed sorterad på senaste aktivitet i stället för placering eller totalvarvsranking
|
|
- konfigurerbart gemensamt klubbmål som räknar alla nya giltiga träningsvarv från registrerade förare från det att målet skapas
|
|
- en gemensam hopfällbar Mer statistik-del med aktiva 30-minutersblock baserade på trimmat snitt
|
|
- klasspecifika setupmarkörer för däck, dämpare, bilbyte eller egen notering med automatisk jämförelse 30 minuter före/efter
|
|
- detaljerad stintanalys med normaltempo, bästa race pace över 10 varv, misstag, konsekvens och utveckling mellan start/slut
|
|
- automatiska utvecklingsnivåer vid lämpliga varvantal utan manuell konfiguration
|
|
- rekommenderat träningspass med valbara minuter för maxfokus och kontrollerad körning på 80-90 procent
|
|
- egna varvmål med snabbval på `500`, `1000` och `1500` varv
|
|
- valfri reward/belöning och markering när den har delats ut
|
|
- responsiv layout som kan öppnas från mobilen via samma server i det lokala nätet
|
|
|
|
Direktlänk för mobil/bokmärke: `http://<server-ip>:8081/?view=training`. När en profil och klass väljs läggs de i länken så rätt vy kan sparas som bokmärke.
|
|
|
|
Träningsstatistiken räknar just nu bara giltiga varv som är kopplade till en registrerad förare. Anonyma transpondrar från Open Practice räknas inte förrän de kopplats till en förare.
|
|
|
|
Domarkorrigeringar uppdaterar loggade varv så länge källsessionen finns kvar. När sessionen senare tas bort ligger de synkade träningsvarven kvar så förarens livstidsutveckling inte försvinner. Full dataexport inkluderar varvloggen, belöningsmålen och setupmarkörerna.
|
|
|
|
### Skrivskyddad mobilprofil
|
|
|
|
Varje registrerad förare kan få en valfri personlig mobillänk:
|
|
|
|
1. Öppna `Träning` och välj föraren.
|
|
2. Öppna `Mål och mobilprofil` och klicka sedan `Aktivera mobilprofil`.
|
|
3. Kopiera eller öppna länken som skapas.
|
|
4. Använd `Skapa ny länk` för att återkalla den gamla eller `Stäng av profil` för att stoppa delningen.
|
|
|
|
Länken använder en slumpad 192-bitars bearer-nyckel i stället för förar-ID. Samma länk visar profilens klasser i ett klassval, med helt separata varvtider och träningsresultat. Det publika API:t lämnar inte ut transponder-ID, andra förares namn, klubbrankning, race setup eller admin-state.
|
|
|
|
Mobilsidan har också en lokal träningstimer där föraren själv väljer minuter för `Maxfokus` och `Kontrollerad`. Standard är `10 + 10`, men ett femminutersheat kan exempelvis köras som `5 + 0`. Medan en gemensam Free Practice fortsätter vara igång visar kortet just den förarens antal varv, bästa varv och snitt sedan den personliga timern startades. Timer och tidsval sparas bara i mobilens webbläsare, separat per förare och klass, och ändrar ingen racedata. Tiderna låses medan passet pågår och kan ändras efter målgång eller nollställning.
|
|
|
|
Vid extern publicering ska bara dessa paths proxas:
|
|
|
|
```text
|
|
/public-training/*
|
|
/src/public_training.js
|
|
/src/public_training.css
|
|
```
|
|
|
|
Exponera inte `/api/state` eller hela admin-appen. Statisk servering är begränsad till `/src` och `/docs`; `data/`, serverscripts och bundlade binärer publiceras inte som statiska filer.
|
|
|
|
Regressionstesterna använder Node:s inbyggda testverktyg och kräver inget extra testramverk. Sviten täcker träningsprofiler, racegenerering och tidtagning, domarkorrigeringar, frontend/backend-synk samt ett isolerat SQLite API-test med en temporär datamapp:
|
|
|
|
```bash
|
|
npm test
|
|
```
|
|
|
|
Integrationstestet startar en egen backend på en temporär localhost-port och läser eller skriver aldrig den vanliga databasen `data/rc_timing.sqlite`.
|
|
|
|
|
|
## Create Race Wizard
|
|
- `Race Setup` startar nu med en fyrstegs wizard för nya race:
|
|
- `Grunddata`
|
|
- `Deltagare`
|
|
- `Sessionsplan`
|
|
- `Bekräfta`
|
|
- Wizarden är till för att snabbt skapa första grundstrukturen:
|
|
- välj klass och preset
|
|
- välj vilka förare som faktiskt ska vara giltiga i racet
|
|
- skapa practice, kval och/eller team race automatiskt
|
|
- Finaler skapas fortfarande senare från `Race actions` när practice eller kval är färdiga.
|
|
|
|
## Hantera-flödet
|
|
- Efter att racet skapats är `Hantera` uppdelat i fyra tydliga steg:
|
|
- `Setup`
|
|
- `Format`
|
|
- `Generering`
|
|
- `Live / resultat`
|
|
- `Setup` används för racedeltagare och lag. Stegkorten högst upp fungerar också som snabbnavigering mellan de fyra blocken.
|
|
- `Format` används för practice/kval, finaler, validering, presets och avancerade val. I Grundläge döljer endurance de flesta kval-/finalfält tills du öppnar Avancerat.
|
|
- `Generering` ligger separat så knappar för kval, reseeding, finaler och bump-up inte blandas ihop med raceformatet.
|
|
- `Live / resultat` är där grid, standings, print, PDF och finalmatris används när upplägget väl är klart.
|
|
|
|
## Export / Import
|
|
- `Inställningar -> Lagring` stöder nu:
|
|
- full JSON-export/import för hela tävlingsdatabasen
|
|
- register-JSON för bara klasser, förare och bilar
|
|
- CSV-export och sammanslagande CSV-import för förare och bilar; komma, semikolon och tabb stöds
|
|
- separat rensning av förare, bilar, klasser, race/sessioner eller träningsstatistik
|
|
- `Rensa all tävlingsdata` behåller decoder-, tema-, branding- och serverinställningar
|
|
- `Race Setup -> Hantera -> Race actions` stöder nu enskilda racepaket:
|
|
- exportera ett race med dess sessioner, resultat och refererade klasser/förare/bilar
|
|
- importera paketet på en annan installation som ett nytt race
|
|
- JSON-exporter innehåller nu även exportmetadata och ett schema-/versionsfält för säkrare import framåt.
|
|
- CSV-import från systemets egen export bevarar ID:n. Externa listor utan ID matchas först på transponder och därefter på namn + klass. Tomma fält skriver inte över befintlig information, och nya klassnamn skapas automatiskt.
|
|
- Förarimport kräver bara kolumnen `name` eller `namn`. Rekommenderat minimum är `name;transponder;class`. Valfria kolumner som `brand`, `spoken_name`, `club`, `country` och `profile_id` får saknas; okända kolumner ignoreras och rader utan namn hoppas över.
|
|
|
|
```csv
|
|
name;transponder;class;brand;club;country
|
|
Anna Andersson;123456;2WD;;JMK;SE
|
|
Erik Eriksson;654321;4WD;Associated;;
|
|
```
|
|
|
|
- En tom CSV-mall kan laddas ner direkt vid förarimporten under `Inställningar -> Lagring`.
|
|
- Ta en JSON-backup före rensning. Varje rensningsknapp kräver en separat bekräftelse och åtgärden kan inte ångras.
|
|
- Webbrensningen tömmer kanonisk appdata men behåller den separata råa `passings`-tabellen i SQLite som revisionslogg. En fysisk fabriksrensning av databasen ska göras lokalt på servern när processen är stoppad, inte via en oautentiserad LAN-route.
|
|
|
|
## Nya racefunktioner
|
|
|
|
### Follow-up time
|
|
- Ställs i `Race Setup -> Hantera -> Raceformat`
|
|
- Kan också sättas per session när du skapar eller redigerar en session
|
|
- När ordinarie tid går ut går sessionen först in i `Follow-up aktiv`
|
|
- När follow-up-tiden är slut stängs sessionen automatiskt
|
|
- Genererade kval/finaler ärver follow-up från raceformatet
|
|
|
|
### Min / Max varvtid
|
|
- Ställs i `Race Setup -> Hantera -> Raceformat`
|
|
- `Min varvtid`:
|
|
- varv snabbare än gränsen ignoreras som shortcut eller felträff
|
|
- `Max varvtid`:
|
|
- varv långsammare än gränsen räknas inte som giltigt varv
|
|
- används också för att bryta stintar och förbättra statistik
|
|
|
|
Praktiskt exempel:
|
|
- bana runt `16 sek/varv`
|
|
- `Min varvtid = 11 sek`
|
|
- `Max varvtid = 60 sek`
|
|
|
|
### Ogiltiga passeringar
|
|
- `Tidtagning -> Senaste passeringar` visar nu både giltiga och ogiltiga passeringar
|
|
- status som visas:
|
|
- `För kort varv`
|
|
- `Över maxvarv`
|
|
- ogiltiga passeringar markeras visuellt i listan
|
|
|
|
### Manuella korrigeringar
|
|
- öppna `Tidtagning`
|
|
- klicka `Detaljer` på en förare / ett lag
|
|
- där finns:
|
|
- `+1 varv`
|
|
- `-1 varv`
|
|
- `+1 sek`
|
|
- `+5 sek`
|
|
- `-1 sek`
|
|
- `Nollställ korrigering`
|
|
- korrigeringarna uppdaterar leaderboard och resultat direkt
|
|
|
|
### Best laps / average / consecutive
|
|
- Ställs per session med `Seedmetod` när `Seed bästa varv` är större än `0`
|
|
- tillgängliga lägen:
|
|
- `Bästa N varv, summa`
|
|
- `Bästa N varv, snitt`
|
|
- `Bästa N konsekutiva varv`
|
|
- leaderboard och ranking visar rätt format beroende på läge:
|
|
- summa: `3/00:48.321`
|
|
- snitt: `3 avg 16.107`
|
|
- konsekutiva: `3 con 00:49.005`
|
|
|
|
### Poängtabeller och tie-break
|
|
- Ställs i `Race Setup -> Hantera -> Raceformat`
|
|
- poängtabeller för kval:
|
|
- `Placeringstal (1,2,3...)`
|
|
- `Fallande efter fältstorlek`
|
|
- `10-9-8-7-6-5-4-3-2-1`
|
|
- tie-break för kvalranking:
|
|
- `Jämför räknade rundor`
|
|
- `Bästa enskilda varv`
|
|
- `Bästa runda / heatresultat`
|
|
- kvalrankingen visar även en underrad med aktiv tie-break-information i tabellen
|
|
|
|
### Raceformat presets
|
|
- `Race Setup -> Hantera -> Raceformat`
|
|
- välj ett preset och klicka `Applicera preset`
|
|
- tillgängliga presets:
|
|
- `Kort teknisk bana 16s`
|
|
- `Klubbrace kval + final`
|
|
- `IFMAR-stil kval/final`
|
|
- `Endurance / lagrace`
|
|
- efter applicering kan alla fält fortfarande justeras manuellt och sparas som vanligt
|
|
- `Spara klubb-preset` lagrar egna lokala presets i appens state så de kan återanvändas på samma installation
|
|
- `Ta bort klubb-preset` tar bort ett lokalt preset igen
|
|
- `Inställningar -> Klubb-presetar` kan exportera/importera presetbiblioteket som JSON mellan installationer
|
|
|
|
### Schemaavvikelse på Översikt
|
|
- `Översikt` visar nu om dagen ligger före eller efter schema
|
|
- planerad tid räknar:
|
|
- sessionens varaktighet
|
|
- plus follow-up tid
|
|
- faktisk tid räknar:
|
|
- verklig tid från start till stopp
|
|
- eller pågående körtid om sessionen fortfarande kör
|
|
|
|
### Invalid-lap markering i leaderboard
|
|
- om senaste mottagna passing för en förare/ett lag var ogiltig markeras raden även i leaderboard och overlay
|
|
- det gör det lättare att se felträffar utan att behöva stå i `Senaste passeringar`
|
|
|
|
### Manuell invalidate last lap
|
|
- `Tidtagning -> Detaljer`
|
|
- knappen `Ogiltigförklara senaste varv` markerar senaste räknade varv som manuellt ogiltigt
|
|
- leaderboard, overlay och passings-historik uppdateras direkt
|
|
- `Återställ senaste manuellt ogiltiga varv` lägger tillbaka senaste manuellt ogiltiga varvet om du ångrar dig
|
|
|
|
### Domarvy
|
|
- ny meny `Domare`
|
|
- visar aktiv session, leaderboard, lap history och domarlogg i samma vy
|
|
- samma korrigeringar som i `Tidtagning -> Detaljer` finns där som snabbknappar
|
|
- filter för:
|
|
- `Alla`
|
|
- `Ogiltiga`
|
|
- `Korrigerade`
|
|
- `Team race`
|
|
- domarloggen kan exporteras per session som JSON
|
|
- både `Ångra senaste` och undo-knapp per loggrad finns för flera manuella åtgärder
|
|
|
|
## Framtida förbättringar
|
|
- Valfri neural text-till-tal för naturligare uppläsning av start, mål och förarnamn.
|
|
- Rekommenderad lösning: generera tal via backend, cacha korta ljudfiler under `data/tts/` och spela cachat ljud utan nätverksfördröjning under racet.
|
|
- Leverantörens API-nyckel ska endast finnas i backend och aldrig exponeras i webbläsaren eller publik overlay.
|
|
- Nuvarande systemröst och passing-blipp behålls som offline-fallback.
|
|
- Uppladdade eller förinspelade WAV/MP3-filer kan användas för fasta start- och målmeddelanden.
|
|
|
|
## Installation
|
|
|
|
RC RaceCore körs på 64-bitars Windows 11 och Linux. Använd Node.js 22 eller 24 LTS och npm 10 eller senare. Repot innehåller `package-lock.json`, så använd `npm ci` i stället för `npm install` för en reproducerbar installation.
|
|
|
|
### Windows 11 - ny dator
|
|
|
|
#### 1. Installera Git
|
|
|
|
Öppna PowerShell och kontrollera om Git finns:
|
|
|
|
```powershell
|
|
git --version
|
|
```
|
|
|
|
Om Windows svarar att `git` inte känns igen installerar du Git med Windows Package Manager:
|
|
|
|
```powershell
|
|
winget install --id Git.Git --exact --source winget
|
|
```
|
|
|
|
Stäng och öppna PowerShell efter installationen och kör sedan `git --version` igen. Om `winget` saknas kan Git för Windows installeras från [git-scm.com](https://git-scm.com/download/win).
|
|
|
|
#### 2. Hämta RC RaceCore
|
|
|
|
Klona det publika repot från ett vanligt PowerShell-fönster:
|
|
|
|
```powershell
|
|
Set-Location $HOME
|
|
git clone https://git.dio.nu/Public/Live_RC.git Live_RC
|
|
Set-Location .\Live_RC
|
|
```
|
|
|
|
Skriv den rena URL:en exakt som ovan. Klistra inte in Markdown-format som `[https://...](https://...)` i PowerShell.
|
|
|
|
Om du inte vill installera Git öppnar du [det publika repot](https://git.dio.nu/Public/Live_RC), laddar ner ZIP-arkivet och packar upp hela arkivet. Kontrollera att `package.json`, `server.js`, `src\` och `windows\` ligger i samma projektmapp.
|
|
|
|
#### 3. Kör Windows-installationen
|
|
|
|
Från projektmappen:
|
|
|
|
```powershell
|
|
.\windows\install.bat
|
|
```
|
|
|
|
Du kan även dubbelklicka på `windows\install.bat` i Utforskaren. Installationen:
|
|
|
|
- installerar Node.js LTS via `winget` om Node saknas eller har fel version
|
|
- installerar/kontrollerar Microsoft Visual C++ Runtime som AMMC använder
|
|
- kör `npm.cmd ci` med låsta dependency-versioner
|
|
- verifierar Express, SQLite och bundlade AMMC-filer
|
|
- skapar `data\` och `logs\`
|
|
- kör `npm.cmd restart` och lämnar RC RaceCore igång i bakgrunden
|
|
|
|
Om installationen inte kan installera Node automatiskt installerar du Node.js 22 eller 24 LTS från [nodejs.org](https://nodejs.org/en/download), öppnar PowerShell igen och kör installationen på nytt.
|
|
|
|
#### 4. Verifiera och öppna sidan
|
|
|
|
```powershell
|
|
npm.cmd run status
|
|
Invoke-RestMethod -Uri "http://127.0.0.1:8081/api/health"
|
|
```
|
|
|
|
Öppna:
|
|
|
|
```text
|
|
http://localhost:8081
|
|
```
|
|
|
|
För att öppna RC RaceCore från en annan dator på race-nätverket kör du `ipconfig` på servern och använder:
|
|
|
|
```text
|
|
http://<windows-server-ip>:8081
|
|
```
|
|
|
|
Använd `npm.cmd` i PowerShell. Det undviker det vanliga felet `npm.ps1 cannot be loaded because running scripts is disabled`. Vanliga `npm` fungerar normalt i Kommandotolken.
|
|
|
|
#### Manuell Windows-installation
|
|
|
|
Om du inte använder `install.bat`:
|
|
|
|
```powershell
|
|
node --version
|
|
npm.cmd --version
|
|
npm.cmd ci
|
|
npm.cmd run verify
|
|
npm.cmd start
|
|
```
|
|
|
|
Använd inte `npm.cmd ci --ignore-scripts`. Den inbyggda SQLite-modulen behöver sitt installationsskript.
|
|
|
|
### Linux - Ubuntu/Debian
|
|
|
|
#### 1. Installera Git och grundverktyg
|
|
|
|
```bash
|
|
sudo apt update
|
|
sudo apt install -y git curl build-essential
|
|
git --version
|
|
```
|
|
|
|
#### 2. Installera Node.js 22 LTS vid behov
|
|
|
|
Kontrollera installerad version:
|
|
|
|
```bash
|
|
node --version
|
|
npm --version
|
|
```
|
|
|
|
Om Node saknas eller är äldre än version 22 installerar du Node.js 22 via NodeSource:
|
|
|
|
```bash
|
|
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
|
|
sudo apt install -y nodejs
|
|
node --version
|
|
npm --version
|
|
```
|
|
|
|
Node.js 22 eller 24 LTS rekommenderas. Node.js 18 och 20 stöds inte av nuvarande native SQLite-dependency.
|
|
|
|
#### 3. Klona, installera och starta
|
|
|
|
```bash
|
|
mkdir -p ~/git
|
|
cd ~/git
|
|
git clone https://git.dio.nu/Public/Live_RC.git Live_RC
|
|
cd Live_RC
|
|
npm ci
|
|
npm run verify
|
|
chmod +x AMMC/linux_x86-64/ammc-amb
|
|
npm start
|
|
npm run status
|
|
curl http://127.0.0.1:8081/api/health
|
|
```
|
|
|
|
`npm start` kör RC RaceCore i bakgrunden. Öppna `http://localhost:8081`, eller hitta Linux-serverns adress med `hostname -I` och öppna `http://<linux-server-ip>:8081` från en annan dator.
|
|
|
|
Om den bundlade Linux-versionen av AMMC rapporterar att en `GLIBC`-version saknas behöver du en AMMC-binär som är byggd för hostens Linuxdistribution. Byt inte operativsystemets glibc manuellt.
|
|
|
|
### Driftkommandon
|
|
|
|
Windows PowerShell:
|
|
|
|
```powershell
|
|
npm.cmd start
|
|
npm.cmd run status
|
|
npm.cmd restart
|
|
npm.cmd stop
|
|
npm.cmd run start:fg
|
|
```
|
|
|
|
Linux:
|
|
|
|
```bash
|
|
npm start
|
|
npm run status
|
|
npm restart
|
|
npm stop
|
|
npm run start:fg
|
|
```
|
|
|
|
- `start` kör backend i bakgrunden
|
|
- `status` visar om PID-filen i `data/server.pid` motsvarar en aktiv process
|
|
- `restart` laddar om ändringar i backend
|
|
- `stop` stoppar den hanterade processen
|
|
- `start:fg` kör i terminalen och visar startfel direkt
|
|
- stdout skrivs till `logs/server.out.log`
|
|
- stderr skrivs till `logs/server.err.log`
|
|
- SQLite-data lagras i `data/rc_timing.sqlite`
|
|
|
|
### Windows hjälpskript
|
|
|
|
- `windows\install.bat`: installerar dependencies, verifierar och startar om
|
|
- `windows\start_backend.bat`: startar backend i bakgrunden
|
|
- `windows\restart_backend.bat`: startar om efter kopierad eller hämtad uppdatering
|
|
- `windows\start_ammc.bat`: startar bundlad AMMC manuellt
|
|
- `windows\start_all.bat`: startar AMMC och backend samt öppnar webbläsaren
|
|
- `windows\stop_all.bat`: stoppar backend och `ammc-amb.exe`
|
|
|
|
### Återställ en serverbackup
|
|
|
|
Backuper lagras i `data/backups/`. Återställning är avsiktligt ett lokalt serverkommando och exponeras inte via det oautentiserade webb-API:t.
|
|
|
|
1. Stoppa RC RaceCore.
|
|
2. Kopiera backupfilens namn från `Inställningar -> Lagring` eller lista filerna i `data/backups/`.
|
|
3. Kör restore-kommandot med den uttryckliga bekräftelseflaggan.
|
|
4. Starta RC RaceCore igen.
|
|
|
|
Windows PowerShell:
|
|
|
|
```powershell
|
|
npm.cmd stop
|
|
$backup = Get-ChildItem .\data\backups\*.sqlite | Sort-Object LastWriteTime -Descending | Select-Object -First 1
|
|
$backup.Name
|
|
npm.cmd run backup:restore -- $backup.Name --confirm
|
|
npm.cmd start
|
|
```
|
|
|
|
Linux:
|
|
|
|
```bash
|
|
npm stop
|
|
backup=$(find data/backups -maxdepth 1 -name '*.sqlite' -printf '%T@ %f\n' | sort -nr | head -n 1 | cut -d' ' -f2-)
|
|
printf 'Återställer %s\n' "$backup"
|
|
npm run backup:restore -- "$backup" --confirm
|
|
npm start
|
|
```
|
|
|
|
Restore-kommandot validerar vald SQLite-fil och skapar en `pre_restore`-backup av nuvarande databas innan den ersätts.
|
|
|
|
### Uppdatera utan att förlora data
|
|
|
|
SQLite-databasen och lokal konfiguration ligger i `data/`. Radera eller ersätt aldrig den katalogen vid en uppdatering.
|
|
|
|
Windows:
|
|
|
|
```powershell
|
|
npm.cmd stop
|
|
git pull --ff-only
|
|
npm.cmd ci
|
|
npm.cmd run verify
|
|
npm.cmd restart
|
|
npm.cmd run status
|
|
```
|
|
|
|
Linux:
|
|
|
|
```bash
|
|
npm stop
|
|
git pull --ff-only
|
|
npm ci
|
|
npm run verify
|
|
npm restart
|
|
npm run status
|
|
```
|
|
|
|
Om installationen kommer från ett ZIP-arkiv i stället för Git säkerhetskopierar du `data/`, packar upp de nya programfilerna, återställer/behåller befintlig `data/`, kör `npm ci` och startar om. Kopiera aldrig `node_modules/` mellan Windows och Linux.
|
|
|
|
## Koppla mot AMMC
|
|
Det finns nu två sätt:
|
|
|
|
Komplett nätverksdiagram, färdiga exempel för 1/2/3/4 decoders, brandvägg och felsökning finns i [`docs/decoder-setup.sv.md`](docs/decoder-setup.sv.md). Engelsk version: [`docs/decoder-setup.md`](docs/decoder-setup.md).
|
|
|
|
### A. Hanterad AMMC i webbgränssnittet
|
|
Viktigt:
|
|
- AMMC körs på samma Windows-host där backend startades med `npm.cmd start`.
|
|
- Om du öppnar sidan från en annan laptop startas ingen AMMC där.
|
|
- Fältet `AMMC binär` i `Settings` är en sökväg på backend-hosten, inte på klienten som surfar in.
|
|
|
|
#### Koppling av decoders
|
|
|
|
| Roll | Fysisk placering | Exempel decoder-IP | AMMC WS-port | Funktion |
|
|
|---|---|---:|---:|---|
|
|
| Main start/mål | Start-/målloop | `192.168.1.10` | `9000` | Räknar varv och bestämmer varvtid |
|
|
| Mellantid | Mellantidsloop | `192.168.1.11` | `9001` | Tid från senaste main-passering; räknar aldrig varv |
|
|
| Depå in | Infart till depå | `192.168.1.12` | `9002` | Öppnar ett depåstopp |
|
|
| Depå ut | Utfart från depå | `192.168.1.13` | `9003` | Stänger och tidtar depåstoppet |
|
|
|
|
Decoder-IP och WebSocket-adress är två olika saker. Decoder-IP är den fysiska hårdvarans adress som AMMC ansluter till. Webbläsaren ansluter till AMMC på backend-hosten, till exempel `ws://192.168.1.100:9001`. Varje decoder måste ha unik nätverksadress och varje AMMC-process måste ha unik WebSocket-port.
|
|
|
|
Aktivera bara de kanaler som finns fysiskt på banan. En decoder på `9000` är fortsatt standard och kräver inga extrainställningar. Mellantid kräver en extra decoder. Depåtid kräver två extra decoders eftersom in- och utpassering är separata händelser. Komplett installation använder därför fyra decoders.
|
|
|
|
Mellantids- och depådata visas på flera ställen:
|
|
- `Tidtagning` visar aktivt heats sammanställning och fullständig depåstoppslogg live.
|
|
- `Race Setup -> Hantera -> Live / resultat` visar sammanställning och depålogg för varje heat, inklusive långa 45-minuters endurance-heat.
|
|
- vanliga resultat- och lagrapporter inkluderar split-/depåsammanställning och fullständig in-/utlogg i PDF.
|
|
- `Träning -> Mer statistik` summerar mellantider och depåstopp för vald personlig förarprofil och klass; olika klasser blandas aldrig.
|
|
- den personliga mobilprofilen visar endast sanerade antal och aggregerade tider för vald klass. Den exponerar aldrig transpondrar, andra förare eller den råa depåstoppsloggen.
|
|
|
|
Om ett lag byter förare eller bil mellan depå in och depå ut kopplas det färdiga stoppet till föraren, bilen och transpondern som registrerades vid depåinfarten. Transpondern vid utfarten sparas separat för felsökning.
|
|
|
|
1. Lägg AMMC-binärerna i projektmappen `AMMC/` (redan gjort i denna repo).
|
|
2. Öppna `Settings`.
|
|
3. Aktivera `Hanterad AMMC / Managed AMMC`.
|
|
4. Sätt Main `Decoder IP / host`, kontrollera port `9000` och aktivera vid behov Mellantid och Depå enligt tabellen ovan.
|
|
5. Klicka `Starta AMMC / Start AMMC`.
|
|
6. Klicka `Använd serverns WS-url / Use server WS URL` så sätts klienten till t.ex. `ws://<server-ip>:9000`.
|
|
|
|
Standardbinärer:
|
|
- Linux-host: `AMMC/linux_x86-64/ammc-amb`
|
|
- Windows-host: `AMMC/windows64/ammc-amb.exe`
|
|
- macOS-host: `AMMC/apple_m/ammc-amb`
|
|
|
|
### B. Manuell start
|
|
Starta AMMC med WebSocket (exempel):
|
|
```powershell
|
|
ammc-amb.exe -w 9000 192.168.1.10
|
|
```
|
|
|
|
Komplett exempel med fyra decoders, i fyra separata terminaler/processer:
|
|
```powershell
|
|
ammc-amb.exe -w 9000 192.168.1.10
|
|
ammc-amb.exe -w 9001 192.168.1.11
|
|
ammc-amb.exe -w 9002 192.168.1.12
|
|
ammc-amb.exe -w 9003 192.168.1.13
|
|
```
|
|
|
|
I appen:
|
|
1. `Settings`
|
|
2. Sätt `WebSocket URL` till t.ex. `ws://127.0.0.1:9000`
|
|
3. Sätt `Backend URL` till `http://127.0.0.1:8081`
|
|
4. Klicka `Test Backend`
|
|
5. Gå till `Timing` och klicka `Connect Decoder`
|
|
|
|
Om du kör Linux-brandvägg (UFW), öppna porten:
|
|
```bash
|
|
sudo ufw allow 8081/tcp
|
|
sudo ufw allow 9000:9003/tcp
|
|
```
|
|
|
|
## Auto reload vid uppdatering
|
|
- Servern bevakar `index.html`, `src/app.js` och `src/styles.css`.
|
|
- När du uppdaterar filer i `Live_RC` och sparar, laddar klienten om sidan automatiskt.
|
|
- Om backendkoden ändras i Windows, kör `npm.cmd restart`.
|
|
|
|
## Verifiera att SQLite sparar
|
|
Hämta senaste passeringar via API:
|
|
- `http://localhost:8081/api/passings`
|
|
|
|
Hämta sparad app-state:
|
|
- `http://localhost:8081/api/state`
|
|
|
|
## Viktig regel för sponsor-event
|
|
- I **samma pågående session** måste varje aktiv bil ha unikt transponder-ID.
|
|
- Samma transponder-ID kan återanvändas i **nästa session** (Heat 1 -> Heat 2 -> Heat 3 -> Final 1 ...).
|
|
|
|
## Referens AMMC JSON
|
|
Officiell quick-start:
|
|
- https://www.ammconverter.eu/docs/intro/quick-start/
|
|
|
|
Exempelmeddelande:
|
|
```json
|
|
{
|
|
"msg": "PASSING",
|
|
"passing_number": 1,
|
|
"transponder": 232323,
|
|
"rtc_time": "2022-10-11T22:57:36.099+02:00",
|
|
"strength": 0.0,
|
|
"resend": false,
|
|
"tran_code": "ID:232323",
|
|
"loop_id": "55"
|
|
}
|
|
```
|
|
|
|
## Raceljud och startljus
|
|
|
|
Repot innehåller `rc-race-sound-pack/`. `sound_manifest.json` är källan för kopplingen mellan event, WAV-filer och svenska/engelska utrop. Servern publicerar manifestet på `/race-sounds/sound_manifest.json` och WAV-filerna under `/race-sounds/sounds/effects/`.
|
|
|
|
1. Öppna `Inställningar -> Raceljud och utrop`.
|
|
2. Välj `sv` eller `en`, välj en installerad Race-röst och ställ dess hastighet, tonhöjd samt master-, effekt-, röst- och passing-volym. Offline-standard för race-controller-stil är hastighet `1.08` och tonhöjd `0.90`; för verkligt mänsklig speakerkvalitet krävs fortfarande förinspelade eller neurala klipp.
|
|
3. Slå på/av effekt och röst separat för varje event och använd radens Testa-knapp. Ändringar sparas automatiskt och sektionen har även en egen Spara-knapp. WAV-effekter är förinspelade; röstutrop använder operativsystemets Web Speech-röster.
|
|
4. Välj 0/10/30/60 sekunders förstart, startljus och gränser för slumpad startfördröjning. För tidsstyrda race startar klockan i samma callback som starttonen initieras. Open/Free Practice startar direkt.
|
|
5. Använd Race Control-knapparna i `Tidtagning` för Stopp på banan, Banan fri, Röd flagg, Felaktig start och Banvaktsvarning.
|
|
|
|
Effekter körs asynkront och väntas aldrig in av decoderflödet. Kritiska utrop avbryter lägre prioriterat tal; korta passing-ljud får överlappa. Saknade WAV-filer ignoreras säkert. En förare eller bil kan välja `pass_01.wav` till `pass_08.wav`; tills dessa valfria filer finns i `rc-race-sound-pack/sounds/effects/` används `transponder_pass.wav` som fallback.
|
|
|
|
Automatiska hooks omfattar passering, person-/meetingbästa, snabbaste varv, historiskt klass-banrekord, ledar- och positionsbyte, depå in/ut, 60/30/10 sekunder kvar, sista varv/tiden slut, finish, vinnare och podium. Penalty-utrop återanvänder domarvyns befintliga korrigeringsåtgärd.
|