# JMK RB RaceController English README. Swedish version: [`README.sv.md`](README.sv.md) JMK RB RaceController 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. ## Screenshots ### Overview ![Overview](docs/screenshots/overview.jpg) ### Timing ![Timing](docs/screenshots/timing.jpg) ### Overlay ![Overlay](docs/screenshots/overlay.jpg) ### Event ![Event](docs/screenshots/event.jpg) ### Race Setup ![Race Setup](docs/screenshots/race-setup.jpg) ### Team Overlay ![Team Overlay](docs/screenshots/team-overlay.jpg) ### Judging ![Team Overlay](docs/screenshots/judging.jpg) ## Features - Event modes: - `Race (driver transponders)` - `Track Event (shared cars)` - UI separation: - `Event` = sponsor events with shared cars/transponders - `Race Setup` = competition races with personal driver transponders - Race Setup includes: - explicit race participant selection - practice standings - qualifying standings with `points` or `best result` - built-in step-by-step guide - inline descriptions for all `Race Format` fields - `Follow-up time` after scheduled race time before a heat fully closes - `Min lap time` and `Max lap time` filtering for shortcuts/false hits and better stint/stat logic - seeding modes for practice/qualifying: best N laps total, average, or consecutive - selectable qualifying points tables and tie-break rules - `Race Format` presets for short technical tracks, club races, IFMAR-style layouts, and endurance - schedule drift on `Dashboard` between planned and actual runtime - session type `Free Practice` for 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 grid` per 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/PDF branding from `Settings` - overlay logo upload from `Settings` - per-event/per-race branding in `Manage` - extra speaker cues for `session start`, `new best lap`, and `top 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: - `practice` - `qualification` - `heat` - `final` - `free_practice` - `open_practice` - `team_race` - Sponsor event tools: - automatic round creation (`qualification`, `heat`, `final`) - auto-assign driver -> car per session - Live timing from AMMC WebSocket (`msg: "PASSING"`) - Managed AMMC from the web UI: - backend can start/stop local `ammc-amb` on Windows, Linux, and macOS - bundled binaries from `AMMC/windows64`, `AMMC/linux_x86-64`, `AMMC/apple_m` - Editing in UI: - classes, event names/dates, drivers, and cars can be edited directly - drivers and cars support optional `brand` fields for team, sponsor, manufacturer, or model data - `Drivers` and `Cars` can be filtered by brand directly in the UI - 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 - browser audio for passings (`beep` or driver name) and finish - session start types: `Mass start`, `Position start`, `Staggered` - `Timing` shows grid/order for the active `Position start` session - leaderboard shows `gap to leader`, `gap ahead`, and `own delta` - `Recent Passings` shows invalid laps such as `Short lap` and `Over max lap` - manual corrections in `Timing -> Details`: `+1/-1 lap`, `+1/+5/-1 sec`, reset - practice/qualifying seeding on best `2` or `3` laps - Persistence: - frontend state in browser `localStorage` - same state and passings persisted to local SQLite through the Node backend - Built-in `Guide` page 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: - `SV` - `EN` ## 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`: - laps slower than the threshold are not counted as valid laps - also used to split stints and improve statistics Example: - track around `16 sec/lap` - `Min lap time = 11 sec` - `Max lap time = 60 sec` ### Invalid passings - `Timing -> Recent Passings` shows both valid and invalid passings - displayed statuses include: - `Short lap` - `Over max lap` - invalid passings are visually highlighted ### Manual corrections - open `Timing` - click `Details` on a driver or team - available actions: - `+1 lap` - `-1 lap` - `+1 sec` - `+5 sec` - `-1 sec` - `Reset correction` - leaderboard and results update immediately ### Best laps / average / consecutive - Configure per session with `Seed Method` when `Best laps for seeding` is greater than `0` - available modes: - `Best N laps, total` - `Best N laps, average` - `Best 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` ### Points tables and tie-break - Configure in `Race Setup -> Manage -> Race Format` - qualifying points tables: - `Placement values (1,2,3...)` - `Descending by field size` - `10-9-8-7-6-5-4-3-2-1` - qualifying tie-break options: - `Compare counted rounds` - `Best single lap` - `Best 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 16s` - `Club race qual + finals` - `IFMAR-style qual/finals` - `Endurance / team race` - after applying, all fields can still be adjusted manually and saved as usual - `Save club preset` stores your own local presets in app state - `Delete club preset` removes a local preset - `Settings -> Club presets` can export/import the preset library as JSON between installations ### Schedule drift on Dashboard - `Dashboard` shows 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 -> Details` - `Invalidate last lap` marks the latest counted lap as manually invalid - leaderboard, overlay, and lap history update immediately - `Restore latest manually invalidated lap` puts the latest manually invalidated lap back if needed ### Judging view - separate `Judging` menu - shows active session, leaderboard, lap history, and judging log in one view - same corrections as `Timing -> Details` - row filters: - `All` - `Invalid` - `Corrected` - `Team race` - judging log can be exported per session as JSON - supports `Undo latest` and per-log-row undo for multiple recent manual actions ## Windows installation Run in PowerShell in the project directory. 1. Install Node.js LTS (18+). 2. Install dependencies: ```powershell npm install ``` 3. Start the server in the background: ```powershell npm start ``` 4. Open: - `http://localhost:8081` - or from another computer: `http://:8081` Common commands: ```powershell npm start npm stop npm restart npm run status npm run start:fg ``` - `npm start` starts the backend in the background - `npm stop` stops the process via `data/server.pid` - `npm restart` restarts the backend - `npm run status` shows whether the backend is running - `npm run start:fg` runs in foreground for troubleshooting ### Windows scripts The `windows/` folder includes: - `windows\\start_ammc.bat` starts AMMC in the background - `windows\\start_backend.bat` starts `npm start` in the background (log: `logs\\backend.log`) - `windows\\start_all.bat` starts both AMMC + backend and opens the web page - `windows\\stop_all.bat` stops the backend on port `8081` and `ammc-amb.exe` SQLite database file: - `data\\rc_timing.sqlite` ## Connect to AMMC There are two supported modes. ### A. Managed AMMC from the web UI Important: - AMMC runs on the same host where `npm start` / `node server.js` runs - if you only browse from another laptop, no process starts there - the `AMMC executable` field in `Settings` is a path on the backend host, not the client browser machine 1. Place AMMC binaries in the `AMMC/` project folder. 2. Open `Settings`. 3. Enable `Managed AMMC`. 4. Set `Decoder IP / host`, verify port `9000`, save. 5. Click `Start AMMC`. 6. Click `Use server WS URL` so the client uses for example `ws://: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: ```powershell ammc-amb.exe -w 9000 192.168.1.11 ``` In the app: 1. Open `Settings` 2. Set `WebSocket URL`, for example `ws://127.0.0.1:9000` 3. Set `Backend URL` to `http://127.0.0.1:8081` 4. Click `Test Backend` 5. Go to `Timing` and click `Connect Decoder` If Linux firewall/UFW is enabled: ```bash sudo ufw allow 8081/tcp ``` ## Auto reload during development - The server watches `index.html`, `src/app.js`, and `src/styles.css` - When files in `Live_RC` change, the client reloads automatically - If backend code changes, run `npm 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: - https://www.ammconverter.eu/docs/intro/quick-start/ Example message: ```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" } ```