mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-30 22:20:21 +00:00
init_deco correctly identify previous dives and report overlapping dives
When changing the date/time of a dive in the planner the dive may end up in a totaly new position in respect to date/time of other dives in dive list table. It can be moved to the past or the future before or after other existing dives. It also could overlap with an existing dive. This change enables identification of a new "virtual" dive list position and based on this starts looking for previous dives. Then it (as before the change) does init the deco calculation with any applicable previous dive and surface interval. If some of these applicable dives overlap it returns a neg. surface time which is then used in the planner notes to prohibit display of results. Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
This commit is contained in:
parent
59845c1343
commit
4158a4c7de
6 changed files with 138 additions and 51 deletions
|
@ -911,7 +911,7 @@ struct diveplan {
|
|||
short vpmb_conservatism;
|
||||
struct divedatapoint *dp;
|
||||
int eff_gflow, eff_gfhigh;
|
||||
unsigned int surface_interval;
|
||||
int surface_interval;
|
||||
};
|
||||
|
||||
struct divedatapoint *plan_add_segment(struct diveplan *diveplan, int duration, int depth, int cylinderid, int po2, bool entered);
|
||||
|
|
157
core/divelist.c
157
core/divelist.c
|
@ -11,7 +11,7 @@
|
|||
* void get_dive_gas(struct dive *dive, int *o2_p, int *he_p, int *o2low_p)
|
||||
* int total_weight(struct dive *dive)
|
||||
* int get_divenr(struct dive *dive)
|
||||
* double init_decompression(struct dive *dive)
|
||||
* int init_decompression(struct dive *dive)
|
||||
* void update_cylinder_related_info(struct dive *dive)
|
||||
* void dump_trip_list(void)
|
||||
* dive_trip_t *find_matching_trip(timestamp_t when)
|
||||
|
@ -367,92 +367,169 @@ int get_divesite_idx(struct dive_site *ds)
|
|||
static struct gasmix air = { .o2.permille = O2_IN_AIR, .he.permille = 0 };
|
||||
|
||||
/* take into account previous dives until there is a 48h gap between dives */
|
||||
/* return true if this is a repetitive dive */
|
||||
unsigned int init_decompression(struct dive *dive)
|
||||
/* return last surface time before this dive or dummy value of 48h */
|
||||
/* return negative surface time if dives are overlapping */
|
||||
int init_decompression(struct dive *dive)
|
||||
{
|
||||
int i, divenr = -1;
|
||||
unsigned int surface_time = 0;
|
||||
timestamp_t when, lasttime = 0, laststart = 0;
|
||||
int surface_time = 48 * 60 * 60;
|
||||
timestamp_t last_endtime = 0, last_starttime = 0;
|
||||
bool deco_init = false;
|
||||
double surface_pressure;
|
||||
|
||||
if (!dive)
|
||||
return false;
|
||||
|
||||
surface_pressure = get_surface_pressure_in_mbar(dive, true) / 1000.0;
|
||||
divenr = get_divenr(dive);
|
||||
when = dive->when;
|
||||
i = divenr;
|
||||
if (i < 0) {
|
||||
i = dive_table.nr - 1;
|
||||
while (i >= 0 && get_dive(i)->when > when)
|
||||
--i;
|
||||
i = divenr >= 0 ? divenr : dive_table.nr;
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
if (i >= 0 && i < dive_table.nr)
|
||||
printf("\n\n*** Init deco for dive #%d %d\n", i, get_dive(i)->number);
|
||||
else
|
||||
printf("\n\n*** Init deco 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 (dive->divetrip && pdive->divetrip != dive->divetrip) {
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
printf("No - other dive trip\n");
|
||||
#endif
|
||||
continue;
|
||||
if (!pdive || pdive->when >= when || dive_endtime(pdive) + 48 * 60 * 60 < when)
|
||||
}
|
||||
if (!pdive || pdive->when >= dive->when || dive_endtime(pdive) + 48 * 60 * 60 < last_starttime) {
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
printf("No\n");
|
||||
#endif
|
||||
break;
|
||||
/* For simultaneous dives, only consider the first */
|
||||
if (pdive->when == laststart)
|
||||
continue;
|
||||
lasttime = dive_endtime(pdive);
|
||||
}
|
||||
last_starttime = pdive->when;
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
printf("Yes\n");
|
||||
#endif
|
||||
}
|
||||
while (++i < (divenr >= 0 ? divenr : dive_table.nr)) {
|
||||
/* Walk forward an add dives and surface intervals to deco */
|
||||
while (++i < dive_table.nr) {
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
printf("Check if dive #%d %d will be really added to deco 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 (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)
|
||||
continue; /* This could be break if the divelist is always sorted */
|
||||
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
|
||||
|
||||
surface_pressure = get_surface_pressure_in_mbar(pdive, true) / 1000.0;
|
||||
/* Is it the first dive we add? */
|
||||
if (!deco_init) {
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
printf("Init deco\n");
|
||||
#endif
|
||||
clear_deco(surface_pressure);
|
||||
deco_init = true;
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
printf("Tissues after init:\n");
|
||||
dump_tissues();
|
||||
#endif
|
||||
}
|
||||
if (pdive->when > lasttime) {
|
||||
surface_time = pdive->when - lasttime;
|
||||
lasttime = dive_endtime(pdive);
|
||||
else {
|
||||
surface_time = pdive->when - last_endtime;
|
||||
if (surface_time < 0) {
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
printf("Exit because surface intervall is %d\n", surface_time);
|
||||
#endif
|
||||
return surface_time;
|
||||
}
|
||||
add_segment(surface_pressure, &air, surface_time, 0, dive, prefs.decosac);
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
printf("after surface intervall of %d:%02u\n", FRACTION(surface_time, 60));
|
||||
printf("Tissues after surface intervall of %d:%02u:\n", FRACTION(surface_time, 60));
|
||||
dump_tissues();
|
||||
#endif
|
||||
}
|
||||
|
||||
add_dive_to_deco(pdive);
|
||||
laststart = pdive->when;
|
||||
|
||||
last_starttime = pdive->when;
|
||||
last_endtime = dive_endtime(pdive);
|
||||
clear_vpmb_state();
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
printf("added dive #%d\n", pdive->number);
|
||||
dump_tissues();
|
||||
#endif
|
||||
}
|
||||
/* add the final surface time */
|
||||
if (lasttime && dive->when > lasttime) {
|
||||
surface_time = dive->when - lasttime;
|
||||
surface_pressure = get_surface_pressure_in_mbar(dive, true) / 1000.0;
|
||||
add_segment(surface_pressure, &air, surface_time, 0, dive, prefs.decosac);
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
printf("after surface intervall of %d:%02u\n", FRACTION(surface_time, 60));
|
||||
printf("Tissues after added dive #%d:\n", pdive->number);
|
||||
dump_tissues();
|
||||
#endif
|
||||
}
|
||||
|
||||
surface_pressure = get_surface_pressure_in_mbar(dive, true) / 1000.0;
|
||||
/* We don't have had a previous dive at all? */
|
||||
if (!deco_init) {
|
||||
surface_pressure = get_surface_pressure_in_mbar(dive, true) / 1000.0;
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
printf("Init deco\n");
|
||||
#endif
|
||||
clear_deco(surface_pressure);
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
printf("no previous dive\n");
|
||||
printf("Tissues after no previous dive, surface time set to 48h:\n");
|
||||
dump_tissues();
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
surface_time = dive->when - last_endtime;
|
||||
if (surface_time < 0) {
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
printf("Exit because surface intervall is %d\n", surface_time);
|
||||
#endif
|
||||
return surface_time;
|
||||
}
|
||||
add_segment(surface_pressure, &air, surface_time, 0, dive, prefs.decosac);
|
||||
#if DECO_CALC_DEBUG & 2
|
||||
printf("Tissues after surface intervall of %d:%02u:\n", FRACTION(surface_time, 60));
|
||||
dump_tissues();
|
||||
#endif
|
||||
}
|
||||
|
||||
// I do not dare to remove this call. We don't need the result but it might have side effects. Bummer.
|
||||
tissue_tolerance_calc(dive, surface_pressure);
|
||||
return surface_time;
|
||||
|
|
|
@ -15,7 +15,7 @@ extern void update_cylinder_related_info(struct dive *);
|
|||
extern void mark_divelist_changed(int);
|
||||
extern int unsaved_changes(void);
|
||||
extern void remove_autogen_trips(void);
|
||||
extern unsigned int init_decompression(struct dive *dive);
|
||||
extern int init_decompression(struct dive *dive);
|
||||
|
||||
/* divelist core logic functions */
|
||||
extern void process_dives(bool imported, bool prefer_imported);
|
||||
|
|
|
@ -127,7 +127,7 @@ void interpolate_transition(struct dive *dive, duration_t t0, duration_t t1, dep
|
|||
}
|
||||
|
||||
/* returns the tissue tolerance at the end of this (partial) dive */
|
||||
unsigned int tissue_at_end(struct dive *dive, struct deco_state **cached_datap)
|
||||
int tissue_at_end(struct dive *dive, struct deco_state **cached_datap)
|
||||
{
|
||||
struct divecomputer *dc;
|
||||
struct sample *sample, *psample;
|
||||
|
@ -135,7 +135,7 @@ unsigned int tissue_at_end(struct dive *dive, struct deco_state **cached_datap)
|
|||
depth_t lastdepth = {};
|
||||
duration_t t0 = {}, t1 = {};
|
||||
struct gasmix gas;
|
||||
unsigned int surface_interval = 0;
|
||||
int surface_interval = 0;
|
||||
|
||||
if (!dive)
|
||||
return 0;
|
||||
|
|
|
@ -85,7 +85,22 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
|
|||
|
||||
len = show_disclaimer ? snprintf(buffer, sz_buffer, "<div><b>%s</b><br></div>", disclaimer) : 0;
|
||||
|
||||
if (diveplan->surface_interval > 60) {
|
||||
if (diveplan->surface_interval < 0) {
|
||||
len += snprintf(buffer + len, sz_buffer - len, "<div><b>%s (%s) %s<br>",
|
||||
translate("gettextFromC", "Subsurface"),
|
||||
subsurface_canonical_version(),
|
||||
translate("gettextFromC", "dive plan</b> (Overlapping dives detected)"));
|
||||
dive->notes = strdup(buffer);
|
||||
free((void *)buffer);
|
||||
free((void *)temp);
|
||||
return;
|
||||
} else if (diveplan->surface_interval >= 48 * 60 *60) {
|
||||
len += snprintf(buffer + len, sz_buffer - len, "<div><b>%s (%s) %s %s</b><br>",
|
||||
translate("gettextFromC", "Subsurface"),
|
||||
subsurface_canonical_version(),
|
||||
translate("gettextFromC", "dive plan</b> created on"),
|
||||
get_current_date());
|
||||
} else {
|
||||
len += snprintf(buffer + len, sz_buffer - len, "<div><b>%s (%s) %s %d:%02d) %s %s<br>",
|
||||
translate("gettextFromC", "Subsurface"),
|
||||
subsurface_canonical_version(),
|
||||
|
@ -93,12 +108,6 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
|
|||
FRACTION(diveplan->surface_interval / 60, 60),
|
||||
translate("gettextFromC", "created on"),
|
||||
get_current_date());
|
||||
} else {
|
||||
len += snprintf(buffer + len, sz_buffer - len, "<div><b>%s (%s) %s %s</b><br>",
|
||||
translate("gettextFromC", "Subsurface"),
|
||||
subsurface_canonical_version(),
|
||||
translate("gettextFromC", "dive plan</b> created on"),
|
||||
get_current_date());
|
||||
}
|
||||
|
||||
if (prefs.display_variations)
|
||||
|
|
|
@ -1101,6 +1101,7 @@ void DivePlannerPointsModel::createPlan(bool replanCopy)
|
|||
copy_dive(&displayed_dive, current_dive);
|
||||
}
|
||||
mark_divelist_changed(true);
|
||||
sort_table(&dive_table);
|
||||
|
||||
// Remove and clean the diveplan, so we don't delete
|
||||
// the dive by mistake.
|
||||
|
|
Loading…
Reference in a new issue