mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
CNS calculation fix
Identify previous dives for CNS calculation in a similar way as it is done for previous dives for deco calculation. This is done to identify the previous dives dynamically when moving around date/time of a dive in the planner. Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
This commit is contained in:
parent
4158a4c7de
commit
7a82103c99
1 changed files with 137 additions and 31 deletions
168
core/divelist.c
168
core/divelist.c
|
@ -205,42 +205,19 @@ int const cns_table[][3] = {
|
||||||
{ 600, 720 * 60, 720 * 60 }
|
{ 600, 720 * 60, 720 * 60 }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* this only gets called if dive->maxcns == 0 which means we know that
|
/* Calculate the CNS for a single dive */
|
||||||
* none of the divecomputers has tracked any CNS for us
|
double calculate_cns_dive(struct dive *dive)
|
||||||
* so we calculated it "by hand" */
|
|
||||||
static int calculate_cns(struct dive *dive)
|
|
||||||
{
|
{
|
||||||
int i, divenr;
|
int n;
|
||||||
size_t j;
|
size_t j;
|
||||||
double cns = 0.0;
|
|
||||||
struct divecomputer *dc = &dive->dc;
|
struct divecomputer *dc = &dive->dc;
|
||||||
struct dive *prev_dive;
|
double cns = 0.0;
|
||||||
timestamp_t endtime;
|
|
||||||
|
/* Caclulate the CNS for each sample in this dive and sum them */
|
||||||
/* shortcut */
|
for (n = 1; n < dc->samples; n++) {
|
||||||
if (dive->cns)
|
|
||||||
return dive->cns;
|
|
||||||
/*
|
|
||||||
* Do we start with a cns loading from a previous 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);
|
|
||||||
if (prev_dive) {
|
|
||||||
endtime = dive_endtime(prev_dive);
|
|
||||||
if (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 t;
|
||||||
int po2;
|
int po2;
|
||||||
struct sample *sample = dc->sample + i;
|
struct sample *sample = dc->sample + n;
|
||||||
struct sample *psample = sample - 1;
|
struct sample *psample = sample - 1;
|
||||||
t = sample->time.seconds - psample->time.seconds;
|
t = sample->time.seconds - psample->time.seconds;
|
||||||
if (sample->setpoint.mbar) {
|
if (sample->setpoint.mbar) {
|
||||||
|
@ -259,6 +236,135 @@ static int calculate_cns(struct dive *dive)
|
||||||
j--;
|
j--;
|
||||||
cns += ((double)t) / ((double)cns_table[j][1]) * 100;
|
cns += ((double)t) / ((double)cns_table[j][1]) * 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return cns;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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, divenr;
|
||||||
|
double cns = 0.0;
|
||||||
|
timestamp_t last_starttime, last_endtime = 0;
|
||||||
|
|
||||||
|
/* shortcut */
|
||||||
|
if (dive->cns)
|
||||||
|
return dive->cns;
|
||||||
|
|
||||||
|
divenr = get_divenr(dive);
|
||||||
|
i = divenr >= 0 ? divenr : dive_table.nr;
|
||||||
|
#if DECO_CALC_DEBUG & 2
|
||||||
|
if (i >= 0 && i < dive_table.nr)
|
||||||
|
printf("\n\n*** CNS for dive #%d %d\n", i, get_dive(i)->number);
|
||||||
|
else
|
||||||
|
printf("\n\n*** CNS for dive #%d\n", i);
|
||||||
|
#endif
|
||||||
|
/* Look at next dive in dive list table and correct i when needed */
|
||||||
|
while (i < dive_table.nr - 1) {
|
||||||
|
struct dive *pdive = get_dive(i);
|
||||||
|
if (!pdive || pdive->when > dive->when)
|
||||||
|
break;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
/* Look at previous dive in dive list table and correct i when needed */
|
||||||
|
while (i > 0) {
|
||||||
|
struct dive *pdive = get_dive(i - 1);
|
||||||
|
if (!pdive || pdive->when < dive->when)
|
||||||
|
break;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
#if DECO_CALC_DEBUG & 2
|
||||||
|
printf("Dive number corrected to #%d\n", i);
|
||||||
|
#endif
|
||||||
|
last_starttime = dive->when;
|
||||||
|
/* Walk backwards to check previous dives - how far do we need to go back? */
|
||||||
|
while (i--) {
|
||||||
|
if (i == divenr && i > 0)
|
||||||
|
i--;
|
||||||
|
#if DECO_CALC_DEBUG & 2
|
||||||
|
printf("Check if dive #%d %d has to be considered as prev dive: ", i, get_dive(i)->number);
|
||||||
|
#endif
|
||||||
|
struct dive *pdive = get_dive(i);
|
||||||
|
/* we don't want to mix dives from different trips as we keep looking
|
||||||
|
* for how far back we need to go */
|
||||||
|
if (dive->divetrip && pdive->divetrip != dive->divetrip) {
|
||||||
|
#if DECO_CALC_DEBUG & 2
|
||||||
|
printf("No - other dive trip\n");
|
||||||
|
#endif
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!pdive || pdive->when >= dive->when || dive_endtime(pdive) + 12 * 60 * 60 < last_starttime) {
|
||||||
|
#if DECO_CALC_DEBUG & 2
|
||||||
|
printf("No\n");
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
last_starttime = pdive->when;
|
||||||
|
#if DECO_CALC_DEBUG & 2
|
||||||
|
printf("Yes\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/* Walk forward and add dives and surface intervals to CNS */
|
||||||
|
while (++i < dive_table.nr) {
|
||||||
|
#if DECO_CALC_DEBUG & 2
|
||||||
|
printf("Check if dive #%d %d will be really added to CNS calc: ", i, get_dive(i)->number);
|
||||||
|
#endif
|
||||||
|
struct dive *pdive = get_dive(i);
|
||||||
|
/* again skip dives from different trips */
|
||||||
|
if (dive->divetrip && dive->divetrip != pdive->divetrip) {
|
||||||
|
#if DECO_CALC_DEBUG & 2
|
||||||
|
printf("No - other dive trip\n");
|
||||||
|
#endif
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Don't add future dives */
|
||||||
|
if (pdive->when >= dive->when) {
|
||||||
|
#if DECO_CALC_DEBUG & 2
|
||||||
|
printf("No - future or same dive\n");
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Don't add the copy of the dive itself */
|
||||||
|
if (i == divenr) {
|
||||||
|
#if DECO_CALC_DEBUG & 2
|
||||||
|
printf("No - copy of dive\n");
|
||||||
|
#endif
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#if DECO_CALC_DEBUG & 2
|
||||||
|
printf("Yes\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* CNS reduced with 90min halftime during surface interval */
|
||||||
|
if (last_endtime)
|
||||||
|
cns /= pow(2, (pdive->when - last_endtime) / (90.0 * 60.0));
|
||||||
|
#if DECO_CALC_DEBUG & 2
|
||||||
|
printf("CNS after surface interval: %f\n", cns);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
cns += calculate_cns_dive(pdive);
|
||||||
|
#if DECO_CALC_DEBUG & 2
|
||||||
|
printf("CNS after previous dive: %f\n", cns);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
last_starttime = pdive->when;
|
||||||
|
last_endtime = dive_endtime(pdive);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CNS reduced with 90min halftime during surface interval */
|
||||||
|
if (last_endtime)
|
||||||
|
cns /= pow(2, (dive->when - last_endtime) / (90.0 * 60.0));
|
||||||
|
#if DECO_CALC_DEBUG & 2
|
||||||
|
printf("CNS after last surface interval: %f\n", cns);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
cns += calculate_cns_dive(dive);
|
||||||
|
#if DECO_CALC_DEBUG & 2
|
||||||
|
printf("CNS after dive: %f\n", cns);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* save calculated cns in dive struct */
|
/* save calculated cns in dive struct */
|
||||||
dive->cns = lrint(cns);
|
dive->cns = lrint(cns);
|
||||||
return dive->cns;
|
return dive->cns;
|
||||||
|
|
Loading…
Add table
Reference in a new issue