feat(dive-log): linear estimated tank pressure line for manual dives (#197)#493
Merged
Conversation
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a chart-only, in-memory synthesized tank pressure series for dives that have manually entered start/end pressures but no air-integrated (AI) samples, so the dive profile chart still shows a pressure visualization for manual dives (issue #197). The synthesized series is explicitly labeled as estimated and rendered as a straight line to avoid confusion with real transmitter traces.
Changes:
- Add per-tank “active breathing windows” derivation from gas switches and use it to synthesize flat–drop–flat (windowed) pressure series when only start/end pressures exist.
- Introduce a composing Riverpod provider that augments real
tankPressureswith estimates (chart-only) and plumbsestimatedTankIdsthrough chart/legend/tooltip/readout for labeling + straight-line rendering. - Add i18n key for the estimated suffix across all locales and expand unit/widget/provider tests for the new behavior.
Reviewed changes
Copilot reviewed 38 out of 38 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| test/features/dive_log/presentation/widgets/dive_profile_legend_test.dart | Verifies legend marks estimated tank rows with the suffix. |
| test/features/dive_log/presentation/widgets/dive_profile_chart_test.dart | Verifies estimated pressure lines render straight and tooltip labels include the suffix. |
| test/features/dive_log/presentation/providers/estimated_tank_pressures_provider_test.dart | Tests provider composes real + estimated pressure series for manual tanks. |
| test/features/dive_log/data/services/gas_usage_segments_service_test.dart | Adds coverage for buildActiveTankIntervals interval derivation. |
| test/features/dive_log/data/services/estimated_tank_pressure_synthesizer_test.dart | Adds unit coverage for synthesis trigger rules and flat–drop–flat shape. |
| lib/l10n/arb/app_zh.arb | Adds localized estimated suffix. |
| lib/l10n/arb/app_pt.arb | Adds localized estimated suffix. |
| lib/l10n/arb/app_nl.arb | Adds localized estimated suffix. |
| lib/l10n/arb/app_en.arb | Adds estimated suffix key + description metadata. |
| lib/l10n/arb/app_de.arb | Adds localized estimated suffix. |
| lib/l10n/arb/app_es.arb | Adds localized estimated suffix. |
| lib/l10n/arb/app_fr.arb | Adds localized estimated suffix. |
| lib/l10n/arb/app_it.arb | Adds localized estimated suffix. |
| lib/l10n/arb/app_hu.arb | Adds localized estimated suffix. |
| lib/l10n/arb/app_he.arb | Adds localized estimated suffix. |
| lib/l10n/arb/app_ar.arb | Adds localized estimated suffix. |
| lib/l10n/arb/app_localizations.dart | Declares the new localization getter. |
| lib/l10n/arb/app_localizations_zh.dart | Implements the getter for zh locale. |
| lib/l10n/arb/app_localizations_pt.dart | Implements the getter for pt locale. |
| lib/l10n/arb/app_localizations_nl.dart | Implements the getter for nl locale. |
| lib/l10n/arb/app_localizations_it.dart | Implements the getter for it locale. |
| lib/l10n/arb/app_localizations_hu.dart | Implements the getter for hu locale. |
| lib/l10n/arb/app_localizations_he.dart | Implements the getter for he locale. |
| lib/l10n/arb/app_localizations_fr.dart | Implements the getter for fr locale. |
| lib/l10n/arb/app_localizations_es.dart | Implements the getter for es locale. |
| lib/l10n/arb/app_localizations_en.dart | Implements the getter for en locale. |
| lib/l10n/arb/app_localizations_de.dart | Implements the getter for de locale. |
| lib/l10n/arb/app_localizations_ar.dart | Implements the getter for ar locale. |
| lib/features/dive_log/presentation/widgets/dive_profile_panel.dart | Uses estimated provider output for chart-only rendering and passes estimatedTankIds. |
| lib/features/dive_log/presentation/widgets/dive_profile_legend.dart | Adds estimatedTankIds to legend config and appends localized suffix in Tank Pressures rows. |
| lib/features/dive_log/presentation/widgets/dive_profile_chart.dart | Adds estimatedTankIds, appends suffix in tooltip/readout, and renders estimated lines as straight. |
| lib/features/dive_log/presentation/providers/dive_providers.dart | Adds estimatedTankPressuresProvider composing real + synthesized pressures. |
| lib/features/dive_log/presentation/pages/fullscreen_profile_page.dart | Uses estimated provider output for chart-only rendering and passes estimatedTankIds. |
| lib/features/dive_log/presentation/pages/dive_detail_page.dart | Uses estimated provider output for chart-only rendering and passes estimatedTankIds. |
| lib/features/dive_log/data/services/gas_usage_segments_service.dart | Adds buildActiveTankIntervals (tank-keyed active windows from gas switches). |
| lib/features/dive_log/data/services/estimated_tank_pressure_synthesizer.dart | New pure synthesizer building flat–drop–flat estimated pressure series. |
| docs/superpowers/specs/2026-07-06-linear-tank-pressure-line-design.md | Design spec for the estimated pressure line feature. |
| docs/superpowers/plans/2026-07-06-linear-tank-pressure-line.md | Implementation plan and test strategy for the feature. |
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.
Summary
Closes #197. When a dive has a tank with manually-entered start/end pressures but no air-integrated (AI) transmitter data, the profile chart previously drew no pressure line at all. This adds a linear estimated pressure line so manual-entry dives still get a pressure visualization.
The line is shaped like a real transmitter would have recorded it: flat at the start pressure while the tank is unused, dropping linearly while it is breathed (windowed by gas switches), flat during gaps, and flat at the end pressure afterward. The total drop is distributed across the tank's active windows in proportion to their duration. For the common single-tank dive this collapses to one straight
start → endline.Synthesis happens in memory at the chart-read path and is never persisted — SAC analysis and UDDF/other exports read the repository directly, so they continue to see real measured data only. The estimated line is drawn straight (real AI lines stay curved) and marked "(est.)" in the legend, tooltip, and readout so an interpolation is never mistaken for a transmitter trace.
Design spec and implementation plan:
docs/superpowers/specs/2026-07-06-linear-tank-pressure-line-design.md,docs/superpowers/plans/2026-07-06-linear-tank-pressure-line.md.Changes
buildActiveTankIntervals(gas_usage_segments_service.dart) — per-tank active[start,end)windows from gas switches, reusing the same starting-tank + switch-walk rules asbuildGasUsageSegments(keyed by tankId, no gas-mix merging).synthesizeEstimatedTankPressures+EstimatedTankPressures(newestimated_tank_pressure_synthesizer.dart) — pure flat–drop–flat series builder with duration-proportional drop distribution and full-dive fallbacks; only synthesizes when a tank has both pressures,start > end, no real time-series data, and the dive has a profile.estimatedTankPressuresProvider(dive_providers.dart) — composes real pressures + estimates; chart-only.dive_profile_chart.dart) — newestimatedTankIdsfield; estimated lines renderedisCurved: false; "(est.)" suffix in tooltip and draggable-readout rows.dive_profile_legend.dart) — "(est.)" suffix on estimated tank rows in the Tank Pressures section.dive_profile_panel,dive_detail_page,fullscreen_profile_page) — pass the augmented map +estimatedTankIdsto the chart only; SAC-normalization and marker builders keep reading the real map.diveLog_pressure_estimatedSuffixstring translated across all 11 locales.Test Plan
flutter analyzepasses (whole project, locally clean)flutter test test/features/dive_log/passes (1825 tests; full suite runs in CI)