Features
Phone-camera + laser-cartridge dry fire
Set the phone on a tripod, point it at an IPSC silhouette, drop a laser cartridge into the chamber. The app reads each shot's location at preview frame-rate and converts it into a scored zone.
Calibration
- One-tap auto-segment. SAM (Segment Anything Mobile) runs on-device, seeds at the centre of the frame, returns 4 bounding corners + an octagon silhouette. No manual corner dragging needed for clean targets.
- Live environment grade. The phone measures contrast (target vs ring), background flicker (LED ballast / sun through curtains), tilt and target size. Each gets a Good / Medium / Poor grade so you know whether to start or move the phone.
- Test-shot gate. One ROI-checked shot before the timer starts. If the gate doesn't see a hit in 5 s, you're sent back to recalibrate — no false starts on a live drill.
- REPEAT auto-validation. Tapping REPEAT runs a single SAM frame; if the silhouette centroid drifted > 5 % of frame width, you're prompted to recalibrate. Otherwise straight to ready-shot.
Detection trust pipeline
Every laser candidate is ranked through five filters in strict order:
- ROI — must land inside the calibrated silhouette + 8 % border.
- Blob size — bright pixel cluster within 4–60 px.
- Flash duration — bright spike persists 1–3 frames.
- Brightness delta — Δ ≥ 50 from rolling baseline.
- Debounce — last accepted shot ≥ 100 ms ago.
A weighted confidence (0–1) over brightness, blob size, duration, ROI centeredness and background stability gates the final accept. Every accepted and rejected candidate is logged with its reason, so when the gate drops a shot you know whether it was lighting, size, ROI, or something else.
Modes & drills
- Free Drill — open shooting, manual stop, beep delay 5–15 s.
- Draw / 2-Shots — auto-stops after two valid hits, beep delay 3–15 s.
- Bill Drill — 1 target, 6 shots, par 2 s ideal.
- El Presidente — 3 targets, 6 shots (V1 collapses the reload), par 10 s.
- FAST — 1 target, 6 shots, par 7 s.
Adding a drill is a JSON entry, not a screen.
Coaching layer
After every attempt the app emits one Primary insight, an optional Secondary in a different category, an Action card (Focus / Target / Drill), and a single-line takeaway. The engine is rule-based — deterministic, < 10 ms, no LLM.
Ten priority rules, in order:
- First-shot miss
- Draw breaking (delta > 150 ms)
- Over-confirming first shot (delta > 100 ms, hits clean)
- Transition miss (shots 2–3)
- Late miss (shots ≥ 4)
- Split inconsistency (stddev > threshold per focus)
- Miss rate up under speed
- Alpha leaking into C/D
- Speed up, points down
- Balanced run (positive reinforcement)
Tone shifts with skill tier — Beginner gets supportive phrasing, Advanced gets terse metric-driven lines. The tier is internal only; never shown as an ego label.
Multi-device sync
One phone is the master (timer + scoring). Other phones join as clients (detection only) via a 6-digit room code on the cloud relay. Master clock wins; clients ship local timestamps offset to master via NTP-style sync. Late events that arrive after the stop trigger but inside the grace window are sorted by global time and included in the final timeline.
Disconnect handling: a client gone for > 5 s flips the banner to red and the master finalises with the events it has. Master phone briefly offline → buffers events client- side and replays on reconnect.
Adaptive coaching from pooled data
Once practicalhit has enough runs, the engine compares your numbers to the population's:
- Cohort percentiles. "Your draw is in the bottom quartile of intermediate shooters (median 0.95 s, you 1.18 s). Drill: Draw / 2-Shots × 5 sessions."
- Miss heatmap. Hits aggregated into a 32×32 grid. Cluster centroid is mapped to a known weakness (grip, flinch, follow-through).
- Trend nudge. Two-half average compare on the last 20 attempts. The worst-regressing metric becomes a one-line home-screen nudge ("Your alpha rate is trending down — slow your last 2 shots").
- Weekly challenges. Sunday-to-Sunday window, one drill, public standings.
Performance contract
Hard latency budgets that every PR must keep green:
- Beep audio < 20 ms from controller stamp
- Shot detection < 50 ms from frame timestamp
- Result render < 100 ms from stage complete
- Repeat action < 200 ms from tap to ready-shot
Long-press the home title to surface the live debug overlay (BEEP / DETECT / RENDER / REPEAT pills, green when in budget, red when over). Two consecutive over-budget attempts → remote log entry.
Anti-cheat
- Server re-scores every attempt from the saved per-shot coordinates.
- An attempt without a detection log can't reach the public board.
- Implausible runs (HF > 12 with HIGH confidence) get flagged for manual review.
- Calibration sanity checks the corner quad shape.
- Replay tampering — HIGH confidence stamped but rejection ratio > 50 % — surfaces the row in the review queue.
Privacy
- Anonymous per-install device id is the only identity.
- Optional shooter handle + country (public). Email is private.
- Detection logs decay to histogram-only at 90 days.
- Stack traces scrubbed of file paths before persistence.
DELETE /api/shooter/<handle>is a full GDPR purge.