id: 9c7f99fdd0754673b5fcd1edae935fb3
parent_id: 6d1dc9a77b874fe2b8c14fc0ed3296b6
item_type: 1
item_id: 6c0dcb2a567348fd9796f50c790082e4
item_updated_time: 1780733654994
title_diff: "[]"
body_diff: "[{\"diffs\":[[0,\"*v0.\"],[-1,\"5\"],[1,\"6\"],[0,\".0 — R\"],[-1,\"EST API, Recording Manager, Session Analysis**\"],[1,\"un Deletion, Session Reopen, Feed Merging** |\\\n| **API Reference** | [rusty-telemetry — REST API Reference](joplin://0c837f4e6b7e462a997cbc19e47c864a)\"],[0,\" |\\\n\\\n\"],[-1,\"\\\n\"],[0,\"### \"]],\"start1\":508,\"start2\":508,\"length1\":66,\"length2\":168},{\"diffs\":[[0,\"0.1.\"],[-1,\"0 — Dashboard, Live Feeds, Session Management** |\\\n\\\n### Network Configuration (v0.5.0)\\\n\\\n| Env Var | Purpose | Default |\\\n|---------|---------|---------|\\\n| `RUSTY_TELEMETRY_GAME_HOST` | IP of the machine running the sim game (KSUDP handshake target) | `127.0.0.1` |\\\n| `RUSTY_TELEMETRY_LISTEN` | Local address to bind for incoming UDP feeds (TT, PCARS) | `0.0.0.0` |\\\n| `RUSTY_TELEMETRY_BIND` | Fallback for both (backward compat) | — |\\\n| `RUSTY_TELEMETRY_API_PORT` | REST API server port | `8080` |\\\n| `RUSTY_TELEMETRY_API_HOST` | REST API server bind address | `127.0.0.1` |\\\n\\\n**Same machine** — no config needed:\\\n```bash\\\ncargo run --release\\\n```\\\n\\\n**Remote game machine** — run rusty-telemetry on a separate machine:\\\n```bash\\\n# Analysis machine (e.g. 192.168.1.100), game on 192.168.1.2:\\\nRUSTY_TELEMETRY_GAME_HOST=192.168.1.2 cargo run --release\\\n```\\\nThen configure games to send to the analysis machine's IP:\\\n- **KSUDP**: Works automatically — AC sends telemetry to the handshake's source address\\\n- **Telemetry Tool**: Set `to_ip` to `192.168.1.100` in `config.ini`\\\n- **PCARS**: Set target IP to `192.168.1.100` in in-game UDP settings\\\n\\\n### Module Structure (current — single crate)\\\n\\\n```\\\nrusty-telemetry/\\\n├── Cargo.toml\\\n├── README.md\\\n├── src/\\\n│   ├── main.rs                    (multi-port UDP listener + TUI event loop + auto-recording)\\\n│   ├── api.rs                     (REST API server — axum, recording CRUD, session CRUD, analysis)\\\n│   ├── recording.rs               (recording manager — ring buffers, manifest, UUID dirs, CRUD)\\\n│   ├── session.rs                 (session manager — use-case sessions, runs, frame extraction)\\\n│   ├── analysis.rs                (analysis algorithms — shift points, track mapping)\\\n│   ├── binary_utils.rs            (shared safe binary read helpers)\\\n│   ├── feed_state.rs              (per-feed health/frequency state machine)\\\n│   ├── telemetry_frame.rs         (unified telemetry data model + gear_display)\\\n│   ├── parser_ksudp.rs            (AC port 9996 binary parser)\\\n│   ├── parser_telemetry_tool.rs   (AC port 10101 binary parser)\\\n│   ├── parser_pcars.rs            (AC port 5606 binary parser, V1+V2)\\\n│   └── ui.rs                      (ratatui TUI rendering)\\\n└── data/                          (runtime recording data)\\\n    └── <uuid>/\\\n        ├── manifest.json\\\n        ├── feed_9996_ksudp.jsonl\\\n        ├── feed_10101_telemetry_tool.jsonl\\\n        └── feed_5606_pcars.jsonl\\\n```\"],[1,\"3 — Run Management, Feed Merging, Shifting Charts** |\\\n| **Client Notes** | [racecraft — Vue.js Web Client Notes](joplin://50a09627d5d347009197b94bcee90411) |\\\n\\\n### Related Notes\\\n\\\n| Note | ID |\\\n|------|----|\\\n| [Architecture & Infrastructure](joplin://c1c3a7b2055642268ab230b95551f470) | Client vs. Server, Desktop Packaging, Pre-Calculated Data |\\\n| [AC — UDP Protocol Spec](joplin://aed9f3be040943048273a16e05a8100f) | Assetto Corsa telemetry binary protocol |\\\n| [ACC — UDP Protocol Spec](joplin://6ae7005d9810437093d63470cff98b59) | ACC telemetry protocol (registration + broadcast) |\\\n| [AC EVO — Telemetry Research](joplin://2171d34ab9c1431ea3a979d30d206e23) | AC EVO status — no known telemetry output yet |\\\n| [AC Rally — Telemetry Research](joplin://b7b331aa87544b6ebe5db5b8d7bcd2a0) | AC Rally status — UE5, no known telemetry output yet |\"],[0,\"\\\n\\\n--\"]],\"start1\":1025,\"start2\":1025,\"length1\":2423,\"length2\":850},{\"diffs\":[[0,\"is (\"],[-1,\"boundary extraction with \"],[0,\"spli\"]],\"start1\":5907,\"start2\":5907,\"length1\":33,\"length2\":8},{\"diffs\":[[0,\"ents\"],[-1,\"** (planned — \"],[1,\" — IMPLEMENTED IN v0.6.0 (\"],[0,\"both\"]],\"start1\":6612,\"start2\":6612,\"length1\":22,\"length2\":34},{\"diffs\":[[0,\"h repos)\"],[1,\"**\"],[0,\"\\\n  - [\"],[-1,\" \"],[1,\"x\"],[0,\"] **Feed\"]],\"start1\":6645,\"start2\":6645,\"length1\":23,\"length2\":25},{\"diffs\":[[0,\"eeds\"],[-1,\" (e.g. KSUDP + Telemetry Tool)\"],[0,\" int\"]],\"start1\":6711,\"start2\":6711,\"length1\":38,\"length2\":8},{\"diffs\":[[0,\"data\"],[-1,\". When two feeds are available during a recording, offer a \\\"merge feeds\\\" option on a run to interleave/cross-reference data from both sources. Requires API changes in `rusty-telemetry`:\"],[0,\"\\\n   \"]],\"start1\":6752,\"start2\":6752,\"length1\":193,\"length2\":8},{\"diffs\":[[0,\"tend\"],[-1,\" `StartRunRequest`\"],[1,\"ed\"],[0,\" wit\"]],\"start1\":6798,\"start2\":6798,\"length1\":26,\"length2\":10},{\"diffs\":[[0,\"g[]`\"],[-1,\" to specify which feeds to merge\\\n    - `session.rs` — `extract_run_frames` needs a merge mode that combines frames from multiple feeds, deduplicating by timestamp and preferring higher-quality data\\\n    - `analysis.rs` — merged runs should use the combined dataset for gear curve calculations\"],[1,\"\\\n    - `session.rs` — `start_run` accepts merge feeds, `extract_run_frames` combines frames from multiple feeds\\\n    - racecraft: merge feeds toggle with feed checkboxes when starting a run\"],[0,\"\\\n  - [\"],[-1,\" \"],[1,\"x\"],[0,\"] **\"]],\"start1\":6838,\"start2\":6838,\"length1\":306,\"length2\":203},{\"diffs\":[[0,\"* — \"],[-1,\"Allow d\"],[1,\"D\"],[0,\"elet\"],[-1,\"ing\"],[1,\"e\"],[0,\" ind\"]],\"start1\":7054,\"start2\":7054,\"length1\":22,\"length2\":14},{\"diffs\":[[0,\"runs\"],[-1,\" from a session, both during an active recording and after \"],[1,\", wi\"],[0,\"th\"],[-1,\"e\"],[0,\" ses\"]],\"start1\":7076,\"start2\":7076,\"length1\":70,\"length2\":14},{\"diffs\":[[0,\"ion \"],[-1,\"is completed. When deleting from a completed session, offer the option to re-open the session for further recording. Requires API changes in `rusty-telemetry`:\"],[1,\"reopen option\"],[0,\"\\\n   \"]],\"start1\":7091,\"start2\":7091,\"length1\":167,\"length2\":21},{\"diffs\":[[0,\" session\"],[1,\" (returns 204)\"],[0,\"\\\n    - `\"]],\"start1\":7178,\"start2\":7178,\"length1\":16,\"length2\":30},{\"diffs\":[[0,\"open` — re-open \"],[-1,\"a \"],[0,\"completed sessio\"]],\"start1\":7234,\"start2\":7234,\"length1\":34,\"length2\":32},{\"diffs\":[[0,\"ion \"],[-1,\"to allow adding more runs\\\n    - `session.rs` — add run deletion logic, handle session status transitions (completed → active)\\\n    - `api.rs` — add the two new endpoints\\\n  - [ ] racecraft UI: add merge feeds toggle when starting a run (if multiple feeds available)\\\n  - [ ] racecraft UI: add delete button per run with confirmation dialog\\\n  - [ ] racecraft UI: add reopen session button on completed sess\"],[1,\"(status → active)\\\n    - racecraft: delete button per run with confirmation; reopen button on completed sessions\\\n\\\n- **1.10 Shifting Analysis Charts — IMPLEMENTED IN v0.1.2 (racecraft)**\\\n  - [x] RPM vs. Force scatter chart (x: RPM, y: acceleration_g)\\\n  - [x] Speed vs. Force scatter chart (x: speed_kmh, y: acceleration_g) — renamed from \\\"Gear Acceleration Curves\\\"\\\n  - [x] Speed vs. RPM scatter chart (x: speed_kmh, y: rpm) — gear ratio visualizat\"],[0,\"ion\"],[-1,\"s\"],[0,\"\\\n\\\n--\"]],\"start1\":7264,\"start2\":7264,\"length1\":414,\"length2\":456},{\"diffs\":[[0,\"erence\\\n\\\n\"],[1,\"> **Full API documentation moved to:** [rusty-telemetry — REST API Reference](joplin://0c837f4e6b7e462a997cbc19e47c864a)\\\n> That note contains all endpoints, request/response formats, environment variables, and UDP port configuration.\\\n\\\n\"],[0,\"### Envi\"]],\"start1\":7935,\"start2\":7935,\"length1\":16,\"length2\":251},{\"diffs\":[[0,\"ariables\"],[1,\" (quick reference)\"],[0,\"\\\n\\\n| Vari\"]],\"start1\":8195,\"start2\":8195,\"length1\":16,\"length2\":34},{\"diffs\":[[0,\"hine\"],[-1,\" (KSUDP handshake target, AC :9996)\"],[0,\" | `\"]],\"start1\":8338,\"start2\":8338,\"length1\":43,\"length2\":8},{\"diffs\":[[0,\" Local bind \"],[-1,\"address \"],[0,\"for incoming\"]],\"start1\":8387,\"start2\":8387,\"length1\":32,\"length2\":24},{\"diffs\":[[0,\"eeds\"],[-1,\" (TT :10101, PCARS :5606)\"],[0,\" | `\"]],\"start1\":8413,\"start2\":8413,\"length1\":33,\"length2\":8},{\"diffs\":[[0,\"` |\\\n\"],[-1,\"| `RUSTY_TELEMETRY_BIND` | Legacy fallback for both of the above | — |\\\n\"],[0,\"| `R\"]],\"start1\":8428,\"start2\":8428,\"length1\":79,\"length2\":8},{\"diffs\":[[0,\"EST API \"],[-1,\"server \"],[0,\"port | `\"]],\"start1\":8464,\"start2\":8464,\"length1\":23,\"length2\":16},{\"diffs\":[[0,\"EST API \"],[-1,\"server \"],[0,\"bind add\"]],\"start1\":8520,\"start2\":8520,\"length1\":23,\"length2\":16},{\"diffs\":[[0,\" |\\\n\\\n\"],[-1,\"### Port 9996 (KSUDP) — 3-Phase Handshake Protocol\\\n- AC binds to `0.0.0.0:9996` — accepts handshakes from any IP\\\n- rusty-telemetry sends handshake to `$GAME_HOST:9996`\\\n- AC responds to the source address of the handshake → works across machines\\\n- **Reference**: https://docs.google.com/document/d/1KfkZiIluXZ6mMhLWfDX1qAGbvhGRC3ZUzjVIt5FQpp4/pub\\\n\\\n### Port 10101 (Telemetry Tool Plugin) — OPTIONAL ✅\\\n- Config: `<AC>/apps/python/Telemetry_Tool_plugin/config.ini`\\\n- Set `to_ip` to the analysis machine's IP for remote operation\\\n- **Optional** — if rusty-telemetry can't bind :10101, continues without it\\\n\\\n### Port 5606 (PCARS) — Bind/Listen ✅ (IMPLEMENTED v0.4.0)\\\n- PCARS sends to a configured target IP:port (default 5606)\\\n- rusty-telemetry binds to `$LISTEN:5606` and listens\\\n- Configure in PCARS: Options → System → UDP Protocol → set target IP/port\\\n- PCARS 1: set format to \\\"Project CARS\\\"\\\n- PCARS 2: set format to \\\"2\\\" for native format, or \\\"1\\\" for PCARS1-compatible\\\n- **Optional** — if bind fails, shows as \\\"not available\\\" and continues\\\n\\\n### REST API — Port 8080 (IMPLEMENTED v0.5.0)\\\n- Axum HTTP server with CORS enabled\\\n- `GET /api/live` — live telemetry snapshot (all feeds: health, frequency, speed, RPM, gear, inputs, lap time)\\\n- `GET /api/recordings` — list all recordings\\\n- `POST /api/recordings` — start new recording (JSON: name, game, track, car, use_case, notes — all optional)\\\n- `POST /api/recordings/stop` — stop active recording\\\n- `GET /api/recordings/{id}` — get recording manifest\\\n- `POST /api/recordings/{id}/stop` — stop specific recording\\\n- `DELETE /api/recordings/{id}` — delete recording (removes directory)\\\n- `GET /api/recordings/{id}/data/{feed_name}` — download raw feed binary\\\n- `GET /api/use-cases` — list valid use cases (shift_points, racing_line, braking_analysis, lap_times, sector_analysis, track_map, general)\\\n- `GET /api/games` — list supported games (assetto_corsa, assetto_corsa_competizione, project_cars_1, project_cars_2)\\\n- `GET /api/sessions` — list all sessions\\\n- `POST /api/sessions` — create analysis session (JSON: use_case, label)\\\n- `GET /api/sessions/{id}` — get session details\\\n- `DELETE /api/sessions/{id}` — delete session\\\n- `POST /api/sessions/{id}/runs` — start a run (JSON: feed_name, label)\\\n- `POST /api/sessions/{id}/runs/{run_id}/stop` — stop a run\\\n- `POST /api/sessions/{id}/complete` — complete session and auto-analyze\\\n- `GET /api/sessions/{id}/analysis` — get analysis results\\\n- `POST /api/sessions/{id}/analyze` — re-run analysis on completed session\\\n\\\n### Planned REST API additions (see §1.9)\\\n- `DELETE /api/sessions/{id}/runs/{run_id}` — delete a run from a session\\\n- `POST /api/sessions/{id}/reopen` — re-open a completed session for further recording\\\n- `POST /api/sessions/{id}/runs` — extend with optional `merge_feeds` field\\\n\\\n### Port 5005 (AC Lua Plugin) — REMOVED in v0.3.0\\\n- Abandoned — CSP lacks compiled LuaSocket C core\\\n\\\n\"],[0,\"---\\\n\"]],\"start1\":8554,\"start2\":8554,\"length1\":2900,\"length2\":8},{\"diffs\":[[0,\"s IP\"],[-1,\" (TT config.ini, PCARS in-game settings)\"],[0,\"\\\n3. \"]],\"start1\":9001,\"start2\":9001,\"length1\":48,\"length2\":8},{\"diffs\":[[0,\"try \"],[-1,\"on analysis machine \"],[0,\"with\"]],\"start1\":9027,\"start2\":9027,\"length1\":28,\"length2\":8},{\"diffs\":[[0,\"P>`\\\n\"],[-1,\"4. KSUDP: handshake goes to game machine, telemetry streams back automatically\\\n\\\n---\\\n\\\n## 15. Change Log\\\n\\\n### racecraft v0.1.2 (2026-06-06) — Shifting Analysis Chart Renames\\\n\\\n**UI:**\\\n- Renamed \\\"RPM vs. Acceleration (Tractive Force)\\\" chart → \\\"RPM vs. Force\\\" (cleaner title, y-axis label \\\"Force (g)\\\")\\\n- Renamed \\\"Gear Acceleration Curves\\\" chart → \\\"Speed vs. Force\\\" (describes actual axes: speed on x, force on y)\\\n- Chart order remains: RPM vs. Force → Speed vs. Force → Speed vs. RPM (Gear Ratios) → Crossover Points\\\n\\\n### racecraft v0.1.1 (2026-06-05) — Dashboard Status Card Layout\\\n\\\n**UI:**\\\n- Refactored System Status section to display API Server, Sim Connection, and Recording as three individual cards in a row (3-column grid) instead of vertically stacked rows\\\n- Each status card now has its own background, border, and rounded corners\\\n- Responsive: collapses to single column on screens below 768px\\\n- Saves vertical screen space, reduces need for scrolling\\\n\\\n### v0.5.0 (2026-06-05) — REST API, Recording M\"],[1,\"\\\n---\\\n\\\n## 15. Change Log\\\n\\\n> **Per-repo change logs moved to:**\\\n> - [rusty-telemetry — REST API Reference](joplin://0c837f4e6b7e462a997cbc19e47c864a) (backend version history)\\\n> - [racecraft — Vue.js Web Client Notes](joplin://50a09627d5d347009197b94bcee90411) (frontend version history)\\\n\\\n### Recent Ch\"],[0,\"an\"],[-1,\"a\"],[0,\"ge\"],[-1,\"r, Session Analysis\\\n\\\n**New Features:**\\\n- REST API server (axum) on configurable port (default 8080, default host 127.0.0.1)\\\n- Recording session manager with UUID-based session directories, JSON manifests, auto-start on launch\\\n- Live telemetry endpoint with per-feed snapshots (health, frequency, speed, RPM, gear, inputs, lap time)\\\n- Recording CRUD: create, list, get, stop, delete via REST API\\\n- Feed data endpoint: read frames from active ring buffer or stopped JSONL on disk\\\n- Use case taxonomy (shift_points, racing_line, braking_analysis, lap_times, sector_analysis, track_map, general)\\\n\\\n**Session Management & Analysis:**\\\n- Use-case sessions: create, start runs, stop runs, complete with auto-analysis\\\n- Shift point analysis: gear RPM ranges, upshift detection, recommended shift RPM\\\n- Track map analysis: boundary extraction with spline-aligned interpolation for center line\\\n- `data_truncated` flag detects ring buffer wrap on runs\\\n- 9 session API endpoints (CRUD, run management, analysis triggers, re-analysis)\\\n\\\n**Architecture:**\\\n- Always-on ring buffers (5 min, 18k frames per feed) replacing raw binary dumps\\\n- Ring buffer flush to JSONL on recording stop/shutdown\\\n- Mutex poisoning recovery on all session API handlers\\\n- Flush: ring buffer lock held only during frame clone, JSON serialization outside lock\\\n- Flush failures propagated (manifest not saved as Stopped on failure)\\\n- `stop_recording` holds active lock across flush (prevents race with `start_recording`)\\\n\\\n**New Modules:**\\\n- `src/session.rs` (256 lines) — SessionManager with use-case sessions, runs, frame extraction\\\n- `src/analysis.rs` (300 lines) — Shift point analysis, track map analysis, dispatch\\\n- `src/api.rs` (526 lines) — REST API with recording + session endpoints\\\n- `src/recording.rs` (501 lines) — RecordingManager with ring buffers, manifest CRUD, flush\\\n\\\n**New Dependencies:**\\\n- axum 0.8, serde 1 (derive), serde_json 1, uuid 1 (v4, serde), tower-http 0.6 (cors)\\\n\\\n**Documentation:**\\\n- Updated README.md with session API docs, analysis response examples, ring buffer architecture\\\n\\\n###\"],[1,\"s (summary)\\\n\\\n| Version | Date | Highlights |\\\n|---------|------|------------|\\\n| rusty-telemetry v0.6.0 | 2026-06-06 | Run deletion, session reopen, feed merging |\\\n| racecraft v0.1.3 | 2026-06-06 | Run management UI, feed merging toggle, session reopen button |\\\n| racecraft v0.1.2 | 2026-06-06 | RPM vs. Force, Speed vs. RPM charts, chart renames |\\\n| racecraft v0.1.1 | 2026-06-05 | Dashboard status card layout (3-column grid) |\\\n| rusty-telemetry v0.5.0 | 2026-06-05 | REST API, recording manager, session analysis |\\\n| rusty-telemetry\"],[0,\" v0.4.1 \"],[-1,\"(\"],[1,\"| \"],[0,\"2026\"]],\"start1\":9070,\"start2\":9070,\"length1\":3099,\"length2\":855},{\"diffs\":[[0,\"6-04\"],[-1,\") —\"],[1,\" |\"],[0,\" Remote \"],[-1,\"O\"],[1,\"o\"],[0,\"pera\"]],\"start1\":9927,\"start2\":9927,\"length1\":20,\"length2\":19},{\"diffs\":[[0,\"ion \"],[-1,\"S\"],[1,\"s\"],[0,\"upport\"],[-1,\"\\\n\\\n- Split `RUSTY_TELEMETRY_BIND` into `RUSTY_TELEMETRY_GAME_HOST` and `RUSTY_TELEMETRY_LISTEN`\\\n- `GAME_HOST` controls KSUDP handshake target (IP of the sim machine), default `127.0.0.1`\\\n- `LISTEN` controls local bind address for incoming feeds, default `0.0.0.0` (any interface)\\\n- Both fall back to `RUSTY_TELEMETRY_BIND` for backward compatibility\\\n- Updated README.md with full usage documentation, feed setup, TUI description, architecture\\\n\\\n###\"],[1,\" (GAME_HOST/LISTEN split) |\\\n| rusty-telemetry\"],[0,\" v0.4.0 \"],[-1,\"(\"],[1,\"| \"],[0,\"2026\"]],\"start1\":9947,\"start2\":9947,\"length1\":470,\"length2\":70},{\"diffs\":[[0,\"6-04\"],[-1,\") — PCARS Support + Code Quality\\\n\\\n**New Features:**\\\n- Added PCARS 1 & 2 UDP telemetry parser (port 5606) with auto-detection\\\n- Auto-detects PCARS1 (1367-byte V1 format) vs PCARS2 (559-byte V2 format)\\\n- Maps PCARS-specific data: engine temps, damage, weather, tyre wear, 3D position\\\n- PCARS feed appears as third panel in TUI (optional, degrades gracefully)\\\n\\\n**Code Quality:**\\\n- Created shared `binary_utils` module — eliminates duplicated read helpers across parsers\\\n- All read helpers use safe `get()` bounds checking (return zero fallback instead of panicking)\\\n- Moved parsing outside mutex lock to minimize contention with TUI render thread\\\n- Added `parse_first_driver()` for Telemetry Tool — avoids unnecessary multi-driver Vec allocation\\\n- Removed dead code: `speed_display()`, `ValidationFailed` variant, `NoDrivers` variant\\\n- Removed unused `serde` dependency from Cargo.toml\\\n- Renamed `data_rate_kbps` → `data_rate_kb_s` (correct unit: kilobytes/sec)\\\n- 32 unit tests (14 feed_state + 6 ksudp + 7 telemetry_tool + 5 pcars)\\\n\\\n###\"],[1,\" | PCARS 1 & 2 support, binary_utils refactor |\\\n| rusty-telemetry\"],[0,\" v0.3.0 \"],[-1,\"(\"],[1,\"| \"],[0,\"2026\"]],\"start1\":10019,\"start2\":10019,\"length1\":1051,\"length2\":83},{\"diffs\":[[0,\"6-04\"],[-1,\") —\"],[1,\" |\"],[0,\" TUI\"],[-1,\" + Binary Parsers + Handshake Fix\\\n\\\n**Major Changes:**\\\n- Replaced stdout data dump with ratatui/crossterm TUI\\\n- Implemented KSUDP 3-phase handshake protocol (was broken — only sent 4-byte handshake)\\\n- Added binary parsers for KSUDP (port 9996) and Telemetry Tool (port 10101)\\\n- Added ring-buffer frequency calculation and feed health state machine\\\n- Made Telemetry Tool feed optional (degrades gracefully if bind fails)\\\n- Removed port 5005 (Lua plugin — abandoned)\\\n- Per-feed TUI panels with health indicators, frequency, data rate, telemetry snapshot\"],[1,\", KSUDP handshake fix, binary parsers |\"],[0,\"\\\n\\\n--\"]],\"start1\":10104,\"start2\":10104,\"length1\":565,\"length2\":53},{\"diffs\":[[0,\"ave (v0.\"],[-1,\"5\"],[1,\"6\"],[0,\".0):**\\\n-\"]],\"start1\":10441,\"start2\":10441,\"length1\":17,\"length2\":17},{\"diffs\":[[0,\" management,\"],[1,\" run management (delete, merge feeds, reopen),\"],[0,\" and basic a\"]],\"start1\":10716,\"start2\":10716,\"length1\":24,\"length2\":70},{\"diffs\":[[0,\" management,\"],[1,\" run management,\"],[0,\" and shiftin\"]],\"start1\":10891,\"start2\":10891,\"length1\":24,\"length2\":40},{\"diffs\":[[0,\"ased\"],[-1,\" (no app)\"],[0,\" | 1\"]],\"start1\":12325,\"start2\":12325,\"length1\":17,\"length2\":8},{\"diffs\":[[0,\") | \"],[-1,\"The industry standard for real motorsport. Sim racers use it via exported data. Extremely powerful but steep learning curve. |\\\n| **ATLAS (McLaren Applied)** | F1-grade telemetry system | Enterprise / F1-only | Multi-million dollar per season. Not available to consumers. |\\\n| **Cosworth Toolbox** | Real racing data analysis | License-based | Used in WEC, IndyCar, Touring Cars |\\\n| **Dell/AMD F1 partnership** | Real-time F1 telemetry | Not for sale | F1 teams use bespoke systems built on Dell servers + AMD GPUs |\\\n\\\n#### Tier 3: Community & Content Platforms\\\n\\\n| Product | Role | Rally Coverage | Notes |\\\n|---|---|---|---|\\\n| **OverTake.gg** (formerly RaceDepartment) | Sim racing community hub, news, forums, mods | Has WRC, AC Rally categories; partnered with Track Titan for coaching benefits | The Track Titan × OverTake collaboration is exactly what the user asked about — OverTake integrates Track Titan's coaching & setup tools as a \\\"Community Benefit\\\" |\\\n| **Race Sim Studio** | Car mods for AC/AMS2 | Limited | No telemetry |\\\n| **SimulatorController** | AI driving coach, race engineer, spotter | Supports AC, ACC, RRE, PCARS, AMS2, RF2, LMU | Open-source, runs locally. Has telemetry integration but focused on AI voice coaching, not data analysis. |\\\n\\\n---\\\n\\\n### 16.3 The Track Titan × OverTake Model\\\n\\\nTrack Titan's collaboration with OverTake.gg (formerly RaceDepartment, the largest sim racing community with 2M+ registered users) is the case study for how to build a product in this space:\\\n\\\n**The Model:**\\\n1. **Track Titan** builds the telemetry + coaching technology (SaaS product)\\\n2. **OverTake.gg** provides the community, content, and distribution channel\\\n3. OverTake integrates Track Titan as a \\\"Community Benefit\\\" — coaching & setups for OverTake members\\\n4. Track Titan gains user acquisition through OverTake's massive audience\\\n5. Both parties monetize: Track Titan through subscriptions, OverTake through premium memberships\\\n\\\n**Why it works:**\\\n- Track Titan doesn't need to build a community from scratch\\\n- OverTake doesn't need to build telemetry technology\\\n- The sim racing market is fragmented across many games — a platform approach works better than a single-game tool\\\n- Freemium model (free basic telemetry, paid AI coaching/setups) lowers barrier to entry\\\n\\\n**Key lesson for us:** Distribution and community matter as much as technology. Track Titan has Porsche Ventures and former WRC/F1 executives as investors — they understand that the go-to-market is about partnerships and network effects, not just having better algorithms.\\\n\\\n---\\\n\\\n### 16.4 Rally Telemetry — The Underserved Market\\\n\\\n**Does anything like Track Titan exist for rally games?**\\\n\\\n**No.** This is a significant gap in the market. Here's what currently exists:\\\n\\\n| Tool | Rally Support | Limitation |\\\n|---|---|---|\\\n| Track Titan | None | Circuit racing only — no rally stages, pacenotes, or stage-based analysis |\\\n| SimRacingSetup | None | F1-focused |\\\n| VRS | None | iRacing circuit only |\\\n| MoTeC i2 | Can import rally data if exported | Requires manual data export, no direct game integration, no rally-specific analysis |\\\n| Dirt Rally 2.0 built-in | Basic stage times | No telemetry overlays, no coaching, no lap comparison |\\\n| Richard Burns Rally community tools | NGP plugin, some data export | Fragmented, technical, not user-friendly |\\\n| EA Sports WRC | Basic stage recap | No telemetry export API, no third-party analysis |\\\n\\\n**Why rally is different from circuit racing:**\\\n\\\n| Aspect | Circuit Racing | Rally |\\\n|---|---|---|\\\n| Track | Static, memorizable | Dynamic, pacenote-dependent |\\\n| Surface | Uniform (asphalt/curbs) | Mixed (gravel, tarmac, snow, ice, mud) |\\\n| Analysis unit | Lap time | Stage time (no repeated laps on same surface) |\\\n| Key metric | Consistency across laps | Commitment to pacenotes, surface adaptation |\\\n| Coaching focus | Braking points, racing line, throttle application | Pacenote accuracy, weight transfer on loose surfaces, car setup for mixed conditions |\\\n| Comparison | Lap overlay against reference lap | Split-time comparison against other drivers on same stage |\\\n| Data richness | Very high (60 Hz all channels) | Variable — depends on game's UDP output |\\\n\\\n**Assetto Corsa Rally** (the new rally expansion for AC, covered on OverTake.gg) changes the game because:\\\n- AC already has rich telemetry output (our 10101 port works)\\\n- AC Rally runs on the same engine → same parsers apply\\\n- The rally modding community is massive\\\n- Combined circuit + rally telemetry analysis from the SAME platform is novel\\\n\\\n**This is a genuine differentiator.** No other telemetry platform offers both circuit AND rally coaching in one tool.\\\n\\\n---\\\n\\\n### 16.5 Real-World Racing Telemetry — Do Real Teams Use This?\\\n\\\n**Yes, extensively.** Telemetry is fundamental to professional motorsport at every level:\\\n\\\n#### Track Racing (Circuit)\\\n\\\n| Category | Telemetry System | What They Analyze | Cost Level |\\\n|---|---|---|---|\\\n| **Formula 1** | McLaren ATLAS, bespoke systems | Everything: tyre temps, brake bias, engine maps, aero balance, driver inputs, fuel flow, ERS deployment | $1M+/season |\\\n| **WEC / Le Mans** | MoTeC, Cosworth, Magnetti Marelli | Tyre degradation over stints, fuel strategy, driver consistency, traffic management | $50K–500K/season |\\\n| **GT3 / IMSA** | MoTeC, AIM, Bosch | Suspension loads, brake temperatures, tyre pressures, driver inputs | $10K–100K/season |\\\n| **Touring Cars** | MoTeC, Stack, Race Technology | Engine mapping, chassis setup, driver technique | $5K–50K/season |\\\n| **Club / Amateur** | Garmin Catalyst, RaceLogic VBOX, TrackAddict | GPS lines, lap times, basic G-forces, video overlay | $500–5,000 |\\\n\\\n#### Rally (WRC and National Level)\\\n\\\n| Category | Telemetry System | What They Analyze | Notes |\\\n|---|---|---|---|\\\n| **WRC (factory teams)** | Bespoke systems (Hyundai, Toyota, M-Sport each have proprietary setups) | Damper data, suspension travel, split times, surface grip estimation, pacenote timing correlation, turbo boost, differential mapping | WRC cars have ~200 sensor channels. Data is transmitted in real-time back to service park via satellite/4G. |\\\n| **WRC2 / WRC3** | MoTeC, SRA (Stage Rally Analysis) | Stage times, suspension, driver inputs | More budget-constrained, still sophisticated |\\\n| **National Rally** | Various (RaceLogic VBOX, basic data loggers) | GPS tracks, stage times, basic G-forces | Growing adoption as costs decrease |\\\n| **Rallycross** | MoTeC, AIM | Launch data, suspension, tyre management for multi-lap format | Hybrid/EV rallycross adds energy management |\\\n\\\n**Key insight for product strategy:** Real racing teams already have expensive, purpose-built telemetry systems. The market gap is NOT in selling to F1 teams — it's in democratizing professional-grade analysis for:\\\n1. **Sim racers** who want to improve (Track Titan's 285K users prove this market exists)\\\n2. **Club/amateur real racers** who can't afford MoTeC-level systems ($500–5K budget)\\\n3. **Rally drivers at national level** who have NO accessible telemetry platform\\\n4. **Sim-to-real pipeline** — drivers who train in sims and want consistent analysis across both\\\n\\\n---\\\n\\\n### 16.6 Product Roadmap — From v0.5.0 to Sellable Product\\\n\\\n#### Phase A: Complete the Core (Months 1–3)\\\n\\\n**Goal:** Make the existing tool genuinely useful for personal use, then shareable.\\\n\\\n| Milestone | Tasks | Success Metric |\\\n|---|---|---|\\\n| **A1: Verify with live sessions** | Test KSUDP + PCARS with real game sessions; fix any issues | All 3 feeds working reliably with live gameplay |\\\n| **A2: §1.9 implementation** | Feed merging, run deletion, session reopen | Multi-feed analysis working end-to-end |\\\n| **A3: WebSocket streaming** | Replace REST polling with real-time WS for live telemetry | <50ms latency from game → browser |\\\n| **A4: Lap detection** | Auto-detect laps from spline position crossing start/finish | Automatic lap segmentation without manual marking |\\\n| **A5: Reference lap overlay** | Allow loading a \\\"reference\\\" lap and overlaying current lap against it | Visual overlay of two laps with delta trace |\\\n| **A6: Tyre analysis** | Tyre temperature heat maps, tyre wear projection over stint | Graphs showing tyre degradation curves |\\\n| **A7: Brake analysis** | Brake pressure traces, braking point consistency scoring | Per-corner braking analysis with consistency rating |\\\n\\\n#### Phase B: Multi-Game & Rally Support (Months 4–6)\\\n\\\n**Goal:** Expand beyond AC to cover the sim racing ecosystem.\\\n\\\n| Milestone | Tasks | Success Metric |\\\n|---|---|---|\\\n| **B1: ACC support** | ACC UDP telemetry parser (port unchanged from AC, but different data structure) | ACC sessions captured and analyzed |\\\n| **B2: iRacing support** | iRacing telemetry via YAML file or memory-mapped file | iRacing sessions captured |\\\n| **B3: Rally game support** | Add support for AC Rally, Dirt Rally 2.0, EA WRC UDP output | Rally stages captured and analyzed |\\\n| **B4: Rally-specific analysis** | Stage-based analysis (not laps), surface type detection, pacenote timing, split time comparison | Rally coaching insights unique to rally discipline |\\\n| **B5: F1 game support** | F1 2025/26 UDP telemetry (widely documented, standard format) | F1 sessions captured — access to largest casual sim racing audience |\\\n\\\n#### Phase C: AI Coaching & Automation (Months 7–10)\\\n\\\n**Goal:** This is the moat. Raw telemetry is a commodity; AI-driven coaching is the product.\\\n\\\n| Milestone | Tasks | Success Metric |\\\n|---|---|---|\\\n| **C1: Automated anomaly detection** | ML model to detect \\\"unusual\\\" inputs (late braking, early throttle, inconsistent steering) | System highlights top 3 mistakes per lap without user input |\\\n| **C2: Coaching Flows (Track Titan's killer feature)** | Step-by-step guided analysis: \\\"Here's your biggest time loss, here's how to fix it\\\" | Users get actionable advice, not just raw data |\\\n| **C3: Setup recommendations** | Correlate telemetry patterns with setup changes; suggest adjustments | \\\"Your rear tyre temps are 15°C too high — try reducing rear anti-roll bar\\\" |\\\n| **C4: LLM-powered coaching chat** | Integrate LLM (local or API) to answer questions about telemetry in natural language | \\\"Why am I losing time in Turn 3?\\\" → detailed explanation with data references |\\\n| **C5: Rally pacenote analysis** | Correlate pacenote calls (if game provides them) with driver inputs to find commitment issues | \\\"You're lifting 30m early on every '4 left' — here's where you're losing 2.3s per stage\\\" |\\\n\\\n#### Phase D: Platform & Monetization (Months 11–18)\\\n\\\n**Goal:** Turn it into a business.\\\n\\\n| Milestone | Tasks | Success Metric |\\\n|---|---|---|\\\n| **D1: User accounts & cloud sync** | Authentication, cloud storage for recordings, cross-device access | Users can access their data from any device |\\\n| **D2: Community features** | Leaderboards, lap sharing, setup sharing, driver profiles | Users share and compare laps with others |\\\n| **D3: Freemium model** | Free tier (basic telemetry) + Pro tier (AI coaching, reference laps, advanced analysis) | Revenue model validated |\\\n| **D4: Partnership with community platform** | OverTake.gg-style partnership with a rally or sim racing community | Distribution channel established |\\\n| **D5: Mobile companion app** | iOS/Android app for post-session review, notifications, coaching alerts | Users review sessions on mobile |\\\n| **D6: Real-world telemetry bridge** | Support OBD-II / CAN bus data from real cars; combine sim data with real data for sim-to-real coaching | Product works for both sim and real racing |\\\n\\\n---\\\n\\\n### 16.7 Revenue Model Options\\\n\\\n| Model | Pricing | Target Audience | Revenue Potential | Feasibility |\\\n|---|---|---|---|---|\\\n| **SaaS Subscription** (Track Titan model) | Free basic + £5–10/mo Pro + £15/mo Teams | Sim racers, esports teams | Medium-High | High — proven model |\\\n| **One-time License** (MoTeC model) | $99–299 perpetual license | Serious sim racers, small teams | Medium | Medium — less predictable revenue |\\\n| **API / SDK Platform** | Per-call or per-seat licensing | Sim racing app developers, esports leagues | High if adopted | Low — requires ecosystem |\\\n| **Coaching Marketplace** | Commission on 1:1 coaching sessions | Sim racers wanting personalized coaching | Medium | Medium — needs coach supply |\\\n| **Enterprise / Team** | $50–200/mo per team seat | Esports organizations, racing academies | High | Medium — needs team features |\\\n| **Real Racing Telemetry** | $20–50/mo + hardware bundle | Club racers, rally drivers, track day enthusiasts | Very High | Low — requires hardware R&D |\\\n\\\n**Recommended: Start with SaaS Freemium** (Track Titan model), evolve toward real racing telemetry as a premium tier.\\\n\\\n---\\\n\\\n### 16.8 Unique Differentiators — What Would Make This Stand Out\\\n\\\n1. **Circuit + Rally in one platform** — Nobody does this. Track Titan is circuit-only. SimRacingSetup is F1-only. A platform that handles both Vallelunga GP AND Monte Carlo Rally stage analysis is genuinely novel.\\\n\\\n2. **Open-source core** — MoTeC i2 costs thousands. An open-source telemetry platform (like how VS Code is open-source but monetized via services) builds trust and community. The rusty-telemetry backend could be open-source while the AI coaching SaaS is proprietary.\\\n\\\n3. **Rust performance** — 60 Hz telemetry with real-time analysis in <50ms. Most competitors use Python or Electron. Rust gives us a genuine edge in processing large datasets (long endurance races, multi-hour rally stages).\\\n\\\n4. **Self-hostable option** — Privacy-conscious users, teams, and racing academies who don't want their data on someone else's cloud. Premium feature: \\\"deploy on your own server.\\\"\\\n\\\n5. **Sim-to-real bridge** — Long-term vision: the same analysis tools work for your sim sessions AND your real track days (via OBD-II/CAN data). No competitor offers this unified experience today.\\\n\\\n6. **AI coaching built on local LLMs** — Privacy-preserving AI coaching that runs locally. No need to upload telemetry to a cloud for analysis. This matters to serious racers who consider their data competitive intelligence.\\\n\\\n---\\\n\\\n### 16.9 Key Risks & Mitigation\\\n\\\n| Risk | Probability | Impact | Mitigation |\\\n|---|---|---|---|\\\n| Track Titan expands to rally | Medium | High — eliminates our key differentiator | Move fast on rally support; build deeper rally-specific features (pacenote analysis, surface adaptation) |\\\n| Game devs restrict telemetry access | Low | Critical — kills the product | Support many games to avoid single-point dependency; engage game devs as partners |\\\n| AI coaching requires massive training data | High | Medium — limits coaching quality | Start with rule-based coaching (no ML needed for \\\"brake later here\\\"); crowdsource training data from community |\\\n| Real racing telemetry requires hardware | High | High — significant R&D cost | Defer real racing to Phase D+; validate with sim racing first; partner with existing hardware vendors (RaceLogic, Garmin) |\\\n| User acquisition cost too high | Medium | High — can't build sustainable business | Partner with community platforms (OverTake model); open-source core builds organic adoption; content marketing (YouTube coaching videos) |\\\n\\\n---\\\n\\\n### 16.10 Recommended First Steps (Next 30 Days)\\\n\\\n1. **Ship §1.9** (feed merging, run deletion) — makes the tool genuinely usable for multi-feed analysis\\\n2. **Verify with live AC session** — prove the whole stack works end-to-end with real gameplay\\\n3. **Add lap detection** — auto-segment laps from spline data (critical for any coaching feature)\\\n4. **Build reference lap overlay** — the single most requested feature in sim racing telemetry (this is what makes Track Titan sticky)\\\n5. **Research AC Rally telemetry output** — determine if our existing parsers work with the new rally expansion\\\n6. **Draft the rally coaching model** — what does \\\"coaching\\\" look like for a rally stage vs. a circuit lap?\\\n\\\n---\\\n\\\n## 17. Analysis Use Cases — Track Mapping, Corner Analysis & Ideal Lap\\\n\\\n> **Analysis date: 2026-06-06**\\\n> **Goal: Define the next analysis use cases beyond shift points, with track mapping as the foundation for everything that follows.**\\\n\\\n---\\\n\\\n### 17.1 Why Track Mapping Must Come First — The Deliberate Boundary Recording Method\\\n\\\n**The core insight:** Every subsequent analysis feature (corner detection, grip mapping, theoretical best lap, optimal racing line) depends on an accurate model of the track geometry. Without knowing the track's exact shape, width, and curvature, we cannot calculate optimal lines or detect where a driver deviates from the ideal.\\\n\\\n**Why automatic boundary estimation from normal laps is insufficient:**\\\n\\\nDrivers almost never use the absolute edge of the track. If we estimate boundaries from even 20 normal racing laps, the derived \\\"track\\\" will be 2–4 meters narrower than reality. For optimal line calculation, this is fatal — the optimal line EXPLOITS the full track width. A 2-meter error means the calculated optimal line will clip corners 1 meter early and leave 1 meter of unused exit road. That's the difference between a useful coaching tool and a novelty.\\\n\\\n**Deliberate boundary recording solves this:**\\\n\\\n| Aspect | Auto-Estimated Boundaries | Deliberate Boundary Recording |\\\n|---|---|---|\\\n| Track width accuracy | ±2–4m (too narrow) | ±0.5m (near-exact) |\\\n| Confidence in optimal line | Low — can't trust the line is actually possible | High — line stays within known boundaries |\\\n| Number of laps needed | 10–20+ normal laps | 2 dedicated slow laps |\\\n| Enables optimal line calc? | No — too narrow | Yes |\\\n| Effort | None (passive) | One 10-minute session per track |\\\n| Reusable? | No — re-estimate every time | Yes — persistent TrackModel keyed by (game, track) |\\\n\\\n**The track mapping ritual (user workflow):**\\\n\\\n1. Load track in the sim, select car\\\n2. Start a `track_mapping` session in racecraft\\\n3. **Run 1: Left boundary** — Drive a slow, careful lap hugging the left edge of the track. The system records `world_pos` at 60 Hz. Label: \\\"left_boundary\\\"\\\n4. **Run 2: Right boundary** — Same thing, hugging the right edge. Label: \\\"right_boundary\\\"\\\n5. Stop recording. System builds `TrackModel` automatically.\\\n6. TrackModel is persisted and keyed by `(game, track_name)`. All future sessions at this track automatically load this TrackModel.\\\n\\\n**Why this is a good first experience with the product:**\\\n- It's a deliberate, mindful exercise — the user is actively participating, not just passively recording\\\n- It builds investment (you mapped this track, now you want to use the analysis)\\\n- The resulting track map is immediately visual — satisfying feedback\\\n- It naturally introduces the concept of \\\"track width\\\" and \\\"racing line\\\" before we start coaching\\\n- Once mapped, the track model is a shareable asset (future community feature)\\\n\\\n---\\\n\\\n### 17.2 The Analysis Pipeline — From Raw Data to Coaching\\\n\\\nThe full pipeline from raw 60 Hz telemetry to coaching output:\\\n\\\n```\\\n                     ┌─────────────────────────┐\\\n                     │   60 Hz Telemetry Feed   │\\\n                     │  (world_pos, speed, Gs,  │\\\n                     │   slip, inputs, spline)  │\\\n                     └───────────┬─────────────┘\\\n                                 │\\\n                     ┌───────────▼─────────────┐\\\n                     │    1. LAP DETECTION      │\\\n                     │  Detect lap boundaries   │\\\n                     │  from spline_position    │\\\n                     │  crossing 0.0 → 1.0      │\\\n                     └───────────┬─────────────┘\\\n                                 │\\\n                     ┌───────────▼─────────────┐\\\n                     │  2. TRACK MAPPING        │\\\n                     │  (if not yet mapped)     │\\\n                     │  Build TrackModel from   │\\\n                     │  boundary laps:          │\\\n                     │  - Left/right edges      │\\\n                     │  - Center line           │\\\n                     │  - Width profile         │\\\n                     │  - Curvature κ(s)        │\\\n                     │  - Auto-detected corners │\\\n                     └───────────┬─────────────┘\\\n                                 │ (TrackModel persisted)\\\n                                 │\\\n                ┌────────────────┼────────────────┐\\\n                │                │                 │\\\n    ┌───────────▼──────┐  ┌─────▼──────────┐  ┌──▼───────────────────┐\\\n    │ 3. CORNER        │  │ 4. GRIP        │  │ 5. THEORETICAL       │\\\n    │    ANALYSIS      │  │    ENVELOPE    │  │    BEST LAP          │\\\n    │ Per-corner:      │  │ From all laps: │  │ Stitch best sectors  │\\\n    │ - Entry/mid/exit │  │ - Max lat G    │  │ across multiple laps │\\\n    │ - Speed trace    │  │ - Max accel G  │  │ into one ideal lap   │\\\n    │ - G-forces       │  │ - Max brake G  │  │                      │\\\n    │ - Slip angles    │  │ - Grip circle  │  │ → Optimal speed      │\\\n    │ - Input profile  │  │   boundary     │  │   trace              │\\\n    └───────┬──────────┘  └───────┬────────┘  └──────────┬───────────┘\\\n            │                     │                       │\\\n            └─────────────┬───────┘───────────────────────┘\\\n                          │\\\n              ┌───────────▼─────────────────┐\\\n              │  6. TIME LOSS ATTRIBUTION    │\\\n              │  Per corner per lap:         │\\\n              │  - Delta vs. theoretical best│\\\n              │  - Root cause analysis       │\\\n              │  - Where in corner (entry/   │\\\n              │    mid/exit) time was lost   │\\\n              │  - Why (slip, inputs, speed) │\\\n              └───────────┬─────────────────┘\\\n                          │\\\n              ┌───────────▼─────────────────┐\\\n              │  7. COACHING OUTPUT          │\\\n              │  \\\"Turn 3: -0.4s              │\\\n              │   Braked 12m too early       │\\\n              │   Car can do 1.4g,           │\\\n              │   you used only 1.1g         │\\\n              │   → Brake 12m later,         │\\\n              │     carry 7 km/h more speed\\\" │\\\n              └─────────────────────────────┘\\\n```\\\n\\\n---\\\n\\\n### 17.3 Step 1: Lap Detection\\\n\\\n**Data source:** `spline_position` (0.0–1.0) from the Telemetry Tool feed. This field represents the car's position along the track's spline (normalized track progress). A lap crossing occurs when the value wraps from ~1.0 back to ~0.0.\\\n\\\n**Algorithm:**\\\n\\\n```rust\\\nfn detect_laps(frames: &[TelemetryFrame]) -> Vec<Lap> {\\\n    let mut laps = Vec::new();\\\n    let mut current_lap_start = 0;\\\n    let mut last_spline = frames[0].spline_position;\\\n\\\n    for (i, frame) in frames.iter().enumerate().skip(1) {\\\n        let spline = frame.spline_position;\\\n\\\n        // Lap crossing: spline jumps backward (1.0 → 0.0)\\\n        if spline < last_spline - 0.5 {\\\n            // Transition: frames[current_lap_start..i] form one lap\\\n            laps.push(Lap {\\\n                start_frame: current_lap_start,\\\n                end_frame: i,\\\n                lap_time: frame.timestamp - frames[current_lap_start].timestamp,\\\n                frames: &frames[current_lap_start..i],\\\n            });\\\n            current_lap_start = i;\\\n        }\\\n        last_spline = spline;\\\n    }\\\n\\\n    laps\\\n}\\\n```\\\n\\\n**Edge cases to handle:**\\\n- Invalid lap detection (off-track, cutting) → flag `is_valid` based on spline monotonicity check\\\n- First partial lap (crossing start before first full lap) → mark as \\\"out lap\\\"\\\n- Pit lane entry/exit → spline may jump; filter by `in_pit` / `in_pitlane` flags\\\n- Slow-speed crossings (creeping over start/finish) → minimum speed threshold\\\n\\\n**New data structures:**\\\n\\\n```rust\\\nstruct Lap {\\\n    start_frame: usize,\\\n    end_frame: usize,\\\n    lap_time_ms: u64,\\\n    is_valid: bool,         // no off-track, no cutting, no pit\\\n    is_out_lap: bool,       // first crossing after leaving pits\\\n    is_in_lap: bool,        // lap before pit entry\\\n}\\\n```\\\n\\\n**Effort:** 1–2 days. This is foundational — everything depends on it.\\\n\\\n---\\\n\\\n### 17.4 Step 2: Track Mapping — Building the TrackModel\\\n\\\n**New use case:** `track_mapping`\\\n\\\nThis is a dedicated session type. The user deliberately drives boundary laps. The system builds a persistent `TrackModel` from these laps.\\\n\\\n**New data structures:**\\\n\\\n```rust\\\n/// Persistent track model, keyed by (game, track_name).\\\n/// Stored as JSON in data/tracks/<game>/<track_name>.json\\\nstruct TrackModel {\\\n    game: String,                      // e.g. \\\"assetto_corsa\\\"\\\n    track_name: String,                // e.g. \\\"vallelunga\\\"\\\n    created_at: u64,                   // timestamp\\\n    resolution: usize,                 // number of spline sample points (e.g. 1000)\\\n\\\n    // Per-sample-point arrays, indexed by spline position\\\n    center_line: Vec<[f32; 3]>,        // [x, y, z] at each spline point\\\n    left_boundary: Vec<[f32; 3]>,      // left edge position\\\n    right_boundary: Vec<[f32; 3]>,     // right edge position\\\n    track_width: Vec<f32>,             // distance left→right at each point (meters)\\\n    heading: Vec<f32>,                 // track direction angle at each point (radians)\\\n    curvature: Vec<f32>,               // κ = dθ/ds at each point (1/meters)\\\n\\\n    // Auto-detected from curvature\\\n    corners: Vec<Corner>,\\\n    sectors: Vec<Sector>,\\\n\\\n    // Metadata\\\n    total_length_meters: f32,          // track length\\\n    sample_spacing_meters: f32,        // meters between spline samples\\\n}\\\n\\\nstruct Corner {\\\n    id: usize,\\\n    entry_spline: f32,                 // where curvature starts rising\\\n    apex_spline: f32,                  // peak curvature point\\\n    exit_spline: f32,                  // where curvature returns to ~0\\\n    radius_meters: f32,               // effective corner radius\\\n    direction: TurnDirection,          // Left or Right\\\n    sector_id: usize,                  // which sector this corner belongs to\\\n}\\\n\\\nenum TurnDirection {\\\n    Left,\\\n    Right,\\\n}\\\n\\\nstruct Sector {\\\n    id: usize,\\\n    start_spline: f32,\\\n    end_spline: f32,\\\n    sector_type: SectorType,\\\n}\\\n\\\nenum SectorType {\\\n    Straight,\\\n    Corner(usize),     // references Corner id\\\n    Complex,           // multiple corners close together (chicane, esses)\\\n}\\\n```\\\n\\\n**Track building algorithm:**\\\n\\\n```\\\n1. RESAMPLE boundary laps to uniform spline positions\\\n   - Left boundary lap: 60 Hz samples with (world_pos, spline_pos)\\\n   - Right boundary lap: same\\\n   - Interpolate both onto a uniform grid of 1000 spline positions (0.000, 0.001, ..., 0.999)\\\n\\\n2. BUILD center line\\\n   - center[i] = midpoint(left[i], right[i])\\\n   - This is the geometric center of the track, NOT the racing line\\\n\\\n3. CALCULATE track width at each point\\\n   - width[i] = distance(left[i], right[i])\\\n\\\n4. CALCULATE heading at each point\\\n   - θ[i] = atan2(center[i+1].y - center[i].y, center[i+1].x - center[i].x)\\\n\\\n5. CALCULATE curvature at each point\\\n   - dθ[i] = angle_difference(θ[i+1], θ[i])\\\n   - ds[i] = distance(center[i], center[i+1])\\\n   - κ[i] = dθ[i] / ds[i]\\\n   - Smooth with moving average (window = ~20m of track)\\\n\\\n6. DETECT corners from curvature\\\n   - Threshold: |κ| > corner_threshold (auto-calibrate: use median(|κ|) * 3 as threshold)\\\n   - Merge corners closer than 15m apart\\\n   - For each corner group: entry = first sample above threshold, apex = max(|κ|), exit = last sample above threshold\\\n   - Corner radius R = 1 / |κ_apex|\\\n   - Direction: positive κ = left turn, negative κ = right turn\\\n\\\n7. COMPUTE sectors\\\n   - Split track into sectors at corner entry/exit points\\\n   - Label as Straight, Corner(id), or Complex\\\n\\\n8. PERSIST to data/tracks/<game>/<track_name>.json\\\n```\\\n\\\n**API additions:**\\\n\\\n| Endpoint | Method | Description |\\\n|---|---|---|\\\n| `GET /api/tracks` | GET | List all mapped tracks |\\\n| `GET /api/tracks/{game}/{track_name}` | GET | Get TrackModel |\\\n| `POST /api/tracks/build` | POST | Build TrackModel from boundary runs (JSON: recording_id, left_run_id, right_run_id) |\\\n| `DELETE /api/tracks/{game}/{track_name}` | DELETE | Delete a track model |\\\n\\\n**New module:** `src/track_model.rs` (~300 lines) — TrackModel builder, persistence, corner detection, curvature calculation.\\\n\\\n**Effort:** 3–5 days. This is the most important single piece of work — every downstream feature depends on it.\\\n\\\n---\\\n\\\n### 17.5 Step 3: Corner Analysis\\\n\\\nOnce we have laps and a TrackModel with auto-detected corners, we can analyze each corner in each lap.\\\n\\\n**New data structures:**\\\n\\\n```rust\\\nstruct CornerAnalysis {\\\n    corner_id: usize,\\\n    lap_number: usize,\\\n\\\n    // Speed profile\\\n    entry_speed_kmh: f32,\\\n    apex_speed_kmh: f32,\\\n    exit_speed_kmh: f32,\\\n    min_speed_kmh: f32,\\\n    speed_delta_kmh: f32,              // entry - min (how much speed was scrubbed)\\\n\\\n    // G-forces\\\n    peak_lateral_g: f32,\\\n    avg_lateral_g: f32,\\\n    peak_longitudinal_g_entry: f32,    // braking G at entry\\\n    peak_longitudinal_g_exit: f32,     // acceleration G at exit\\\n\\\n    // Tyre behavior\\\n    peak_front_slip_angle: f32,        // max front slip angle\\\n    peak_rear_slip_angle: f32,         // max rear slip angle\\\n    understeer_detected: bool,         // front slip >> rear slip during corner\\\n    oversteer_detected: bool,          // rear slip >> front slip during corner\\\n    peak_nd_slip: f32,                 // max normalized slip across all 4 wheels\\\n\\\n    // Driver inputs\\\n    brake_at_entry: bool,              // was brake applied at corner entry?\\\n    trail_braking_detected: bool,      // brake + steer overlap > 100ms\\\n    throttle_application_spline: f32,   // where throttle first exceeds 10% after braking\\\n    steering_corrections: u32,         // count of direction reversals in steering\\\n\\\n    // Timing\\\n    time_in_corner_ms: u64,            // entry → exit duration\\\n    time_loss_vs_best_ms: i64,         // positive = slower than best lap's same corner\\\n\\\n    // Grip utilization\\\n    grip_utilization_pct: f32,         // peak_lat_g / max_lat_g_from_envelope × 100\\\n}\\\n```\\\n\\\n**Key derived metrics:**\\\n\\\n| Metric | How to Calculate | Coaching Insight |\\\n|---|---|---|\\\n| **Trail braking detection** | Brake > 5% AND steer > 5% for > 100ms after corner entry | Advanced technique — indicates driver is rotating the car on entry |\\\n| **Understeer detection** | Front slip angle > rear slip angle by > threshold during mid-corner | Car is pushing — driver turning but car isn't turning |\\\n| **Oversteer detection** | Rear slip angle > front slip angle by > threshold | Car is loose — driver is catching slides |\\\n| **Grip utilization** | `peak_lateral_g / grip_envelope.max_lat_g(speed) × 100` | How close to the limit. <70% = lots of time on the table |\\\n| **Throttle application point** | First frame where throttle > 10% after last brake release | Early throttle = good exit, late throttle = cautious or poor line |\\\n| **Steering corrections** | Count zero-crossings in steering angle derivative | Smooth = 1 clean input, corrections = fighting the car or misjudged entry |\\\n\\\n**New module:** `src/corner_analysis.rs` (~400 lines) — CornerAnalyzer that takes laps + TrackModel and produces `Vec<CornerAnalysis>`.\\\n\\\n**Effort:** 3–4 days.\\\n\\\n---\\\n\\\n### 17.6 Step 4: Grip Envelope — The Car Performance Model\\\n\\\nFrom multiple laps of data, we can build a model of what this car is CAPABLE of. This is the \\\"grip circle\\\" — the boundary of maximum force the tyres can generate.\\\n\\\n**New data structures:**\\\n\\\n```rust\\\n/// Car performance envelope, keyed by (game, track, car, setup_hash).\\\n/// Built from multiple laps of telemetry.\\\nstruct GripEnvelope {\\\n    game: String,\\\n    track: String,\\\n    car: String,\\\n\\\n    // Maximum lateral acceleration at each speed range\\\n    // Sorted by speed, gives us the cornering limit\\\n    max_lateral_g_by_speed: Vec<SpeedGPair>,   // [(speed_kmh, max_lat_g), ...]\\\n\\\n    // Maximum longitudinal acceleration (throttle) at each speed\\\n    max_accel_g_by_speed: Vec<SpeedGPair>,\\\n\\\n    // Maximum braking deceleration at each speed\\\n    max_brake_g_by_speed: Vec<SpeedGPair>,\\\n\\\n    // The grip circle boundary: combined lateral + longitudinal\\\n    // Points on the edge of the (lat_g, lon_g) plot\\\n    grip_circle_boundary: Vec<(f32, f32)>,     // [(lat_g, lon_g), ...]\\\n\\\n    // Derived constants\\\n    estimated_mu: f32,                // estimated coefficient of friction\\\n    peak_lateral_g: f32,              // overall maximum lateral G\\\n    peak_brake_g: f32,                // overall maximum braking G\\\n}\\\n\\\nstruct SpeedGPair {\\\n    speed_kmh: f32,\\\n    max_g: f32,\\\n}\\\n```\\\n\\\n**Building the grip envelope:**\\\n\\\n```\\\n1. Collect ALL telemetry frames across ALL laps in a session\\\n2. BIN by speed (e.g., 10 km/h bins: 0-10, 10-20, ..., 250-260)\\\n3. For each bin:\\\n   - max_lat_g = max(|acc_lateral|) across all frames in bin\\\n   - max_accel_g = max(acc_frontal) where throttle > 80%\\\n   - max_brake_g = max(|acc_frontal|) where brake > 80%\\\n4. For grip circle:\\\n   - Plot all (|acc_lateral|, acc_frontal) points\\\n   - Compute convex hull → this IS the grip circle\\\n   - The inside = within grip limits, the outside = sliding\\\n5. Estimate μ from peak lateral G: μ ≈ peak_lat_g / 9.81\\\n```\\\n\\\n**Why this matters for coaching:**\\\n\\\nThe grip envelope tells us the car's absolute performance limit. When we see a driver at 1.1g lateral in a corner where the car can do 1.4g, we know they're only using 78% of the available grip. That's a quantifiable coaching opportunity.\\\n\\\nThe grip envelope is also car-specific and setup-specific. Different cars have different envelopes. Different setups (tyre pressures, aero, suspension) change the envelope. This is why professional teams spend so much time mapping grip envelopes — it's the fundamental constraint that everything else is optimized against.\\\n\\\n**Effort:** 2–3 days for the builder module. The data is already there in the telemetry frames.\\\n\\\n---\\\n\\\n### 17.7 Step 5: Theoretical Best Lap — Sector Stitching\\\n\\\nThis is the approach that delivers the biggest coaching value for the least implementation effort. No physics model needed.\\\n\\\n**Algorithm:**\\\n\\\n```\\\n1. Load TrackModel for this (game, track)\\\n2. Load all valid laps from the session (e.g., 10 laps)\\\n3. Segment each lap into sectors using TrackModel.corners\\\n   - Each sector = corner_entry to next corner_entry\\\n   - Or use traditional S1/S2/S3 if the game provides sector times\\\n4. For each sector:\\\n   - Find the fastest traversal across ALL laps\\\n   - Record which lap it came from\\\n5. Stitch: theoretical_best_time = sum(fastest_sector_times)\\\n6. Build speed trace: for each sector, use the speed data from the lap that was fastest in that sector\\\n7. Build position trace: same, for track map visualization\\\n```\\\n\\\n**New data structures:**\\\n\\\n```rust\\\nstruct TheoreticalBestLap {\\\n    track: String,\\\n    total_time_ms: u64,\\\n    sectors: Vec<BestSector>,\\\n    speed_trace: Vec<(f32, f32)>,        // (spline_position, speed_kmh)\\\n    position_trace: Vec<[f32; 3]>,       // world_pos at each spline point\\\n}\\\n\\\nstruct BestSector {\\\n    sector_id: usize,\\\n    best_time_ms: u64,\\\n    source_lap_number: usize,            // which actual lap this came from\\\n    entry_spline: f32,\\\n    exit_spline: f32,\\\n}\\\n```\\\n\\\n**Why this works so well:**\\\n- It's grounded in REALITY — the car actually achieved each sector time\\\n- It shows the driver: \\\"Your best T1 was Lap 5, your best T2 was Lap 12 — put them together and you're 0.8s faster\\\"\\\n- It naturally identifies which corners lose the most time across laps\\\n- It doesn't require a physics model, tyre model, or aerodynamic data\\\n\\\n**Effort:** 2–3 days.\\\n\\\n---\\\n\\\n### 17.8 Step 6: Time Loss Attribution — The Coaching Engine\\\n\\\nThis is where everything comes together. For each corner in each lap, we compare against the theoretical best and explain WHY time was lost.\\\n\\\n**Algorithm:**\\\n\\\n```\\\nFor each lap L:\\\n  For each corner C in TrackModel:\\\n    actual_time = time from C.entry_spline to C.exit_spline in lap L\\\n    best_time = time for same corner from TheoreticalBestLap\\\n    time_loss = actual_time - best_time\\\n\\\n    If time_loss > threshold (e.g., 50ms):\\\n      Determine WHERE in the corner time was lost:\\\n        entry_phase = C.entry_spline to C.apex_spline\\\n        exit_phase = C.apex_spline to C.exit_spline\\\n\\\n        entry_time_loss = time_lost_in(entry_phase) vs. best\\\n        exit_time_loss = time_lost_in(exit_phase) vs. best\\\n\\\n      Determine WHY:\\\n\\\n      If entry_time_loss > exit_time_loss:\\\n        → Problem is at ENTRY\\\n        Check:\\\n        - Was entry_speed significantly lower than best?\\\n          → \\\"Braked too early\\\" (most common amateur mistake)\\\n        - Was entry_speed significantly HIGHER than best?\\\n          → \\\"Braked too late, had to correct mid-corner\\\"\\\n        - Was peak brake G lower than grip envelope allows?\\\n          → \\\"Not braking hard enough — you can brake harder\\\"\\\n        - Was trail braking not detected when best lap had it?\\\n          → \\\"Try trail braking to rotate the car on entry\\\"\\\n\\\n      If exit_time_loss > entry_time_loss:\\\n        → Problem is at EXIT\\\n        Check:\\\n        - Was exit_speed significantly lower than best?\\\n          → \\\"Not getting on throttle early enough\\\"\\\n        - Was throttle_application_spline later than best?\\\n          → \\\"Applying throttle X meters later than optimal\\\"\\\n        - Was grip_utilization low (<75%)?\\\n          → \\\"Only using X% of available grip — the car can take more speed\\\"\\\n        - Was understeer detected?\\\n          → \\\"Car is understeering — consider adjusting line or setup\\\"\\\n\\\n      Mid-corner check:\\\n        - Were steering_corrections > 2?\\\n          → \\\"Steering is inconsistent — try a smoother, single input\\\"\\\n        - Was there a mid-corner throttle lift?\\\n          → \\\"Confidence lift detected — the car can carry more speed here\\\"\\\n```\\\n\\\n**Coaching output format:**\\\n\\\n```json\\\n{\\\n  \\\"corner_id\\\": 3,\\\n  \\\"corner_label\\\": \\\"Turn 3 (Right Hairpin)\\\",\\\n  \\\"time_loss_ms\\\": 412,\\\n  \\\"phase\\\": \\\"entry\\\",\\\n  \\\"severity\\\": \\\"high\\\",\\\n  \\\"findings\\\": [\\\n    {\\\n      \\\"type\\\": \\\"early_braking\\\",\\\n      \\\"message\\\": \\\"Braked 15m too early\\\",\\\n      \\\"detail\\\": \\\"Entry speed was 89 km/h vs. optimal 101 km/h\\\",\\\n      \\\"data\\\": { \\\"actual_entry_speed\\\": 89, \\\"optimal_entry_speed\\\": 101 }\\\n    },\\\n    {\\\n      \\\"type\\\": \\\"low_grip_utilization\\\",\\\n      \\\"message\\\": \\\"Only using 71% of available grip\\\",\\\n      \\\"detail\\\": \\\"Peak lateral G: 1.05g, car can do 1.48g at this speed\\\",\\\n      \\\"data\\\": { \\\"actual_peak_g\\\": 1.05, \\\"max_g\\\": 1.48, \\\"utilization_pct\\\": 71 }\\\n    }\\\n  ],\\\n  \\\"recommendation\\\": \\\"Brake 15m later, carry 12 km/h more speed into the corner. The car has 30% more grip available — trust it.\\\"\\\n}\\\n```\\\n\\\n**Effort:** 4–5 days for the core engine. Iterative refinement ongoing.\\\n\\\n---\\\n\\\n### 17.9 Step 7 (Future): Physics-Based Optimal Racing Line\\\n\\\nThis is the \\\"holy grail\\\" — calculating the mathematically optimal path around the track, not just stitching best sectors. Requires the GripEnvelope and TrackModel as prerequisites.\\\n\\\n**The theory:**\\\n\\\nThe optimal racing line through a corner maximizes the effective radius, which allows the highest cornering speed:\\\n\\\n```\\\nFor a simple corner:\\\n  Track width = W (from TrackModel)\\\n  Corner geometric radius = R (from TrackModel.curvature)\\\n  Optimal line radius = R + W/2 (out-in-out uses full track width)\\\n  Maximum cornering speed = sqrt(μ × g × R_effective)\\\n```\\\n\\\nFor complex corners (chicanes, esses, decreasing-radius), it's an optimization problem:\\\n\\\n```\\\nMinimize: total lap time\\\nSubject to:\\\n  - Path stays within track boundaries (from TrackModel)\\\n  - Lateral force stays within grip circle (from GripEnvelope)\\\n  - Longitudinal force stays within grip circle\\\n  - Speed = integral of acceleration\\\n  - Position = integral of velocity × heading\\\n```\\\n\\\n**Simplified practical approach (good enough for coaching):**\\\n\\\nInstead of solving the full optimal control problem, use a geometric method:\\\n\\\n```\\\n1. For each corner, calculate the widest possible arc using full track width:\\\n   - Entry: approach from outside edge\\\n   - Apex: clip inside edge\\\n   - Exit: track out to outside edge\\\n   - This gives the maximum-radius path through the corner\\\n\\\n2. Calculate maximum speed at each point on this path:\\\n   - At apex: v_max = sqrt(μ × g × R_effective)\\\n   - On entry: calculate braking curve from approach speed to apex speed\\\n   - On exit: calculate acceleration curve from apex speed to next straight's speed\\\n\\\n3. Combine with straight-line performance:\\\n   - Full throttle acceleration curve from GripEnvelope\\\n   - Maximum braking curve from GripEnvelope\\\n\\\n4. The result: a speed-at-every-spline-point profile\\\n   → This IS the optimal lap, expressed as the fastest possible speed trace\\\n```\\\n\\\n**Why this is a future step (not immediate):**\\\n- Requires well-calibrated GripEnvelope (needs many laps to build accurately)\\\n- Assumes the tyre model is constant (ignores tyre wear, temperature effects)\\\n- The geometric approach works for simple corners but needs iterative optimization for complexes\\\n- The theoretical best lap (sector stitching) provides 80% of the coaching value at 20% of the effort\\\n\\\n**Effort:** 2–4 weeks for a robust implementation. Can be deferred until the simpler coaching features are proven useful.\\\n\\\n---\\\n\\\n### 17.10 Implementation Order and Dependencies\\\n\\\n```mermaid\\\ngraph TD\\\n    A[Lap Detection] --> B[Track Mapping]\\\n    B --> C[Corner Detection<br/>from Curvature]\\\n    C --> D[Corner Analysis<br/>per-lap per-corner]\\\n    C --> E[Grip Envelope<br/>from multiple laps]\\\n    D --> F[Theoretical Best Lap<br/>sector stitching]\\\n    E --> F\\\n    F --> G[Time Loss Attribution<br/>coaching engine]\\\n    D --> G\\\n    E --> H[Optimal Racing Line<br/>physics-based<br/>FUTURE]\\\n    B --> H\\\n```\\\n\\\n**Recommended build order:**\\\n\\\n| Order | Module | Depends On | Effort | Value |\\\n|---|---|---|---|---|\\\n| **1** | Lap Detection | Spline data (already captured) | 1–2 days | Foundational |\\\n| **2** | Track Mapping + Boundary Recording | Lap Detection | 3–5 days | Foundational — enables everything |\\\n| **3** | Corner Detection (from curvature) | TrackModel | 2–3 days | Enables corner analysis |\\\n| **4** | Corner Analysis (per-corner metrics) | Laps + Corners | 3–4 days | Immediate coaching value |\\\n| **5** | Grip Envelope Builder | Multiple laps of data | 2–3 days | Enables optimal line, grip utilization % |\\\n| **6** | Theoretical Best Lap | Laps + Corners + Grip Envelope | 2–3 days | The \\\"ah-ha\\\" feature |\\\n| **7** | Time Loss Attribution | All of the above | 4–5 days | The actual coaching output |\\\n| **8** | Optimal Racing Line (future) | Grip Envelope + TrackModel | 2–4 weeks | Physics-perfect line |\\\n\\\n**Total effort for steps 1–7:** ~18–25 days of focused implementation.\\\n\\\n---\\\n\\\n### 17.11 What We Need From the Next Live Session\\\n\\\nTo start building these analysis features, we need specific data from the next AC session. Here's the session plan:\\\n\\\n**Session Goal: Track Mapping + Initial Laps at Vallelunga**\\\n\\\n| Run | Description | Duration | Purpose |\\\n|---|---|---|---|\\\n| 1 | Left boundary lap — slow, hugging left edge | ~2 min | TrackModel left boundary |\\\n| 2 | Right boundary lap — slow, hugging right edge | ~2 min | TrackModel right boundary |\\\n| 3–5 | 3 normal flying laps (Abarth 500, Vallelunga) | ~3 min each | Initial data for grip envelope, corner analysis, theoretical best |\\\n| 6 | Optional: more flying laps | ~3 min each | More data = better theoretical best |\\\n\\\n**What to verify during this session:**\\\n1. `spline_position` actually crosses 0.0→1.0 correctly for lap detection\\\n2. `world_pos` gives usable X/Y coordinates (check for NaN or zero values)\\\n3. `acc_lateral`, `acc_frontal` give plausible G-force values (compare to expected ~1.0–1.5g for Abarth)\\\n4. `tyre_slip_angle` and `nd_slip` show variation during cornering (not always zero)\\\n5. Speed values match expected range (0–200 km/h for Abarth at Vallelunga)\\\n\\\n**If the data checks out, we have everything needed to build steps 1–7.**\\\n\\\n---\\\n\\\n*Last updated: 2026-06-06 — Added §17: Analysis Use Cases (track mapping with deliberate boundary recording, lap detection, corner analysis, grip envelope, theoretical best lap, time loss attribution, optimal racing line, implementation order, next session plan)*\\\n*Next: implement §1.9 (feed merging, run deletion, session reopen), then §17.3 Lap Detection, then §17.4 Track Mapping, then live verification session at Vallelunga\"],[1,\"Industry standard for real motorsport. Sim racers use it via exported data. |\\\n| **ATLAS (McLaren Applied)** | F1-grade telemetry system | Enterprise / F1-only | Multi-million dollar per season. |\\\n| **Cosworth Toolbox** | Real racing data analysis | License-based | WEC, IndyCar, Touring Cars |\\\n\\\n#### Tier 3: Community & Content Platforms\\\n\\\n| Product | Role | Rally Coverage | Notes |\\\n|---|---|---|---|\\\n| **OverTake.gg** (formerly RaceDepartment) | Sim racing community hub | Has WRC, AC Rally categories; partnered with Track Titan | The Track Titan × OverTake collaboration is the distribution model to study |\\\n\\\n---\\\n\\\n### 16.3 The Track Titan × OverTake Model\\\n\\\nTrack Titan's collaboration with OverTake.gg (2M+ registered users) is the case study for how to build a product in this space:\\\n\\\n1. **Track Titan** builds the telemetry + coaching technology (SaaS product)\\\n2. **OverTake.gg** provides the community, content, and distribution channel\\\n3. OverTake integrates Track Titan as a \\\"Community Benefit\\\"\\\n4. Both parties monetize: Track Titan through subscriptions, OverTake through premium memberships\\\n\\\n**Key lesson:** Distribution and community matter as much as technology. The sim racing market is fragmented across many games — a platform approach works better than a single-game tool. Freemium model lowers barrier to entry.\\\n\\\n---\\\n\\\n### 16.4 Rally Telemetry — The Underserved Market\\\n\\\n**No competitor serves rally telemetry.** This is a genuine differentiator.\\\n\\\n| Aspect | Circuit Racing | Rally |\\\n|---|---|---|\\\n| Track | Static, memorizable | Dynamic, pacenote-dependent |\\\n| Surface | Uniform | Mixed (gravel, tarmac, snow, ice, mud) |\\\n| Analysis unit | Lap time | Stage time |\\\n| Key metric | Consistency across laps | Commitment to pacenotes, surface adaptation |\\\n| Coaching focus | Braking points, racing line | Pacenote accuracy, weight transfer on loose surfaces |\\\n\\\n**AC Rally** (UE5, Early Access) is the key opportunity. If KUNOS ports their telemetry infrastructure, we get rally-specific data with circuit-quality depth. No other product offers both.\\\n\\\nSee [AC Rally — Telemetry Status & Research](joplin://b7b331aa87544b6ebe5db5b8d7bcd2a0) for full investigation plan.\\\n\\\n---\\\n\\\n### 16.5 Real-World Racing Telemetry\\\n\\\nReal racing teams already have expensive, purpose-built systems (MoTeC, ATLAS). The market gap is democratizing professional-grade analysis for:\\\n1. **Sim racers** wanting to improve (Track Titan's 285K users prove this market)\\\n2. **Club/amateur real racers** who can't afford MoTeC-level systems\\\n3. **Rally drivers at national level** who have NO accessible telemetry platform\\\n4. **Sim-to-real pipeline** — consistent analysis across both\\\n\\\n---\\\n\\\n### 16.6 Product Roadmap — From v0.6.0 to Sellable Product\\\n\\\n#### Phase A: Complete the Core (Months 1–3)\\\n\\\n| Milestone | Tasks | Success Metric |\\\n|---|---|---|\\\n| **A1: Verify with live sessions** | Test KSUDP + PCARS with real game sessions | All 3 feeds working reliably |\\\n| **A2: ~~§1.9~~ ✅ DONE** | Feed merging, run deletion, session reopen | Shipped in v0.6.0 / v0.1.3 |\\\n| **A3: WebSocket streaming** | Replace REST polling with real-time WS | <50ms latency game → browser |\\\n| **A4: Lap detection** | Auto-detect laps from spline position crossing | Automatic lap segmentation |\\\n| **A5: Reference lap overlay** | Load reference lap, overlay current against it | Visual overlay with delta trace |\\\n| **A6: Tyre analysis** | Tyre temperature heat maps, wear projection | Degradation curve graphs |\\\n| **A7: Brake analysis** | Brake pressure traces, consistency scoring | Per-corner braking analysis |\\\n\\\n#### Phase B: Multi-Game & Rally Support (Months 4–6)\\\n\\\n| Milestone | Tasks | Success Metric |\\\n|---|---|---|\\\n| **B1: ACC support** | ACC UDP parser (registration + broadcast) | ACC sessions captured and analyzed |\\\n| **B2: iRacing support** | YAML file or memory-mapped file telemetry | iRacing sessions captured |\\\n| **B3: Rally game support** | AC Rally, Dirt Rally 2.0, EA WRC | Rally stages captured |\\\n| **B4: Rally-specific analysis** | Stage-based analysis, surface detection, pacenote timing | Unique rally coaching insights |\\\n| **B5: F1 game support** | F1 2025/26 UDP telemetry | F1 sessions — largest casual audience |\\\n\\\n#### Phase C: AI Coaching & Automation (Months 7–10)\\\n\\\n| Milestone | Tasks |\\\n|---|---|\\\n| **C1: Anomaly detection** | ML model to detect unusual inputs |\\\n| **C2: Coaching Flows** | Step-by-step guided analysis (\\\"Here's your biggest time loss\\\") |\\\n| **C3: Setup recommendations** | Correlate telemetry with setup changes |\\\n| **C4: LLM coaching chat** | Natural language questions about telemetry |\\\n| **C5: Rally pacenote analysis** | Correlate pacenotes with driver inputs |\\\n\\\n#### Phase D: Platform & Monetization (Months 11–18)\\\n\\\n| Milestone | Tasks |\\\n|---|---|\\\n| **D1: User accounts & cloud sync** | Auth, cloud storage, cross-device access |\\\n| **D2: Community features** | Leaderboards, lap sharing, setup sharing |\\\n| **D3: Freemium model** | Free basic + Pro tier |\\\n| **D4: Partnership** | OverTake-style distribution partnership |\\\n| **D5: Mobile companion** | Post-session review, coaching alerts |\\\n| **D6: Real-world telemetry** | OBD-II / CAN bus bridge for sim-to-real |\\\n\\\n---\\\n\\\n### 16.7 Revenue Model Options\\\n\\\n| Model | Pricing | Feasibility |\\\n|---|---|---|\\\n| **SaaS Subscription** (Track Titan model) | Free basic + £5–10/mo Pro + £15/mo Teams | High — proven model |\\\n| **One-time License** (MoTeC model) | $99–299 perpetual | Medium |\\\n| **Self-hosted** | £50–100/mo Docker image | Medium — esports teams, academies |\\\n\\\n**Recommended:** Start with SaaS Freemium, evolve toward real racing telemetry as premium tier.\\\n\\\n---\\\n\\\n### 16.8 Unique Differentiators\\\n\\\n1. **Circuit + Rally in one platform** — Nobody does this\\\n2. **Open-source core** — Builds trust and community\\\n3. **Rust performance** — 60 Hz with <50ms latency. Most competitors use Python/Electron\\\n4. **Self-hostable** — Privacy-conscious users, esports teams\\\n5. **Sim-to-real bridge** — Same tools for sim AND real track days\\\n6. **Local LLM coaching** — Privacy-preserving AI that runs locally\\\n\\\n---\\\n\\\n### 16.9 Key Risks & Mitigation\\\n\\\n| Risk | Probability | Impact | Mitigation |\\\n|---|---|---|---|\\\n| Track Titan expands to rally | Medium | High | Move fast on rally support |\\\n| Game devs restrict telemetry | Low | Critical | Support many games |\\\n| AI coaching needs massive data | High | Medium | Start with rule-based coaching |\\\n| Real racing needs hardware | High | High | Defer, validate with sim first |\\\n| User acquisition cost too high | Medium | High | Partner with community platforms |\\\n\\\n---\\\n\\\n### 16.10 Recommended First Steps (Next 30 Days)\\\n\\\n1. ~~Ship §1.9~~ ✅ DONE (v0.6.0 / v0.1.3)\\\n2. **Verify with live AC session** — prove the whole stack works end-to-end\\\n3. **Add lap detection** — auto-segment laps from spline data\\\n4. **Build reference lap overlay** — the \\\"Track Titan killer\\\" feature\\\n5. **Research AC Rally telemetry output** — determine if existing parsers work\\\n6. **Draft rally coaching model** — coaching for a stage vs. a lap\\\n\\\n---\\\n\\\n## 17. Analysis Use Cases — Track Mapping, Corner Analysis & Ideal Lap\\\n\\\n> **Analysis date: 2026-06-06**\\\n> **Goal: Define the next analysis use cases beyond shift points, with track mapping as the foundation for everything that follows.**\\\n\\\n---\\\n\\\n### 17.1 Why Track Mapping Must Come First — The Deliberate Boundary Recording Method\\\n\\\n**The core insight:** Every subsequent analysis feature (corner detection, grip mapping, theoretical best lap, optimal racing line) depends on an accurate model of the track geometry.\\\n\\\n**Deliberate boundary recording** (2 slow laps per track) gives ±0.5m accuracy vs. ±2–4m from auto-estimation from normal laps. The track model is persisted and keyed by `(game, track_name)`.\\\n\\\n**The track mapping workflow:**\\\n1. Load track, select car\\\n2. Start a `track_mapping` session\\\n3. **Run 1:** Left boundary (hug left edge)\\\n4. **Run 2:** Right boundary (hug right edge)\\\n5. System builds `TrackModel` automatically\\\n6. TrackModel persisted — all future sessions load it\\\n\\\n---\\\n\\\n### 17.2 The Analysis Pipeline\\\n\\\n```\\\n60 Hz Telemetry → 1. Lap Detection → 2. Track Mapping → \\\n  3. Corner Analysis | 4. Grip Envelope | 5. Theoretical Best Lap →\\\n  6. Time Loss Attribution → 7. Coaching Output\\\n```\\\n\\\n---\\\n\\\n### 17.3 Lap Detection\\\n\\\nData source: `spline_position` (0.0–1.0). Lap crossing = spline wraps from ~1.0 to ~0.0. Edge cases: invalid laps (off-track), out laps, pit lane, slow crossings.\\\n\\\nEstimated effort: 1–2 days. Foundational — everything depends on it.\\\n\\\n---\\\n\\\n### 17.4 Track Mapping — Building the TrackModel\\\n\\\nNew use case: `track_mapping`. Persistent `TrackModel` stored at `data/tracks/<game>/<track_name>.json`.\\\n\\\nKey data: center_line, left/right boundaries, track_width, heading, curvature κ(s), auto-detected corners and sectors.\\\n\\\nAPI additions: `GET /api/tracks`, `GET /api/tracks/{game}/{track_name}`, `POST /api/tracks/build`, `DELETE /api/tracks/{game}/{track_name}`.\\\n\\\n---\\\n\\\n### 17.5 Corner Analysis\\\n\\\nPer-corner breakdown: entry/mid/exit speed trace, G-forces, slip angles, input profile. Requires TrackModel for corner detection.\\\n\\\n---\\\n\\\n### 17.6 Grip Envelope\\\n\\\nFrom all laps: max lateral G, max accel G, max brake G, binned by speed. Produces the \\\"grip circle\\\" boundary. Used for coaching: \\\"car can do 1.4g, you used only 1.1g\\\".\\\n\\\n---\\\n\\\n### 17.7 Theoretical Best Lap\\\n\\\nStitch best sectors across multiple laps into one ideal lap. Produces optimal speed trace.\\\n\\\n---\\\n\\\n### 17.8 Time Loss Attribution\\\n\\\nPer corner per lap: delta vs. theoretical best, root cause (braking too early, not enough throttle, wrong line), where in corner time was lost.\\\n\\\n---\\\n\\\n### 17.9 Coaching Output\\\n\\\nFinal output: \\\"Turn 3: -0.4s. Braked 12m too early. Car can do 1.4g, you used only 1.1g. → Brake 12m later, carry 7 km/h more speed.\\\"\\\n\\\n---\\\n\\\n### 17.10 Implementation Priority\\\n\\\n| Use Case | Depends On | Estimated Effort | Priority |\\\n|----------|-----------|-----------------|----------|\\\n| Lap detection | Spline data in TT feed | 1–2 days | P0 — blocks everything |\\\n| Track mapping | Lap detection | 3–5 days | P0 — blocks corner/grip analysis |\\\n| Corner analysis | Track model | 3–5 days | P1 |\\\n| Grip envelope | Track model | 2–3 days | P1 |\\\n| Theoretical best lap | Lap detection + sectors | 2–3 days | P1 |\\\n| Time loss attribution | Corner + grip + theoretical | 3–5 days | P2 |\\\n| Coaching output | All of the above | 5–10 days | P2 |\\\n\\\n---\\\n\\\n*Last updated: 2026-06-06 — v0.6.0/v0.1.3: §1.9 run management complete; split API reference and client notes into separate Joplin notes*\\\n*Next: verify with live AC session, add lap detection, track mapping, reference lap overlay\"],[0,\"*\"]],\"start1\":12741,\"start2\":12741,\"length1\":43661,\"length2\":10582}]"
metadata_diff: {"new":{},"deleted":[]}
encryption_cipher_text: 
encryption_applied: 0
updated_time: 2026-06-06T08:24:10.667Z
created_time: 2026-06-06T08:24:10.667Z
type_: 13