diving_decompression/
lib.rs1#![forbid(unsafe_code)]
54#![deny(non_snake_case)]
55#![deny(non_camel_case_types)]
56#![deny(non_upper_case_globals)]
57#![deny(unused_imports)]
58#![deny(unused_mut)]
59#![deny(missing_docs)]
60#![deny(dead_code)]
61#[macro_use]
62
63extern crate serde_derive;
64
65pub mod airtables;
67
68#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
70pub struct Dive {
71 pub depth: u16,
73 pub bottom_time: u16,
75}
76
77#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
79pub struct DivePlan {
80 pub depth: u16,
82 pub bottom_time: u16,
84 pub surface_interval_time: u16,
86 pub next_dive_depth: u16,
88}
89
90impl Dive {
91 pub fn new(depth: u16, bottom_time: u16) -> Self {
92 Self {
94 depth,
95 bottom_time,
96 }
97 }
98
99 pub fn no_decompression_limit(self) -> u16 {
100 let mut ndl: u16 = 0;
104
105 if self.depth > 190 {
106 return ndl;
107 }
108
109 let nodeco_table = airtables::nodeco_table()
110 .expect("Error serializing the data within the table nodeco_table");
111
112 for row in nodeco_table.table_data.iter() {
113 if row.min_fsw <= self.depth && self.depth <= row.max_fsw {
114 ndl = row.no_stop_limit
115 }
116 }
117
118 return ndl;
119 }
120
121 pub fn group_letter(self) -> String {
122 let mut gl: String = String::from("");
127
128 let nodeco_table = airtables::nodeco_table()
129 .expect("Error serializing the data within the deco_table");
130
131 for row in nodeco_table.table_data.iter() {
132 if row.min_fsw <= self.depth && self.depth <= row.max_fsw {
133 for value in row.values.iter() {
134 if value.min_time <= self.bottom_time && self.bottom_time <= value.max_time {
135 gl = String::from(&value.group_letter);
136 }
137 }
138 }
139 }
140
141 if gl == String::from("") && self.depth > 0 && self.depth <= 10 && self.bottom_time > 462 {
142 gl = String::from("F")
143 } else if gl == String::from("") && self.depth > 10 && self.depth <= 15 && self.bottom_time > 449 {
144 gl = String::from("I")
145 } else if gl == String::from("") && self.depth > 15 && self.depth <= 20 && self.bottom_time > 461 {
146 gl = String::from("L")
147 }
148
149 if gl == String::from("") && self.depth <= 190 {
150 gl = String::from("this dive is out of the time range for no-decompression air dives")
151 } else if gl == String::from("") && self.depth > 190 {
152 gl = String::from("this dive is out of the depth range for no-decompression air dives")
153 }
154
155 return gl;
156 }
157
158 pub fn deco_dive(self) -> airtables::RowDeco {
159 let deco_table = airtables::deco_table()
164 .expect("Error deserializing no decompression table");
165
166 let mut deco_profile: airtables::RowDeco = airtables::RowDeco {
167 min_time: 0,
168 max_time: 0,
169 air_tat: String::from("0"),
170 o2_tat: String::from("0"),
171 ttfs: String::from("0"),
172 o2cp: 0.0,
173 repetgroup_letter: String::from("0"),
174 surdo2_recommended: false,
175 exceptional_exposure: false,
176 surdo2_required: false,
177 strict_surdo2: false,
178 air_deco_stops: vec![],
179 o2_deco_stops: vec![],
180 };
181
182 for row_deco in deco_table.table_data.iter() {
183 if row_deco.min_fsw <= self.depth && self.depth <= row_deco.max_fsw {
184 for profile in row_deco.rows.iter() {
185 if profile.min_time <= self.bottom_time && profile.max_time <= self.bottom_time {
186 deco_profile = profile.clone()
187 }
188 }
189 }
190 }
191 return deco_profile;
192 }
193}
194
195impl DivePlan {
196 pub fn new(depth: u16, bottom_time: u16, surface_interval_time: u16, next_dive_depth: u16) -> Self {
197 Self {
202 depth,
203 bottom_time,
204 surface_interval_time,
205 next_dive_depth,
206 }
207 }
208
209 pub fn from_dive(dive: Dive, surface_interval_time: u16, next_dive_depth: u16) -> Self {
210 Self {
215 depth: dive.depth,
216 bottom_time: dive.bottom_time,
217 surface_interval_time,
218 next_dive_depth,
219 }
220 }
221
222 pub fn no_decompression_limit(self) -> u16 {
223 let mut ndl: u16 = 0;
226
227 if self.depth > 190 {
228 return ndl;
229 }
230
231 let nodeco_table = airtables::nodeco_table()
232 .expect("Error serializing the data withthe table deco_table");
233
234 for row in nodeco_table.table_data.iter() {
235 if row.min_fsw <= self.depth && self.depth <= row.max_fsw {
236 ndl = row.no_stop_limit
237 }
238 }
239
240 return ndl;
241 }
242
243 pub fn group_letter(self) -> String {
244 let mut gl: String = String::from("");
249
250 let nodeco_table = airtables::nodeco_table()
251 .expect("Error serializing the data within the deco_table");
252
253 for row in nodeco_table.table_data.iter() {
254 if row.min_fsw <= self.depth && self.depth <= row.max_fsw {
255 for value in row.values.iter() {
256 if value.min_time <= self.bottom_time && self.bottom_time <= value.max_time {
257 gl = String::from(&value.group_letter);
258 }
259 }
260 }
261 }
262
263 if gl == String::from("") && self.depth > 0 && self.depth <= 10 && self.bottom_time > 462 {
264 gl = String::from("F")
265 } else if gl == String::from("") && self.depth > 10 && self.depth <= 15 && self.bottom_time > 449 {
266 gl = String::from("I")
267 } else if gl == String::from("") && self.depth > 15 && self.depth <= 20 && self.bottom_time > 461 {
268 gl = String::from("L")
269 }
270
271 if gl == String::from("") && self.depth <= 190 {
272 gl = String::from("this dive is out of the time range for no-decompression air dives")
273 } else if gl == String::from("") && self.depth > 190 {
274 gl = String::from("this dive is out of the depth range for no-decompression air dives")
275 }
276 return gl;
277 }
278
279 pub fn repet_letter(self) -> String {
280 let nodeco_table = airtables::nodeco_table()
285 .expect("Error serializing the data within the deco_table");
286
287 let rgl_table = airtables::rgl_table()
288 .expect("there was an error deserializing deco table");
289
290 let mut rl = String::new();
291
292 for row in nodeco_table.table_data.iter() {
293 if row.min_fsw <= self.depth && self.depth <= row.max_fsw {
294 for group in row.values.iter() {
295 if group.min_time <= self.bottom_time && self.bottom_time <= group.max_time {
296 for rgl_row in rgl_table.table_data.iter() {
297 if rgl_row.group_letter == group.group_letter && rgl_row.min_time <= self.surface_interval_time && self.surface_interval_time <= rgl_row.max_time {
298 rl = String::from(&rgl_row.repet_letter)
299 }
300 }
301 }
302 }
303 }
304 }
305
306 return rl;
307 }
308
309 pub fn residual_nitrogen_time(self) -> u16 {
310 let nodeco_table = airtables::nodeco_table()
315 .expect("Error deserializing no decompression table");
316
317 let rgl_table = airtables::rgl_table()
318 .expect("Error deserializing repetitive group letter table");
319
320 let rnt_table = airtables::rnt_table()
321 .expect("Error deserializing residual nitrogen time table");
322
323 let mut rnt = 0;
324
325 for row in nodeco_table.table_data.iter() {
326 if row.min_fsw <= self.depth && self.depth <= row.max_fsw {
327 for group in row.values.iter() {
328 if group.min_time <= self.bottom_time && self.bottom_time <= group.max_time {
329 for rgl_row in rgl_table.table_data.iter() {
330 if rgl_row.group_letter == group.group_letter && rgl_row.min_time <= self.surface_interval_time && self.surface_interval_time <= rgl_row.max_time {
331 for rnt_column in rnt_table.table_data.iter() {
332 if rnt_column.repet_letter == rgl_row.repet_letter {
333 for element in rnt_column.rnt.iter() {
334 if element.min_depth <= self.next_dive_depth && self.next_dive_depth <= element.max_depth {
335 rnt = element.rnt
336 }
337 }
338 }
339 }
340 }
341 }
342 }
343 }
344 }
345 }
346
347 return rnt;
348 }
349}