Duration of a dive is the maximum duration from all divecomputers

So far we always used the duration of the first divecomputer. The same fix
needs to be done for some of the other calculations that always use the
first divecomputer.

This commit also removes some obsolete code from the webservice merging.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Dirk Hohndel 2013-02-08 17:48:07 +11:00
parent 5692131a79
commit 9846ba9e94
5 changed files with 48 additions and 43 deletions

32
dive.c
View file

@ -219,6 +219,17 @@ static void update_duration(duration_t *duration, int new)
duration->seconds = new; duration->seconds = new;
} }
int get_duration_in_sec(struct dive *dive)
{
int duration;
struct divecomputer *dc = &dive->dc;
do {
duration = dc->duration.seconds;
dc = dc->next;
} while (dc);
return duration;
}
static void update_temperature(temperature_t *temperature, int new) static void update_temperature(temperature_t *temperature, int new)
{ {
if (new) { if (new) {
@ -413,6 +424,7 @@ static struct event *find_previous_event(struct divecomputer *dc, struct event *
return previous; return previous;
} }
/* right now this only operates on the first divecomputer */
struct dive *fixup_dive(struct dive *dive) struct dive *fixup_dive(struct dive *dive)
{ {
int i,j; int i,j;
@ -1182,11 +1194,6 @@ static int match_dc_dive(struct divecomputer *a, struct divecomputer *b)
return 0; return 0;
} }
static int max_time(duration_t a, duration_t b)
{
return a.seconds > b.seconds ? a.seconds : b.seconds;
}
/* /*
* Do we want to automatically try to merge two dives that * Do we want to automatically try to merge two dives that
* look like they are the same dive? * look like they are the same dive?
@ -1224,20 +1231,13 @@ static int likely_same_dive(struct dive *a, struct dive *b)
if (a->divetrip && b->divetrip && a->divetrip != b->divetrip) if (a->divetrip && b->divetrip && a->divetrip != b->divetrip)
return 0; return 0;
/* if one of the dives has no depth and duration this could be
* a location marker from the webservice (in this situation it
* is valid to only check the first dc structure as we know that
* a location marker will only ever have one of those structures) */
if ((!a->dc.maxdepth.mm && !a->dc.duration.seconds) ||
(!b->dc.maxdepth.mm && !b->dc.duration.seconds))
return ((a->when <= b->when + fuzz) && (a->when >= b->when - fuzz));
/* /*
* Do some basic sanity testing of the values we * Do some basic sanity testing of the values we
* have filled in during 'fixup_dive()' * have filled in during 'fixup_dive()'
*/ */
if (!similar(a->dc.maxdepth.mm, b->dc.maxdepth.mm, 1000) || if (!similar(a->dc.maxdepth.mm, b->dc.maxdepth.mm, 1000) ||
!similar(a->dc.meandepth.mm, b->dc.meandepth.mm, 1000) || !similar(a->dc.meandepth.mm, b->dc.meandepth.mm, 1000) ||
!similar(a->dc.duration.seconds, b->dc.duration.seconds, 5*60)) !similar(get_duration_in_sec(a), get_duration_in_sec(b), 5*60))
return 0; return 0;
/* See if we can get an exact match on the dive computer */ /* See if we can get an exact match on the dive computer */
@ -1249,7 +1249,7 @@ static int likely_same_dive(struct dive *a, struct dive *b)
* Allow a time difference due to dive computer time * Allow a time difference due to dive computer time
* setting etc. Check if they overlap. * setting etc. Check if they overlap.
*/ */
fuzz = max_time(a->dc.duration, b->dc.duration) / 2; fuzz = MAX(get_duration_in_sec(a), get_duration_in_sec(b)) / 2;
if (fuzz < 60) if (fuzz < 60)
fuzz = 60; fuzz = 60;
@ -1537,7 +1537,7 @@ struct dive *find_dive_including(timestamp_t when)
* also we always use the duration from the first divecomputer * also we always use the duration from the first divecomputer
* could this ever be a problem? */ * could this ever be a problem? */
for_each_dive(i, dive) { for_each_dive(i, dive) {
if (dive->when <= when && when <= dive->when + dive->dc.duration.seconds) if (dive->when <= when && when <= dive->when + get_duration_in_sec(dive))
return dive; return dive;
} }
return NULL; return NULL;
@ -1545,7 +1545,7 @@ struct dive *find_dive_including(timestamp_t when)
gboolean dive_within_time_range(struct dive *dive, timestamp_t when, timestamp_t offset) gboolean dive_within_time_range(struct dive *dive, timestamp_t when, timestamp_t offset)
{ {
return when - offset <= dive->when && dive->when + dive->dc.duration.seconds <= when + offset; return when - offset <= dive->when && dive->when + get_duration_in_sec(dive) <= when + offset;
} }
/* find the n-th dive that is part of a group of dives within the offset around 'when'. /* find the n-th dive that is part of a group of dives within the offset around 'when'.

2
dive.h
View file

@ -530,7 +530,7 @@ extern void report_dives(gboolean imported, gboolean prefer_imported);
extern struct dive *fixup_dive(struct dive *dive); extern struct dive *fixup_dive(struct dive *dive);
extern struct dive *merge_dives(struct dive *a, struct dive *b, int offset, gboolean prefer_downloaded); extern struct dive *merge_dives(struct dive *a, struct dive *b, int offset, gboolean prefer_downloaded);
extern struct dive *try_to_merge(struct dive *a, struct dive *b, gboolean prefer_downloaded); extern struct dive *try_to_merge(struct dive *a, struct dive *b, gboolean prefer_downloaded);
extern int get_duration_in_sec(struct dive *dive);
extern void renumber_dives(int nr); extern void renumber_dives(int nr);
extern void add_gas_switch_event(struct dive *dive, struct divecomputer *dc, int time, int idx); extern void add_gas_switch_event(struct dive *dive, struct divecomputer *dc, int time, int idx);

View file

@ -638,11 +638,12 @@ static int active_o2(struct dive *dive, struct divecomputer *dc, duration_t time
return o2permille; return o2permille;
} }
/* calculate OTU for a dive */ /* calculate OTU for a dive - this only takes the first diveomputer into account */
static int calculate_otu(struct dive *dive, struct divecomputer *dc) static int calculate_otu(struct dive *dive)
{ {
int i; int i;
double otu = 0.0; double otu = 0.0;
struct divecomputer *dc = &dive->dc;
for (i = 1; i < dc->samples; i++) { for (i = 1; i < dc->samples; i++) {
int t; int t;
@ -688,19 +689,22 @@ static double calculate_airuse(struct dive *dive)
return airuse; return airuse;
} }
static int calculate_sac(struct dive *dive, struct divecomputer *dc) /* this only uses the first divecomputer to calculate the SAC rate */
static int calculate_sac(struct dive *dive)
{ {
struct divecomputer *dc = &dive->dc;
double airuse, pressure, sac; double airuse, pressure, sac;
int duration, i; int duration, i;
airuse = calculate_airuse(dive); airuse = calculate_airuse(dive);
if (!airuse) if (!airuse)
return 0; return 0;
if (!dive->dc.duration.seconds) duration = dc->duration.seconds;
if (!duration)
return 0; return 0;
/* find and eliminate long surface intervals */ /* find and eliminate long surface intervals */
duration = dive->dc.duration.seconds;
for (i = 0; i < dc->samples; i++) { for (i = 0; i < dc->samples; i++) {
if (dc->sample[i].depth.mm < 100) { /* less than 10cm */ if (dc->sample[i].depth.mm < 100) { /* less than 10cm */
int end = i + 1; int end = i + 1;
@ -776,10 +780,10 @@ double init_decompression(struct dive *dive)
* for how far back we need to go */ * for how far back we need to go */
if (dive->divetrip && pdive->divetrip != dive->divetrip) if (dive->divetrip && pdive->divetrip != dive->divetrip)
continue; continue;
if (!pdive || pdive->when > when || pdive->when + pdive->dc.duration.seconds + 48 * 60 * 60 < when) if (!pdive || pdive->when > when || pdive->when + get_duration_in_sec(pdive) + 48 * 60 * 60 < when)
break; break;
when = pdive->when; when = pdive->when;
lasttime = when + pdive->dc.duration.seconds; lasttime = when + get_duration_in_sec(pdive);
} }
while (++i < divenr) { while (++i < divenr) {
struct dive* pdive = get_dive(i); struct dive* pdive = get_dive(i);
@ -801,7 +805,7 @@ double init_decompression(struct dive *dive)
#endif #endif
if (pdive->when > lasttime) { if (pdive->when > lasttime) {
surface_time = pdive->when - lasttime; surface_time = pdive->when - lasttime;
lasttime = pdive->when + pdive->dc.duration.seconds; lasttime = pdive->when + get_duration_in_sec(pdive);
tissue_tolerance = add_segment(surface_pressure, &air, surface_time, 0, dive); tissue_tolerance = add_segment(surface_pressure, &air, surface_time, 0, dive);
#if DECO_CALC_DEBUG & 2 #if DECO_CALC_DEBUG & 2
printf("after surface intervall of %d:%02u\n", FRACTION(surface_time,60)); printf("after surface intervall of %d:%02u\n", FRACTION(surface_time,60));
@ -833,8 +837,8 @@ double init_decompression(struct dive *dive)
void update_cylinder_related_info(struct dive *dive) void update_cylinder_related_info(struct dive *dive)
{ {
if (dive != NULL) { if (dive != NULL) {
dive->sac = calculate_sac(dive, &dive->dc); dive->sac = calculate_sac(dive);
dive->otu = calculate_otu(dive, &dive->dc); dive->otu = calculate_otu(dive);
} }
} }
@ -1314,7 +1318,7 @@ static void fill_dive_list(void)
DIVE_NR, dive->number, DIVE_NR, dive->number,
DIVE_DATE, dive->when, DIVE_DATE, dive->when,
DIVE_DEPTH, dive->dc.maxdepth, DIVE_DEPTH, dive->dc.maxdepth,
DIVE_DURATION, dive->dc.duration.seconds, DIVE_DURATION, get_duration_in_sec(dive),
DIVE_LOCATION, dive->location, DIVE_LOCATION, dive->location,
DIVE_LOC_ICON, icon, DIVE_LOC_ICON, icon,
DIVE_RATING, dive->rating, DIVE_RATING, dive->rating,
@ -1327,7 +1331,7 @@ static void fill_dive_list(void)
DIVE_NR, dive->number, DIVE_NR, dive->number,
DIVE_DATE, dive->when, DIVE_DATE, dive->when,
DIVE_DEPTH, dive->dc.maxdepth, DIVE_DEPTH, dive->dc.maxdepth,
DIVE_DURATION, dive->dc.duration.seconds, DIVE_DURATION, get_duration_in_sec(dive),
DIVE_LOCATION, dive->location, DIVE_LOCATION, dive->location,
DIVE_LOC_ICON, icon, DIVE_LOC_ICON, icon,
DIVE_RATING, dive->rating, DIVE_RATING, dive->rating,
@ -2357,7 +2361,7 @@ static void add_dive_merge_label(int idx, GtkMenuShell *menu)
return; return;
/* .. and if the surface interval is excessive, you must be kidding us */ /* .. and if the surface interval is excessive, you must be kidding us */
if (b->when > a->when + a->dc.duration.seconds + 30*60) if (b->when > a->when + get_duration_in_sec(a) + 30*60)
return; return;
/* If so, we can add a "merge dive" menu entry */ /* If so, we can add a "merge dive" menu entry */

2
info.c
View file

@ -1145,7 +1145,7 @@ static timestamp_t dive_time_widget(struct dive *dive)
*/ */
if (amount_selected == 1) { if (amount_selected == 1) {
timestamp_t when = current_dive->when; timestamp_t when = current_dive->when;
when += current_dive->dc.duration.seconds; when += get_duration_in_sec(current_dive);
when += 60*60; when += 60*60;
utc_mkdate(when, &tm); utc_mkdate(when, &tm);
time = &tm; time = &tm;

View file

@ -135,13 +135,14 @@ static void process_temperatures(struct dive *dp, stats_t *stats)
static void process_dive(struct dive *dp, stats_t *stats) static void process_dive(struct dive *dp, stats_t *stats)
{ {
int old_tt, sac_time = 0; int old_tt, sac_time = 0;
int duration = get_duration_in_sec(dp);
old_tt = stats->total_time.seconds; old_tt = stats->total_time.seconds;
stats->total_time.seconds += dp->dc.duration.seconds; stats->total_time.seconds += duration;
if (dp->dc.duration.seconds > stats->longest_time.seconds) if (duration > stats->longest_time.seconds)
stats->longest_time.seconds = dp->dc.duration.seconds; stats->longest_time.seconds = duration;
if (stats->shortest_time.seconds == 0 || dp->dc.duration.seconds < stats->shortest_time.seconds) if (stats->shortest_time.seconds == 0 || duration < stats->shortest_time.seconds)
stats->shortest_time.seconds = dp->dc.duration.seconds; stats->shortest_time.seconds = duration;
if (dp->dc.maxdepth.mm > stats->max_depth.mm) if (dp->dc.maxdepth.mm > stats->max_depth.mm)
stats->max_depth.mm = dp->dc.maxdepth.mm; stats->max_depth.mm = dp->dc.maxdepth.mm;
if (stats->min_depth.mm == 0 || dp->dc.maxdepth.mm < stats->min_depth.mm) if (stats->min_depth.mm == 0 || dp->dc.maxdepth.mm < stats->min_depth.mm)
@ -150,14 +151,14 @@ static void process_dive(struct dive *dp, stats_t *stats)
process_temperatures(dp, stats); process_temperatures(dp, stats);
/* Maybe we should drop zero-duration dives */ /* Maybe we should drop zero-duration dives */
if (!dp->dc.duration.seconds) if (!duration)
return; return;
stats->avg_depth.mm = (1.0 * old_tt * stats->avg_depth.mm + stats->avg_depth.mm = (1.0 * old_tt * stats->avg_depth.mm +
dp->dc.duration.seconds * dp->dc.meandepth.mm) / stats->total_time.seconds; duration * dp->dc.meandepth.mm) / stats->total_time.seconds;
if (dp->sac > 2800) { /* less than .1 cuft/min (2800ml/min) is bogus */ if (dp->sac > 2800) { /* less than .1 cuft/min (2800ml/min) is bogus */
sac_time = stats->total_sac_time + dp->dc.duration.seconds; sac_time = stats->total_sac_time + duration;
stats->avg_sac.mliter = (1.0 * stats->total_sac_time * stats->avg_sac.mliter + stats->avg_sac.mliter = (1.0 * stats->total_sac_time * stats->avg_sac.mliter +
dp->dc.duration.seconds * dp->sac) / sac_time ; duration * dp->sac) / sac_time ;
if (dp->sac > stats->max_sac.mliter) if (dp->sac > stats->max_sac.mliter)
stats->max_sac.mliter = dp->sac; stats->max_sac.mliter = dp->sac;
if (stats->min_sac.mliter == 0 || dp->sac < stats->min_sac.mliter) if (stats->min_sac.mliter == 0 || dp->sac < stats->min_sac.mliter)
@ -421,7 +422,7 @@ static void process_all_dives(struct dive *dive, struct dive **prev_dive)
*prev_dive = NULL; *prev_dive = NULL;
memset(&stats, 0, sizeof(stats)); memset(&stats, 0, sizeof(stats));
if (dive_table.nr > 0) { if (dive_table.nr > 0) {
stats.shortest_time.seconds = dive_table.dives[0]->dc.duration.seconds; stats.shortest_time.seconds = get_duration_in_sec(dive_table.dives[0]);
stats.min_depth.mm = dive_table.dives[0]->dc.maxdepth.mm; stats.min_depth.mm = dive_table.dives[0]->dc.maxdepth.mm;
stats.selection_size = dive_table.nr; stats.selection_size = dive_table.nr;
} }
@ -555,10 +556,10 @@ static void show_single_dive_stats(struct dive *dive)
tm.tm_hour, tm.tm_min); tm.tm_hour, tm.tm_min);
set_label(single_w.date, buf); set_label(single_w.date, buf);
set_label(single_w.dive_time, _("%d min"), (dive->dc.duration.seconds + 30) / 60); set_label(single_w.dive_time, _("%d min"), (get_duration_in_sec(dive) + 30) / 60);
if (prev_dive) if (prev_dive)
set_label(single_w.surf_intv, set_label(single_w.surf_intv,
get_time_string(dive->when - (prev_dive->when + prev_dive->dc.duration.seconds), 4)); get_time_string(dive->when - (prev_dive->when + get_duration_in_sec(prev_dive)), 4));
else else
set_label(single_w.surf_intv, _("unknown")); set_label(single_w.surf_intv, _("unknown"));
value = get_depth_units(dive->dc.maxdepth.mm, &decimals, &unit); value = get_depth_units(dive->dc.maxdepth.mm, &decimals, &unit);