dive_deco/common/
deco_model.rs1use crate::common::deco::{DecoCalculationError, DecoRuntime};
2use crate::common::global_types::{CeilingType, MbarPressure};
3use crate::common::ox_tox::OxTox;
4use crate::common::{AscentRatePerMinute, Cns, Gas, Otu};
5use crate::common::{Depth, Time};
6use alloc::string::String;
7use alloc::vec;
8use alloc::vec::Vec;
9#[cfg(feature = "serde")]
10use serde::{Deserialize, Serialize};
11
12#[derive(Debug, PartialEq)]
13#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
14pub struct ConfigValidationErr {
15 pub field: String,
16 pub reason: String,
17}
18
19impl ConfigValidationErr {
20 pub fn new(field: &str, reason: &str) -> Self {
21 Self {
22 field: String::from(field),
23 reason: String::from(reason),
24 }
25 }
26}
27
28pub trait DecoModelConfig {
29 fn validate(&self) -> Result<(), ConfigValidationErr>;
30 fn surface_pressure(&self) -> MbarPressure;
31 fn deco_ascent_rate(&self) -> AscentRatePerMinute;
32 fn ceiling_type(&self) -> CeilingType;
33 fn round_ceiling(&self) -> bool;
34}
35
36#[derive(Debug, Clone)]
37#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
38pub struct DiveState {
39 pub depth: Depth,
40 pub time: Time,
41 pub gas: Gas,
42 pub ox_tox: OxTox,
43}
44
45pub trait DecoModel {
46 type ConfigType: DecoModelConfig;
47
48 fn default() -> Self;
50
51 fn new(config: Self::ConfigType) -> Self;
53
54 fn config(&self) -> Self::ConfigType;
56
57 fn dive_state(&self) -> DiveState;
59
60 fn record(&mut self, depth: Depth, time: Time, gas: &Gas);
62
63 fn record_travel(&mut self, target_depth: Depth, time: Time, gas: &Gas);
65
66 fn record_travel_with_rate(
68 &mut self,
69 target_depth: Depth,
70 rate: AscentRatePerMinute,
71 gas: &Gas,
72 );
73
74 fn ndl(&self) -> Time;
76
77 fn ceiling(&self) -> Depth;
79
80 fn deco(&self, gas_mixes: Vec<Gas>) -> Result<DecoRuntime, DecoCalculationError>;
82
83 fn in_deco(&self) -> bool {
85 let ceiling_type = self.config().ceiling_type();
86 match ceiling_type {
87 CeilingType::Actual => self.ceiling() > Depth::zero(),
88 CeilingType::Adaptive => {
89 let current_gas = self.dive_state().gas;
90 let runtime = self.deco(vec![current_gas]).unwrap();
91 let deco_stages = runtime.deco_stages;
92 deco_stages.len() > 1
93 }
94 }
95 }
96
97 fn cns(&self) -> Cns {
99 self.dive_state().ox_tox.cns()
100 }
101
102 fn otu(&self) -> Otu {
104 self.dive_state().ox_tox.otu()
105 }
106}