diff options
author | Anton Lundin <glance@acc.umu.se> | 2013-04-09 19:25:21 +0200 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2013-04-23 20:43:34 -0700 |
commit | ee0025f69687af08347de738dcd2d2dc9ebc6365 (patch) | |
tree | f9c50e4b7b5cbbf2c3a0bda3cc2de690638dbcee /divelist.c | |
parent | 8cdb8364008487753d9e8f31f9165048f827f2d1 (diff) | |
download | subsurface-ee0025f69687af08347de738dcd2d2dc9ebc6365.tar.gz |
Add a simple table-based cns calculations
For dives where divecomputers haven't provided us with a cns, we
calculate our cns accumulated during that dive based on a simple table.
We also check if we did a dive in the prior 12 ours and grab the cns
from it and calculate how much of that still affects us.
[Dirk Hohndel: a couple of small changes: remove unnecessary check of cns
values in the samples of the first dive computer, changed
the way we determine the 'previous dive' and used the end
time of that previous dive for the decay calculation]
Signed-off-by: Anton Lundin <glance@acc.umu.se>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Diffstat (limited to 'divelist.c')
-rw-r--r-- | divelist.c | 72 |
1 files changed, 71 insertions, 1 deletions
diff --git a/divelist.c b/divelist.c index 42fb272b0..577750399 100644 --- a/divelist.c +++ b/divelist.c @@ -273,7 +273,7 @@ static int active_o2(struct dive *dive, struct divecomputer *dc, duration_t time return o2permille; } -/* calculate OTU for a dive - this only takes the first diveomputer into account */ +/* calculate OTU for a dive - this only takes the first divecomputer into account */ static int calculate_otu(struct dive *dive) { int i; @@ -297,6 +297,74 @@ static int calculate_otu(struct dive *dive) } return otu + 0.5; } +/* calculate CNS for a dive - this only takes the first divecomputer into account */ +int const cns_table[][3] = { +/* po2, Maximum Single Exposure, Maximum 24 hour Exposure */ + {1600, 45 * 60, 150 * 60}, + {1500, 120 * 60, 180 * 60}, + {1400, 150 * 60, 180 * 60}, + {1300, 180 * 60, 210 * 60}, + {1200, 210 * 60, 240 * 60}, + {1100, 240 * 60, 270 * 60}, + {1000, 300 * 60, 300 * 60}, + { 900, 360 * 60, 360 * 60}, + { 800, 450 * 60, 450 * 60}, + { 700, 570 * 60, 570 * 60}, + { 600, 720 * 60, 720 * 60} +}; + +/* this only gets called if dive->maxcns == 0 which means we know that + * none of the divecomputers has tracked any CNS for us + * so we calculated it "by hand" */ +static int calculate_cns(struct dive *dive) +{ + int i, j, divenr; + double cns = 0.0; + struct divecomputer *dc = &dive->dc; + struct dive *prev_dive; + timestamp_t endtime; + + /* shortcut */ + if (dive->cns) + return dive->cns; + /* + * Do we start with a cns loading from a privious dive? + * Check if we did a dive 12 hours prior, and what cns we had from that. + * Then apply ha 90min halftime to see whats left. + */ + divenr = get_divenr(dive); + if (divenr) { + prev_dive = get_dive(divenr -1 ); + endtime = prev_dive->when + prev_dive->duration.seconds; + if (prev_dive && dive->when < (endtime + 3600 * 12)) { + cns = calculate_cns(prev_dive); + cns = cns * 1/pow(2, (dive->when - endtime) / (90.0 * 60.0)); + } + } + /* Caclulate the cns for each sample in this dive and sum them */ + for (i = 1; i < dc->samples; i++) { + int t; + int po2; + struct sample *sample = dc->sample + i; + struct sample *psample = sample - 1; + t = sample->time.seconds - psample->time.seconds; + if (sample->po2) { + po2 = sample->po2; + } else { + int o2 = active_o2(dive, dc, sample->time); + po2 = o2 / 1000.0 * depth_to_mbar(sample->depth.mm, dive); + } + /* Find what table-row we should calculate % for */ + for (j = 1; j < sizeof(cns_table)/(sizeof(int) * 3); j++) + if (po2 > cns_table[j][0]) + break; + j--; + cns += ((double)t)/((double)cns_table[j][1]) * 100; + } + /* save calculated cns in dive struct */ + dive->cns = cns; + return dive->cns; +} /* * Return air usage (in liters). */ @@ -456,6 +524,8 @@ void update_cylinder_related_info(struct dive *dive) if (dive != NULL) { dive->sac = calculate_sac(dive); dive->otu = calculate_otu(dive); + if (dive->maxcns == 0) + dive->maxcns = calculate_cns(dive); } } |