Marshaling: live enter/exit re-detection with manual commit#348
Merged
Conversation
The RotorHazard-style "Recalculate with draggable thresholds" the RssiGraph deferred (marshaling.html §5), frontend-only: - lib/redetect.ts (pure, tested): detectPasses re-runs RH-semantics enter/exit hysteresis over the captured trace (open at ≥enter, track the window peak, close at ≤exit; pass = peak time; an open window at trace end emits nothing; enter must exceed exit). diffPasses greedy-nearest-matches the re-detection against the current official passes (500ms tolerance, each pass matches at most once) into kept/added/removed; previewLaps derives the would-be lap list (first pass = holeshot); officialPasses reconstructs a competitor's boundary passes from the corrected lap list; defaultThresholds gives a 75th/25th-percentile fallback for unset traces. - RssiGraph.svelte: opt-in tuning props — `onthresholds` grows draggable (pointer) + keyboard-nudgeable (±1) handles on the enter/exit lines; `tuned` overrides the drawn levels (and the shaded crossing windows) for the competitor being adjusted; `preview` draws hollow dashed markers for would-be-ADDED passes and strikes/dims lap markers whose closing pass would be REMOVED. Without the new props the graph stays exactly the old display-only surface. - Marshaling.svelte: a "Tune detection" panel (trace + control only, scoped to the marshaled pilot) with enter/exit number inputs seeded from the trace's recorded thresholds, two-way with the graph drag. The preview re-detects live — "Would be N laps (+A added, −R removed)" plus the preview lap list — sending NOTHING while adjusting. Commit turns the diff into the existing primitives (a VoidDetection per removed pass, then a heat-tagged InsertLap per added one, sequentially), refreshes, and toasts a summary with the resolved callsign; Reset restores the recorded levels. The thresholds are a UI/preview concern only — never written back to the timer (pushing calibration to RH via the plugin is a separate future feature). Tests: 20 redetect unit tests (hysteresis incl. double-peak/open-window/ boundary/dense-times, diff tolerance edges, preview laps, official passes, percentile fallback), 6 graph tuning tests (drag/keyboard emit, tuned override, preview markers, display-only without props), 7 screen tests (panel gating + seeding, live preview without sends, exact commit batches, invalid-threshold flag, reset). Full suite 524 green; svelte-check + lint clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The RotorHazard-style marshaling flow, per user spec: move the entry/exit levels live over the captured RSSI trace, watch the re-detected laps populate as a preview, and Commit to make them official.
How it works
redetect.ts— crossing opens ≥ enter, peak-timed, closes ≤ exit; dense per-sample timestamps preferred; incomplete trailing windows excluded), diffs against the current official passes (greedy nearest-match, 500ms tolerance), and shows added candidates (dashed hollow markers) and would-be-removed laps (struck/dimmed) on the graph plus a preview lap list — "would be N laps (+A, −R)".VoidDetectionper removed pass, a heat-taggedInsertLapper added one — so every re-detection lands in the audit trail and is reversible like any other ruling. Reset restores the recorded thresholds.Verification
33 new tests (detection math incl. noisy double-peaks/ties/boundary-inclusive edges/dense-vs-uniform timing; graph drag/keyboard/preview rendering; screen gating, live-preview-sends-nothing, exact commit command batches, Reset). Suite: 41 files / 524 tests green, both svelte-check passes, lint clean. Display-only graph behavior is unchanged when the new props are absent (all 11 pre-existing graph tests untouched).
🤖 Generated with Claude Code