[PATCH v2] Add a simple table-based cns calculations
Dirk Hohndel
dirk at hohndel.org
Tue Apr 9 20:44:34 PDT 2013
Anton Lundin <glance at acc.umu.se> writes:
> 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.
>
> Signed-off-by: Anton Lundin <glance at acc.umu.se>
Very nice.
I made a few small changes and am about to push this
> +static int calculate_cns(struct dive *dive)
> +{
> + int i, j;
> + double cns = 0.0;
> + struct divecomputer *dc = &dive->dc;
> +
> + /* shortcut */
> + if (dive->cns)
> + return dive->cns;
> + /* or if we have a divecomputer that already tracked cns for us */
> + if ((dc->sample + dc->samples - 1)->cns)
> + return (dc->sample + dc->samples - 1)->cns;
This would be wrong (as it just checks the first divecomputer but there
could be several), but more importantly this is unnecessary as you only
call calculate_cns() if dive->maxcns == 0. And dive->maxcns is (as the
name implies) the maximum cns value found in the samples...
I simply removed those three lines (and added a comment before the
function that explains that this only gets called if dive->maxcns is 0).
> + /*
> + * 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.
> + */
> + if (dive->next && dive->when < (dive->next->when + 3600 * 12)) {
> + cns = calculate_cns(dive->next);
> + cns = cns * 1/pow(2, (dive->when - dive->next->when) / (90.0 * 60.0));
> + }
This is the part that is problematic. dive->next is actually "the next
dive in the current trip". Some people don't use trips. Or a user may
have broken a trip in two. So instead we need to manually LOOK for the
previous dive.
I changed the code to do so.
Also, just from a logical point of view... we should use the END time of
the previous drive for the decay calculation.
> + /* 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;
> +}
The formula looks right to me - I'm surprised by some of the CNS values
that I get - they are just higher than what I'd expect. But I need to
change the code so it calculates the CNS and compares it to what's in
the samples. I think that will give me a better idea if something is
completely off
/D
More information about the subsurface
mailing list