- Add analyze_racing_line(): lap-by-lap path extraction with speed data,
downsampled to 400 pts/lap. Spline-sorted in spline mode for clean paths.
- Add complete_lap_frames() + split_by_lap() utilities: filters to laps
whose spline spans >= 0.9 of [0,1], discarding partial out/in laps.
- Fix complete_lap_frames logic: was checking if segment STARTS at
spline~0, but a full lap starting mid-track (joined before start/finish)
also qualifies. Now checks spline span coverage instead.
- WOT window trimming in analyze_shift_points(): trims to first/last
frame with throttle >= 0.9, filters rev-limiter plateau (acc_g < 0.01).
- Fix frame persistence race condition: persist_session now writes frames
synchronously instead of spawning a thread. Multiple concurrent calls
could race on the same temp file, with earlier calls (empty frames)
overwriting later calls with correct data.
- atomic_write uses UUID-based temp file names as defense-in-depth.
- PositionMode now derives Deserialize for RacingLineAnalysis.
- Empty game/track_name validation in build_track() endpoint.
- Wired RacingLine use case into analysis dispatch.
- Remove obsolete TrackMap use case variant (superseded by TrackMapping)
- Add session/run/analysis persistence: metadata to data/sessions/<id>.json,
frames to <id>.frames.json (split for lazy loading)
- Atomic writes (temp + rename), compact JSON, off-thread frame serialization
- load_all loads metadata only at startup; ensure_frames_loaded lazy-loads
frames before analysis
- Normalize Recording runs to Stopped on reload (stale ring-buffer markers)
- Cache car_name on UseCaseSession during run finalization
- Add characteristics.rs: aggregate shift-point data per car across sessions
- New API: GET /api/characteristics/cars, GET /api/characteristics/cars/{car}
- Add Deserialize to TelemetryFrame and FeedSource for session round-trip
Backend tasks A→B→C→F→E→D from the Track Map Implementation plan:
A. PCARS V1 position data: read world_position (3×i16) and current_lap_distance
from viewed participant entry, compute derived spline_position, add unit tests.
B. Dual position mode: auto-detect spline vs coordinate mode in track map analysis,
compute cumulative 2D distance as pseudo-spline for PCARS/future games.
C. Persistent TrackModel: Corner, Sector, TrackModel data structures with serde,
TrackModelStore with async CRUD at data/tracks/<game>/<track_name>.json.
F. Track model building algorithm: resample boundaries, compute center line,
track width, heading, curvature, auto-detect corners (κ > 0.005), 3 sectors,
coordinate normalization to [0,1]².
E. TrackMapping use case: new boundary recording workflow with step-by-step
guidance, session integration.
D. Track API endpoints: GET/DELETE /api/tracks/{game}/{track_name},
GET /api/tracks, GET .../corners, POST /api/tracks/build.
- DELETE /api/sessions/{id}/runs/{run_id} removes stopped runs
- POST /api/sessions/{id}/reopen transitions Completed → Active
- Optional merge_feeds field on POST /api/sessions/{id}/runs combines
frames from multiple feeds with priority-based deduplication
- In-place merge_frames() avoids 2× peak memory
- All new fields use #[serde(default)] for backward compatibility
- Updated README.md with new endpoints and feed merging docs
Bug Fixes:
- Fixed KSUDP binary parser offsets from packed (323B) to natural C
alignment (328B) — 3 bytes padding after char identifier, 2 bytes
after 6 bools
- Fixed setup_terminal() leaving terminal in raw mode on early exit
New Features:
- Thread-safe warning buffer (warnings.rs) with TUI bar + stderr fallback
- Rewrote shift point analysis per AC forum methodology: per-gear
acceleration curves, crossover detection, same-gear merging
- UseCase::guidance() — step-by-step recording instructions
- Recording metadata enrichment in analysis responses
- recording_id field on sessions
Code Quality:
- Extracted finalize_run() helper (session.rs)
- Extracted execute_and_store_analysis() helper (api.rs)
- Extracted lerp_search<T>() generic helper (analysis.rs)
Breaking API Changes:
- GET /api/use-cases: string[] -> [{id, name, guidance}[]]
- Shift point analysis: gear_ranges/shift_events -> gear_curves/crossover_points
Updated README.md with new API response examples and TUI warning bar.
- Add session layer with UseCaseSession, SessionRun, SessionManager
for use-case driven telemetry analysis (shift points, track mapping)
- Add analysis module with shift point detection (gear RPM ranges,
upshift events, recommended shift RPM) and track map reconstruction
(spline-aligned interpolation for center line from boundary runs)
- Add 9 REST API endpoints for session CRUD, run management, and
analysis triggers under /api/sessions/*
- Add RecordingManager with always-on ring buffers (5 min, 18k frames)
replacing raw binary file dumps
- Wire SessionManager in main.rs with Arc<Mutex> shared state
- Add TelemetryFrame Serialize derives for JSON API output
- Fix stop_recording race: hold active lock across flush I/O
- Fix flush: separate ring buffer lock from JSON serialization
- Fix flush failure propagation: errors prevent Stopped status
- Add data_truncated flag on SessionRun for ring buffer wrap detection
- Deduplicate gear_display into shared free function
- Deduplicate session_display into closure
- Mutex poisoning recovery on all session API handlers