Skip to content

Add actual-dive replay mode using recorded samples (PRO-61) - #162

Merged
shaheinm merged 4 commits into
mainfrom
feature/pro-61-actual-dive-samples
Mar 24, 2026
Merged

shaheinm merged 4 commits into
mainfrom
feature/pro-61-actual-dive-samples

Conversation

@shaheinm

Copy link
Copy Markdown
Contributor

Summary

  • New "Actual Dive" replay mode (default): feeds recorded dive samples through the deco engine with planAscent: true, computing the deco schedule the algorithm would prescribe for the actual dive profile
  • Samples truncated at bottom-end: engine plans ascent from peak tissue loading, not from surface after dive is over
  • Ascent rate from actual dive: uses computed transit-phase ascent rate instead of hardcoded 9 m/min
  • CCR setpoint override: uses recorded per-sample PPO2 by default; only overrides when user explicitly changes the setpoint field
  • "What-If Planning" mode: existing synthetic profile generator preserved as secondary mode
  • Shared mapping extensions: [DiveSample].toSampleInputs() and [GasMix].toGasMixInputs() extracted to DivelogCore, deduplicating FormulaService and DepthProfileChart

Validated on device

  • CCR 200ft/29min dive with GF 50/90: engine computes 31 min deco stops vs 34 min actual (3 min difference from imperfect stop execution — expected)

Test plan

  • make lint — clean
  • make test — all pass
  • macOS build — clean
  • make security — clean
  • make version-check — consistent
  • On-device testing (iPhone) — actual-dive mode produces reasonable results
  • /review-pr — pending
  • Codex MCP review — pending

🤖 Generated with Claude Code

Feed actual recorded dive samples through the deco engine instead of
synthetic square profiles. The replay sheet now has two modes:

- "Actual Dive" (default): runs compute_deco_simulation with plan_ascent
  on the real recorded samples truncated at bottom-end. Uses the dive's
  actual ascent rate, recorded PPO2 values, and gas switches. CCR setpoint
  and diluent remain editable for "what if SP 1.3?" analysis — override
  only applies when user changes the value.

- "What-If Planning": existing synthetic profile generator unchanged.

Also extracts DiveSample.toSampleInputs() and GasMix.toGasMixInputs()
as shared extensions in DivelogCore, deduplicating code from
FormulaService and DepthProfileChart.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Mar 23, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

shaheinm and others added 3 commits March 23, 2026 17:22
The 95% max-depth heuristic fails for multi-level dives. Use the
properly computed bottomEndT from DiveStats when available, which
handles multi-level profiles, depth oscillations, and ascent detection
correctly. Falls back to the heuristic only when stats are unavailable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use recorded gas table for CCR actual-dive mode by default; only
  override when user changes diluent from prefilled values (fixes
  multi-diluent/bailout CCR dives analyzing wrong gas mix)
- Validate setpoint override: show error for non-numeric values instead
  of silently falling back to recorded PPO2
- Relabel "Total Time" to "Recorded Time" in actual-dive mode to
  clarify it's not a simulation output
- Rename "Deco Stops" to "Deco Stop Time" to match the displayed value

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
9 tests covering:
- Empty array handling
- Field mapping (DiveSample → SampleInput, GasMix → GasMixInput)
- PPO2 fallback: ppo2_1 preferred, setpointPpo2 as fallback, nil for OC
- Type conversions (Int → Int32, Float → Double)
- Multiple samples/mixes
- Nil gasmixIndex passthrough

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@shaheinm
shaheinm merged commit 4ffb130 into main Mar 24, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant