When a driver's personal 5-minute practice timer finishes, a "Pass avslutat" card now appears immediately: how this pass's pace and consistency compared to their recent sessions, any goal or lap-count milestone crossed during the pass with its reward text made prominent, and one suggested next goal (reusing the existing pace recommendation, falling back to the next milestone when there isn't enough data yet). Scoped to the driver's current class, and explicit about insufficient sample sizes instead of showing a misleading number. Adds a per-session consistency calculation to buildPublicTrainingWindowStats server-side; everything else needed (stats, goals, recommendation, milestone) was already sent to the client, so the summary itself is computed there from data already in hand - no raw laps or driver IDs added to what the public endpoint exposes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
RC RaceCore
Planned work and completion checklists are tracked in ROADMAP.md.
The running version is shown at the bottom of the menu and comes from package.json. Changes are recorded in CHANGELOG.md.
English README. Swedish version: README.sv.md
RC RaceCore is an RC timing and race-control system with support for sponsor events with shared cars/transponders, AMMC WebSocket input, and local persistence through SQLite.
Architecture
- JavaScript module overview:
docs/javascript-architecture.md - Security and performance audit:
docs/security-performance-audit.md - Swedish operational guide:
README.sv.md
Windows Quick Start
For a new Windows 11 computer, open PowerShell and follow these steps.
- Check whether Git is installed:
git --version
- If
gitis not recognized, install it and reopen PowerShell:
winget install --id Git.Git --exact --source winget
- Download RC RaceCore and enter the project directory:
Set-Location $HOME
git clone https://git.dio.nu/Public/Live_RC.git Live_RC
Set-Location .\Live_RC
- Run the complete installer. It installs/checks Node.js, installs npm dependencies, verifies SQLite and starts the server in the background:
.\windows\install.bat
- Verify the server and open
http://localhost:8081:
npm.cmd run status
Invoke-RestMethod -Uri "http://127.0.0.1:8081/api/health"
If winget is missing, install Git for Windows. You can also download the repository as a ZIP without Git. See the complete Installation section for ZIP installation, LAN access, updates and troubleshooting.
Screenshots
Current layouts for race operation, live presentation, training and system configuration. Click an image to open the full-resolution version.
Public Overlay And OBS
The app now supports a dedicated public overlay route so you do not need to expose the full admin UI externally.
- Public overlay route:
/public-overlay/<mode> - OBS mode:
/public-overlay/obs - OBS overlay can be configured from the
Overlaymenu:- rows
- layout:
leaderboard,grid,lowerthird - theme:
panel,transparent,chroma - visible columns and blocks
- Use
Copy OBS URLto generate a ready-to-paste browser-source link for OBS.
If you want simple protection for public overlays, set this environment variable on the server:
PUBLIC_OVERLAY_TOKEN=your-secret-token
This token gates the overlay route only. Do not expose port 8081 directly to the internet because administration APIs are not authenticated. Use a trusted race LAN, VPN, or authenticated reverse proxy. If the UI is intentionally served from another origin, list it in RC_ALLOWED_ORIGINS (comma-separated). See docs/security-performance-audit.md.
Then the public overlay URL must include:
/public-overlay/obs?token=your-secret-token
Recommended deployment:
- publish only
/public-overlay/*through your reverse proxy - keep the main app/admin UI internal
Features
- Event modes:
Race (driver transponders)Track Event (shared cars)
- UI separation:
Event= sponsor events with shared cars/transpondersRace Setup= untimed Open Practice or competition races with personal driver transponders
- Grouped navigation follows the operating flow:
Start,Create,Run and follow,Directory, andSystem and help. Dashboard -> Getting startedlinks directly to system setup, driver registration, race/practice creation, Timing, and Overlay.- Race Day operation:
- focused current/next/after-next heat queue
- preflight for decoder, participants, transponders, duplicate IDs, lap window, grid and audio
- blockers and warnings shown first, with shortcuts to the relevant settings or register; lap limits can be edited directly in Race Day
- shared start/finish/pause logic with the existing Timing view
- automatic consistent SQLite backup before every session start, full data import and data clear operation
- latest 30 server backups listed under
Settings -> Storage - isolated session replay in
Timingwith play, pause, reset, and 1x/2x/5x/10x speed; source results are never modified
- Storage/import tools:
- full race-data export/import for backup or moving to another machine
- directory export/import for only classes, drivers and cars
- CSV export and safe merging CSV import for drivers and cars through Excel or LibreOffice
- single race-package export/import from
Race Setup -> Manage -> Race Actions
- Race Setup includes:
Quick Open Practice: enter only a name, create an untimed all-transponder session, and continue directly to Timing- no class, registered drivers, preset, qualifying, finals, or duration is required for Quick Open Practice
- grouped
ParticipantsandTeamssections inManage - a four-step
Create Race Wizardfor new races Managesplit intoSetup,Format,Generation, andLive / results- Basic mode now reacts to the selected preset, including a cleaner endurance view
Basic / Advancedmode forRace Format- a right-side race summary card
- a preset-aware summary card that changes between endurance and normal race focus
- status badges for
Setup,Format,Generation, andLive / results - summary warnings when participants, sessions, teams, or lap-window settings are missing
- clickable summary warnings that jump to the relevant Manage section
- clickable step cards that act as quick navigation inside
Manage - compact step cards with live counters such as drivers, teams, sessions, and active/results state
- separate
Race actionsfor generation, reseeding and bump-up - reorganized in-app
Guidewith overview cards and two-column sections - explicit race participant selection
- practice standings
- qualifying standings with
pointsorbest result - built-in step-by-step guide
- inline descriptions for all
Race Formatfields Follow-up timeafter scheduled race time before a heat fully closesMin lap timerejects shortcuts/false hits;Max lap timestarts a new statistics stint without removing the race lap- seeding modes for practice/qualifying: best N laps total, average, or consecutive
- selectable qualifying points tables and tie-break rules
Race Formatpresets for short technical tracks, club races, IFMAR-style layouts, and endurance- schedule drift on
Dashboardbetween planned and actual runtime - session type
Free Practicefor rolling lap-time display without seeding - automatic qualifying heat generation from practice standings or class list
- re-seeding of upcoming qualifying heats from current standings
- automatic
A/B/C...finals generation from rankings - persistent manual grid per session with drag-and-drop grid editor
- auto-reseed skips heats with locked manual grid
- explicit
Lock/Unlock gridper session - multi-leg final standings with counted final legs
- optional bump-up between finals
- reserved bump-up slots in higher finals
- visual finals matrix with reserved bump slots
- drag-and-drop grid editor for position starts
- print/export of heat sheets per qualifying/final
- overlay modes for external display screens
- multiple overlay modes: leaderboard, speaker, results, TV, team
- speaker overlay with event markers and separate speaker cues
- live speaker panel in
Timing - speaker cues and club branding for the sidebar, overlays, public training profiles, and PDFs from
Settings - club logo upload for the sidebar, overlays, public training profiles, and PDFs from
Settings - per-event/per-race branding in
Manage - extra speaker cues for
session start,new best lap, andtop 3 change - selectable PDF themes:
classic,minimal,motorsport - branded print and PDF exports
- server-generated PDF exports with embedded logo
- generated qualifying/finals inherit duration and start mode from race format
- finish sound uses a siren instead of browser TTS
- Sessions:
practicequalificationheatfinalfree_practiceopen_practiceteam_race
- Sponsor event tools:
- automatic round creation (
qualification,heat,final) - auto-assign driver -> car per session
- automatic round creation (
- Live timing from AMMC WebSocket (
msg: "PASSING") - Managed AMMC from the web UI:
- backend can start/stop local
ammc-ambon Windows, Linux, and macOS - bundled binaries from
AMMC/windows64,AMMC/linux_x86-64,AMMC/apple_m
- backend can start/stop local
- Editing in UI:
- classes, event names/dates, drivers, and cars can be edited directly
- drivers and cars support optional
brandfields for team, sponsor, manufacturer, or model data DriversandCarscan be searched by name, transponder, or brand directly in the UI- race start lists and heat sheets include driver brand in print, CSV, and PDF exports
- Live race control:
- countdown during timed sessions
- auto-finish at end of session time with
Race is finished - leaderboard sorting by laps first, then nearest to target time when applicable
- configurable browser audio for start, finish, and passings (
beepor driver name) - selectable operating-system speech voice, speech rate/pitch, and per-driver phonetic spoken name
- session start types:
Mass start,Position start,Staggered Timingshows grid/order for the activePosition startsession- leaderboard shows
gap to leader,gap ahead, andown delta Recent Passingsdistinguishes invalidShort lappassings from counted long laps that start a new stint- manual corrections in
Timing -> Details:+1/-1 lap,+1/+5/-1 sec, reset - practice/qualifying seeding on best
2or3laps
- Persistence:
- frontend state in browser
localStorage - same state and passings persisted to local SQLite through the Node backend
- frontend state in browser
- Built-in
Guidepage in the app covering:- sponsor events (for example 10 drivers / 4 cars)
- standard race setup
- invalid laps, follow-up, and manual corrections
- AMMC + npm setup on Windows and Linux
- UI language selection:
SVEN
Training And Rewards
The Training menu provides a non-race progression view for registered drivers:
The default view is a club overview with totals and one row per driver and class. Select a driver from the list to open the intentionally simple personal view with four key statistics, the next lap target, today's practice plan and active rewards. Goal administration, mobile sharing and detailed history remain available in collapsed sections when needed.
When Open Practice, Free Practice, or Practice is running, the selected driver gets a compact live card with current valid laps, best lap, average, and latest lap. The session remains shared by everyone; only the mobile personal timer and profile link are unique per driver and class. The primary action at the top creates or opens that link.
One person can have separate driver entries for classes such as 2WD and 4WD and link them to the same Practice profile under Drivers. The person then has one profile and one mobile link, while every performance statistic is selected and calculated separately per class. Multiple transponders within the same class are combined in that class's statistics.
The personal profile can also store Club and Country. These values are inherited when another class entry is linked to the same practice profile and are included in full JSON and driver CSV exports. They are not disclosed by the public profile link.
- durable lifetime valid-lap ledger synchronized from stored session results
- practice days, recorded sessions, personal best, overall/recent averages, controlled-lap streak, and recent consistency spread
- automatic stint boundaries at the configured
Max lap time, with a 2-minute fallback for legacy/unconfigured data - best 3 consecutive laps plus best 5-minute result and its average pace
- the best 5-minute result counts the final lap when it started before
5:00(300 s), even when the result finishes after the cutoff - mobile profile pace chart, recent class-specific stint summaries, and daily history for the latest practice days
- per-profile publishing controls for development, achievements, performance/stints, goals/rewards, and history; disabled detail sections are filtered by the public API
- personal development trend comparing the latest 30 valid laps with the preceding 30, always isolated per class
- automatic achievements for first practice, lap totals, practice days, controlled streaks, and completed five-minute stints
- optional personal stable-pace voice feedback after five controlled laps in one practice stint, using the configured driver spoken name and a per-driver cooldown
- three optional daily challenges for valid laps, controlled consecutive laps, and a completed five-minute stint
- a positive personal summary that recognizes today's volume, personal best, pace, consistency, and endurance without ranking drivers
- a recent club progress feed ordered by activity rather than driver position or lap-count ranking
- a configurable shared club target that counts every new valid practice lap from all registered drivers from the moment the target is created
- one collapsed More statistics section with active 30-minute pace blocks based on a trimmed average
- class-specific setup markers for tires, suspension, car changes, or custom notes, including an automatic 30-minute before/after comparison
- detailed stint analysis with normal pace, best 10-lap race pace, outlier laps, pace retention, and strong finishes
- personal control zone, stint-scoped flow streaks, clean five-minute runs, and latest split-time improvement
- automatic progression levels at useful lap totals without manual setup
- a configurable practice timer split into maximum-focus and controlled 80-90% blocks
- custom lap milestones with quick targets at
500,1000, and1500laps - optional reward text and a delivered/redeemed state
- responsive layout for opening the same server from a phone on the local network
Direct mobile/bookmark link: http://<server-ip>:8081/?view=training. Selecting a profile and class adds both to the URL so the exact view can be bookmarked.
Training statistics currently include only valid laps linked to a registered driver. Anonymous Open Practice transponders are intentionally excluded until they are assigned to a driver.
Judging corrections update ledger laps while the source session still exists. Once a session is deleted, its synchronized training laps remain in the ledger so lifetime progression is not lost. Full data export includes the ledger, reward goals, and setup markers.
Restricted mobile profile
Each registered driver can have an optional personal mobile link:
- Open
Trainingand select the driver. - Open
Goals and mobile profile, then clickEnable mobile profile. - For internet sharing, set the public base address, for example
https://racecore.example.org, and clickSave address. - Scan
Local QR codeon the same network as RaceCore, orPublic QR codeover the internet. The local QR is generated from the RaceCore server LAN address, so it also works when the admin UI was opened aslocalhost. - Use
Create new linkto revoke the previous URL, orDisable profileto turn sharing off.Detect public IPis an explicit suggestion only; use the FQDN when the TLS certificate is issued for the domain.
The URL uses a 192-bit random bearer token rather than a driver ID. The same link provides a class selector with fully separate lap times and practice results for each linked class. The public API does not return transponder IDs, other driver names, club ranking, race setup or admin state. The only server-side mobile action is adding a setup marker for the token owner and selected linked class.
Mobile auto-refresh pauses while editing a field or saving a car change. Unsaved car-change notes remain separate per class during page updates and class switching (until the page is reloaded). Temporary refresh failures keep the last loaded statistics visible.
The performance section also shows active 30-minute pace blocks and lets the driver mark a class-specific car/setup change. Open detail sections remain expanded during live polling.
The mobile page also includes a local practice timer where the driver chooses minutes for Maximum focus and Controlled. The default is 10 + 10, while a five-minute heat can for example use 5 + 0. While a shared Free Practice session keeps running, the card shows that driver's lap count, best lap and average since the personal timer started. Timer state and duration choices stay in that phone's browser, separately per driver and class, and do not modify race data. Durations are locked while a session runs and can be changed after finishing or resetting it.
For internet publishing, proxy only these paths:
/public-training/*
/src/public_training.js
/src/public_training.css
Do not expose /api/state or the full admin application. Ready-to-copy Teltonika files are in scripts/teltonika/; the init script recreates Nginx RAM-backed temporary directories at every boot and does not use nginx-util. Static serving is restricted to /src and /docs; data/, server scripts and bundled binaries are not public static files.
Regression tests use Node's built-in test runner and require no extra test-framework dependency. The suite covers training profiles, race generation and timing, judging corrections, frontend/backend state synchronization, and an isolated SQLite API round-trip using a temporary data directory:
npm test
The integration test starts its own backend on a temporary localhost port and never reads or writes the normal data/rc_timing.sqlite database.
Create Race Wizard
Race Setupnow starts with a four-step wizard for new races:BasicsParticipantsSession planConfirm
- The wizard is intended to create the first race structure quickly:
- choose class and preset
- scope valid race drivers
- create practice, qualifying, and/or team-race sessions automatically
- Finals are still generated later from
Race Actionsafter practice or qualifying is complete.
Manage workflow
- After the race is created,
Manageis split into four clear stages:SetupFormatGenerationLive / results
Setuphandles race participants and teams. The top step cards also act as quick navigation between the four blocks.Formathandles practice/qualifying, finals, validation, presets, and advanced settings. In Basic mode, endurance hides most qualifying/finals fields until Advanced is opened.Generationis kept separate so actions like qualifying generation, reseeding, finals generation, and bump-up do not clutter the format form.Live / resultsis where grid, standings, print, PDF, and finals matrix are used once the structure is ready.
Export / Import
Settings -> Storagenow supports:- full JSON export/import for the complete competition database
- directory JSON export/import for only classes, drivers, and cars
- CSV export and merging CSV import for drivers and cars; comma, semicolon, and tab delimiters are supported
- separate clearing of drivers, cars, classes, races/sessions, or training statistics
Clear all competition dataretains decoder, theme, branding, and server settings
Race Setup -> Manage -> Race Actionsnow supports single race packages:- export one race with its sessions, results, and referenced classes/drivers/cars
- import that package into another installation as a new race entry
- JSON export files now include export metadata and a schema version field so future imports can be handled more safely.
- CSV imports from the application's own exports preserve IDs. External lists without IDs first match by transponder and then by name + class. Empty fields do not overwrite existing information, and new class names are created automatically.
- Driver imports only require the
namecolumn. The recommended minimum isname;transponder;class. Optional columns such asbrand,spoken_name,club,country, andprofile_idmay be omitted; unknown columns are ignored and rows without a name are skipped.
name;transponder;class;brand;club;country
Anna Andersson;123456;2WD;;JMK;SE
Erik Eriksson;654321;4WD;Associated;;
- An empty CSV template can be downloaded directly from the driver import area under
Settings -> Storage. - Create a JSON backup before clearing data. Every clear button requires a separate confirmation and cannot be undone.
- Web clearing removes canonical application data but retains the separate raw SQLite
passingstable as an audit log. A physical factory reset of the database must be performed locally on the stopped server, never through an unauthenticated LAN route.
Race features
Follow-up time
- Configure it in
Race Setup -> Manage -> Race Format - It can also be set per session when creating or editing a session
- When scheduled time ends, the session enters follow-up first
- When follow-up ends, the session closes automatically
- Generated qualifying/finals inherit follow-up from race format
Min / Max lap time
- Configure it in
Race Setup -> Manage -> Race Format Min lap time:- laps faster than the threshold are ignored as shortcuts or false hits
Max lap time:- a slower passing starts a new statistics stint
- the transition lap still counts in race results, but is excluded from pace and five-minute averages
Example:
- track around
16 sec/lap Min lap time = 11 secMax lap time = 120 secto begin a new stint after a two-minute interruption
Invalid passings
Timing -> Recent Passingsshows both valid and invalid passings- displayed statuses include:
Short lapfor an invalid shortcut/false hitLong lap · counted · new stintwhen max is exceeded
- invalid passings are visually highlighted; counted long laps remain in the race result
Manual corrections
- open
Timing - click
Detailson a driver or team - available actions:
+1 lap-1 lap+1 sec+5 sec-1 secReset correction
- leaderboard and results update immediately
Best laps / average / consecutive
- Configure per session with
Seed MethodwhenBest laps for seedingis greater than0 - available modes:
Best N laps, totalBest N laps, averageBest N consecutive laps
- leaderboard and standings use the correct format:
- total:
3/00:48.321 - average:
3 avg 16.107 - consecutive:
3 con 00:49.005
- total:
Points tables and tie-break
- Configure in
Race Setup -> Manage -> Race Format - qualifying points tables:
Placement values (1,2,3...)Descending by field size10-9-8-7-6-5-4-3-2-1
- qualifying tie-break options:
Compare counted roundsBest single lapBest round / heat result
- qualifying standings also show an inline tie-break note in the table
Race format presets
Race Setup -> Manage -> Race Format- choose a preset and click
Apply preset - built-in presets:
Short technical track 16sClub race qual + finalsIFMAR-style qual/finalsEndurance / team race
- after applying, all fields can still be adjusted manually and saved as usual
Save club presetstores your own local presets in app stateDelete club presetremoves a local presetSettings -> Club presetscan export/import the preset library as JSON between installations
Schedule drift on Dashboard
Dashboardshows whether the day is ahead of or behind schedule- planned time includes:
- session duration
- follow-up time
- actual time includes:
- real time from start to stop
- or live runtime if the session is still running
Invalid-lap marker in leaderboard
- if the latest passing for a driver or team is invalid, the row is marked in both leaderboard and overlay
- this makes it easier to see problems without staying in
Recent Passings
Manual invalidate / restore last lap
Timing -> DetailsInvalidate last lapmarks the latest counted lap as manually invalid- leaderboard, overlay, and lap history update immediately
Restore latest manually invalidated lapputs the latest manually invalidated lap back if needed
Judging view
- separate
Judgingmenu - shows active session, leaderboard, lap history, and judging log in one view
- same corrections as
Timing -> Details - row filters:
AllInvalidCorrectedTeam race
- judging log can be exported per session as JSON
- supports
Undo latestand per-log-row undo for multiple recent manual actions
Future improvements
- Optional neural text-to-speech for more natural start, finish, and driver-name announcements.
- Preferred design: generate speech through the backend, cache short audio files under
data/tts/, and play cached audio without network delay during a race. - Keep provider credentials on the backend only. Never expose API keys to the browser or public overlay.
- Retain the current system voice and passing beep as offline fallbacks.
- Support uploaded or prerecorded WAV/MP3 clips for fixed start and finish announcements.
Installation
RC RaceCore runs on 64-bit Windows 11 and Linux. Use Node.js 22 or 24 LTS and npm 10 or newer. The repository includes package-lock.json, so use npm ci rather than npm install for repeatable installations.
Windows 11 - new computer
1. Install Git
Open PowerShell and check whether Git is available:
git --version
If Windows reports that git is not recognized, install Git with Windows Package Manager:
winget install --id Git.Git --exact --source winget
Close and reopen PowerShell after installation, then run git --version again. If winget is unavailable, install Git for Windows from git-scm.com.
2. Download RC RaceCore
Clone the public repository from a normal PowerShell prompt:
Set-Location $HOME
git clone https://git.dio.nu/Public/Live_RC.git Live_RC
Set-Location .\Live_RC
Enter the raw URL exactly as shown. Do not paste Markdown syntax such as [https://...](https://...) into PowerShell.
If you do not want to install Git, open the public repository, download its ZIP archive, and extract the complete archive. Make sure package.json, server.js, src\, and windows\ are all in the same project directory.
3. Run the Windows installer
From the project directory:
.\windows\install.bat
You can also double-click windows\install.bat in Explorer. The installer:
- installs Node.js LTS through
wingetwhen Node is missing or unsupported - installs/checks the Microsoft Visual C++ runtime used by AMMC
- runs
npm.cmd ciusing the locked dependency versions - verifies Express, SQLite, and bundled AMMC files
- creates
data\andlogs\ - runs
npm.cmd restartand leaves RC RaceCore running in the background
If the installer cannot install Node automatically, install Node.js 22 or 24 LTS from nodejs.org, reopen PowerShell, and run the installer again.
4. Verify and open the application
npm.cmd run status
Invoke-RestMethod -Uri "http://127.0.0.1:8081/api/health"
Open:
http://localhost:8081
To open RC RaceCore from another computer on the race LAN, run ipconfig on the server and use:
http://<windows-server-ip>:8081
Use npm.cmd in PowerShell. This bypasses the common npm.ps1 cannot be loaded because running scripts is disabled error. Plain npm normally works in Command Prompt.
Windows manual installation
If you do not use install.bat:
node --version
npm.cmd --version
npm.cmd ci
npm.cmd run verify
npm.cmd start
Do not use npm.cmd ci --ignore-scripts. The native SQLite dependency needs its install script.
Linux - Ubuntu/Debian
1. Install Git and basic tools
sudo apt update
sudo apt install -y git curl build-essential
git --version
2. Install Node.js 22 LTS when needed
Check the installed version:
node --version
npm --version
If Node is missing or older than version 22, install Node.js 22 from NodeSource:
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
node --version
npm --version
Node.js 22 or 24 LTS is recommended. Node.js 18 and 20 are not supported by the current native SQLite dependency.
The bundled x86-64 Linux AMMC tools in AMMC/linux_x86-64 require GLIBC 2.39 or newer. This includes the decoder converters and ammc-sim. Check the host before race day with ldd --version and npm run verify. Older distributions can still run RC RaceCore, but must use AMMC binaries built for their GLIBC version or run AMMC on another compatible host.
3. Clone, install, and start
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-*
npm start
npm run status
curl http://127.0.0.1:8081/api/health
npm start launches RC RaceCore in the background. Open http://localhost:8081, or find the Linux server address with hostname -I and open http://<linux-server-ip>:8081 from another computer.
If the bundled AMMC reports version 'GLIBC_2.39' not found, the host is too old for that binary. Use a compatible AMMC build or a Linux distribution with GLIBC 2.39+. Do not manually replace the operating system's GLIBC because that can break the whole system.
AMMC/linux_x86-64/ammc-sim and AMMC/windows64/ammc-sim.exe can emulate an AMB decoder with selected transponders. This is useful for training, overlay tests, and load tests without a physical decoder. See docs/decoder-setup.md for a complete example.
Runtime commands
Windows PowerShell:
npm.cmd start
npm.cmd run status
npm.cmd restart
npm.cmd stop
npm.cmd run start:fg
Linux:
npm start
npm run status
npm restart
npm stop
npm run start:fg
startruns the backend in the backgroundstatusreports whether the PID indata/server.pidis runningrestartreloads backend changesstopstops the managed processstart:fgruns in the current terminal and displays startup errors directly- stdout is written to
logs/server.out.log - stderr is written to
logs/server.err.log - SQLite data is stored in
data/rc_timing.sqlite
Windows helper scripts
windows\install.bat: install dependencies, verify, and restartwindows\start_backend.bat: start the backend in the backgroundwindows\restart_backend.bat: restart after copied or pulled updateswindows\start_ammc.bat: start bundled AMMC manuallywindows\start_all.bat: start AMMC and backend, then open the browserwindows\stop_all.bat: stop the backend andammc-amb.exe
Restore a server backup
Backups are stored in data/backups/. Restore is intentionally a local server command and is not exposed through the unauthenticated web API.
- Stop RC RaceCore.
- Copy the backup filename from
Settings -> Storageor list the files indata/backups/. - Run the restore command with the explicit confirmation flag.
- Start RC RaceCore again.
Windows 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:
npm stop
backup=$(find data/backups -maxdepth 1 -name '*.sqlite' -printf '%T@ %f
' | sort -nr | head -n 1 | cut -d' ' -f2-)
printf 'Restoring %s
' "$backup"
npm run backup:restore -- "$backup" --confirm
npm start
The restore command validates the selected SQLite file and creates a pre_restore backup of the current database before replacing it.
Update an existing installation without losing data
The SQLite database and local configuration are in data/. Do not delete or replace this directory during an update.
Windows:
npm.cmd stop
git pull --ff-only
npm.cmd ci
npm.cmd run verify
npm.cmd restart
npm.cmd run status
Linux:
npm stop
git pull --ff-only
npm ci
npm run verify
npm restart
npm run status
If the installation came from a ZIP archive instead of Git, back up data/, extract the new application files, restore/retain the existing data/ directory, run npm ci, and restart. Never copy node_modules/ between Windows and Linux.
Connect to AMMC
There are two supported modes.
For the complete network diagram, ready-to-use 1/2/3/4-decoder examples, firewall setup, and troubleshooting, see docs/decoder-setup.md. Swedish: docs/decoder-setup.sv.md.
A. Managed AMMC from the web UI
Important:
- AMMC runs on the same host where the backend was started with
npm.cmd start - if you only browse from another laptop, no process starts there
- the
AMMC executablefield inSettingsis a path on the backend host, not the client browser machine
Decoder topology
| Role | Physical placement | Example decoder IP | AMMC WS port | Effect |
|---|---|---|---|---|
| Main start/finish | Start/finish loop | 192.168.1.10 |
9000 |
Counts laps and controls lap time |
| Split | Intermediate loop | 192.168.1.11 |
9001 |
Records split from the latest main crossing; never counts a lap |
| Pit entry | Entry to pit lane | 192.168.1.12 |
9002 |
Opens a pit stop |
| Pit exit | Exit from pit lane | 192.168.1.13 |
9003 |
Closes and times a pit stop |
The decoder IP and WebSocket address are different things. The decoder IP points from AMMC to physical hardware. The browser connects to AMMC on the backend host, for example ws://192.168.1.100:9001. Each decoder must have a unique network address and each AMMC process must have a unique WebSocket port.
Use only the channels physically installed at the track. One decoder on 9000 remains the default and needs no optional settings. Split timing requires one additional decoder. Pit timing requires two additional decoders because entry and exit are separate events. A complete setup therefore uses four decoders.
Split and pit data is available in several places:
Timingshows the active heat summary and complete pit-stop log live.Race Setup -> Manage -> Live / resultsshows the summary and pit log for every heat, including long 45-minute endurance heats.- regular and team result exports include split/pit summaries and the complete entry/exit log in PDF.
Training -> More statisticsaggregates split and pit performance for the selected personal driver profile and class; different classes are never mixed.- the personal mobile profile shows only sanitized counts and aggregate times for the selected class. It never exposes transponders, other drivers, or the raw pit-stop log.
If a team changes driver or car between pit entry and pit exit, the completed stop remains attributed to the driver, car, and transponder detected at pit entry. The exit transponder is retained separately for diagnostics.
- Place AMMC binaries in the
AMMC/project folder. - Open
Settings. - Enable
Managed AMMC. - Set the Main
Decoder IP / host, verify port9000, and optionally enable/configure Split and Pit channels from the table above. - Click
Start AMMC. - Click
Use server WS URLso the client uses for examplews://<server-ip>:9000.
Default binaries:
- Linux host:
AMMC/linux_x86-64/ammc-amb - Windows host:
AMMC/windows64/ammc-amb.exe - macOS host:
AMMC/apple_m/ammc-amb
B. Manual start
Example:
ammc-amb.exe -w 9000 192.168.1.10
Complete four-decoder example, using four separate terminals/processes:
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
In the app:
- Open
Settings - Set
WebSocket URL, for examplews://127.0.0.1:9000 - Set
Backend URLtohttp://127.0.0.1:8081 - Click
Test Backend - Go to
Timingand clickConnect Decoder
If Linux firewall/UFW is enabled:
sudo ufw allow 8081/tcp
sudo ufw allow 9000:9003/tcp
Auto reload during development
- The server watches
index.html,src/app.js, andsrc/styles.css - When files in
Live_RCchange, the client reloads automatically - If backend code changes on Windows, run
npm.cmd restart
Verify SQLite persistence
Latest passings via API:
http://localhost:8081/api/passings
Saved app state via API:
http://localhost:8081/api/state
Important rule for sponsor events
- In the same running session, every active car must have a unique transponder ID
- The same transponder ID can be reused in the next session (
Heat 1 -> Heat 2 -> Heat 3 -> Final 1 ...)
AMMC JSON reference
Official quick start:
Example message:
{
"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"
}
Race audio and start lights
The repository includes rc-race-sound-pack/. sound_manifest.json is the source of truth for event-to-WAV and Swedish/English announcement mappings. The server exposes it at /race-sounds/sound_manifest.json; WAV files are served from /race-sounds/sounds/effects/.
- Open
Settings -> Race sounds and announcements. - Select
svoren, choose an installed Race voice, then set its speed, pitch, and master/effects/voice/passing volume. The offline race-controller defaults are speed1.08and pitch0.90; prerecorded or neural clips are still required for genuinely human announcer quality. - Enable or disable effect and voice independently for each event and use its Test button. Changes save automatically, and the section also has its own Save button. WAV effects are prerecorded; voice announcements use the operating system Web Speech voices.
- Select a 0/10/30/60-second pre-start, start lights, and random delay limits. For timed race sessions the clock starts at the same callback that initiates the start tone. Open/Free Practice starts immediately.
- Use the Race Control buttons in
Timingfor Track call, Track clear, Red flag, False start, and Marshal warning.
Effects are asynchronous and never awaited by decoder processing. Critical speech interrupts lower-priority speech; short passing effects may overlap. Missing WAV files are ignored safely. A driver or car may select pass_01.wav through pass_08.wav; until those optional files exist under rc-race-sound-pack/sounds/effects/, playback falls back to transponder_pass.wav.
Implemented automatic hooks include passings, personal/meeting best, fastest lap, historical class track record, leader and position changes, pit entry/exit, 60/30/10 seconds remaining, final lap/time expired, finish, winner, and podium. Penalty announcements reuse the existing judging correction action.
Reliability checks and save status
The menu shows server connection, pending changes, saving, confirmed saves and save failures. It also shows the latest successful data load/save times. A visible warning indicates a lost or stale server connection; a successful health check does not clear a failed save. Use Retry to resend local changes. Server connection and decoder connection are separate indicators. Keep the tab open while changes are unsaved.
New browser profiles use the page origin (including its port) as the default backend URL. An explicitly configured backend URL takes precedence.
Run npm test for logic and API regression tests. Run npm run test:browser (Windows PowerShell: npm.cmd run test:browser) for real create/edit/reload checks of classes, drivers and cars, draft retention during background polling, and offline-save/retry behavior. Chrome, Chromium or Edge must be installed; set CHROME_PATH if its executable is not found automatically. The runner creates a temporary server database and browser profile and removes them on exit. It does not use your normal race data or start a decoder. See ROADMAP.md for workflows not yet covered.
Browser coverage also includes sponsor-event edits, the endurance race wizard, team creation/membership edits/deletion, Open Practice to team-race conversion, and lap-limit persistence. Overlay sort headings align with their columns; narrow displays scroll the headings and rows together.
Decoder Socket Diagnostics
Open Settings > Decoder / socket diagnostics to inspect Main, Split, Pit entry and Pit exit independently. Each channel shows its saved WebSocket URL, the actual socket URL, connection/reception times and counters. A connected socket alone does not prove that the decoder is sending passings.
Use the AMMC host IP in WebSocket URLs (for example ws://192.168.1.75:9000), not the physical decoder IP. Give each AMMC channel its own port; enable only installed channels. 127.0.0.1 means the computer running the browser.
Frames include all received WebSocket messages; PASSING counts recognized passing messages, not accepted laps. Handled includes split/pit events and start references. Ignored, invalid laps and JSON errors are separate. Select a channel to inspect its latest raw frame and 50 diagnostic events. Pause freezes only this display; Clear resets only that channel's diagnostic counters/log, preserving connection timestamps. Copy provides a manual fallback on plain HTTP. Diagnostics are local to this browser, memory-only, capped at 512 characters per sample, and reset on page reload. They neither change timing nor expose a new public API. Logs may contain transponder numbers; review before sharing.
Mobile Profile Connection Status
The personal training link displays the last successful data retrieval. After 30 seconds without applying fresh data, it warns that statistics may be outdated (including when updates are deferred during input). A failed request keeps existing statistics and shows Retry. Finish any active input before retrying. Requests time out after 15 seconds; automatic polling continues every 10 seconds while the page is visible, without overlapping requests. The status describes profile retrieval, not decoder connectivity or confirmation that a car-change marker was saved.








