aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dive.c114
-rw-r--r--dive.h2
-rw-r--r--qt-ui/divelistview.cpp5
3 files changed, 99 insertions, 22 deletions
diff --git a/dive.c b/dive.c
index 10ce63859..0248888a3 100644
--- a/dive.c
+++ b/dive.c
@@ -2743,28 +2743,48 @@ int count_dives_with_suit(const char *suit)
return counter;
}
-
+/*
+ * Merging two dives can be subtle, because there's two different ways
+ * of merging:
+ *
+ * (a) two distinctly _different_ dives that have the same dive computer
+ * are merged into one longer dive, because the user asked for it
+ * in the divelist.
+ *
+ * Because this case is with teh same dive computer, we *know* the
+ * two must have a different start time, and "offset" is the relative
+ * time difference between the two.
+ *
+ * (a) two different dive computers that we migth want to merge into
+ * one single dive with multiple dive computers.
+ *
+ * This is the "try_to_merge()" case, which will have offset == 0,
+ * even if the dive times migth be different.
+ */
struct dive *merge_dives(struct dive *a, struct dive *b, int offset, bool prefer_downloaded)
{
struct dive *res = alloc_dive();
struct dive *dl = NULL;
- /* Aim for newly downloaded dives to be 'b' (keep old dive data first) */
- if (a->downloaded && !b->downloaded) {
- struct dive *tmp = a;
- a = b;
- b = tmp;
+ if (offset) {
+ /*
+ * If "likely_same_dive()" returns true, that means that
+ * it is *not* the same dive computer, and we do not want
+ * to try to turn it into a single longer dive. So we'd
+ * join them as two separate dive computers at zero offset.
+ */
+ if (likely_same_dive(a, b))
+ offset = 0;
+ } else {
+ /* Aim for newly downloaded dives to be 'b' (keep old dive data first) */
+ if (a->downloaded && !b->downloaded) {
+ struct dive *tmp = a;
+ a = b;
+ b = tmp;
+ }
+ if (prefer_downloaded && b->downloaded)
+ dl = b;
}
- if (prefer_downloaded && b->downloaded)
- dl = b;
-
- /*
- * Did the user ask us to merge dives in the dive list?
- * We may want to just join the dive computers, not try to
- * interleave them at some offset.
- */
- if (offset && likely_same_dive(a, b))
- offset = 0;
res->when = dl ? dl->when : a->when;
res->selected = a->selected || b->selected;
@@ -2793,6 +2813,56 @@ struct dive *merge_dives(struct dive *a, struct dive *b, int offset, bool prefer
return res;
}
+/*
+ * "dc_maxtime()" is how much total time this dive computer
+ * has for this dive. Note that it can differ from "duration"
+ * if there are surface events in the middle.
+ *
+ * Still, we do ignore all but the last surface samples from the
+ * end, because some divecomputers just generate lots of them.
+ */
+static inline int dc_totaltime(const struct divecomputer *dc)
+{
+ int time = dc->duration.seconds;
+ int nr = dc->samples;
+
+ while (nr--) {
+ struct sample *s = dc->sample + nr;
+ time = s->time.seconds;
+ if (s->depth.mm >= SURFACE_THRESHOLD)
+ break;
+ }
+ return time;
+}
+
+/*
+ * The end of a dive is actually not trivial, because "duration"
+ * is not the duration until the end, but the time we spend under
+ * water, which can be very different if there are surface events
+ * during the dive.
+ *
+ * So walk the dive computers, looking for the longest actual
+ * time in the samples (and just default to the dive duration if
+ * there are no samples).
+ */
+static inline int dive_totaltime(const struct dive *dive)
+{
+ int time = dive->duration.seconds;
+ const struct divecomputer *dc;
+
+ for_each_dc(dive, dc) {
+ int dc_time = dc_totaltime(dc);
+ if (dc_time > time)
+ time = dc_time;
+ }
+ return time;
+}
+
+timestamp_t dive_endtime(const struct dive *dive)
+{
+ return dive->when + dive_totaltime(dive);
+}
+
struct dive *find_dive_including(timestamp_t when)
{
int i;
@@ -2802,7 +2872,7 @@ struct dive *find_dive_including(timestamp_t when)
* also we always use the duration from the first divecomputer
* could this ever be a problem? */
for_each_dive (i, dive) {
- if (dive->when <= when && when <= dive->when + dive->duration.seconds)
+ if (dive->when <= when && when <= dive_endtime(dive))
return dive;
}
return NULL;
@@ -2810,12 +2880,16 @@ struct dive *find_dive_including(timestamp_t when)
bool time_during_dive_with_offset(struct dive *dive, timestamp_t when, timestamp_t offset)
{
- return dive->when - offset <= when && when <= dive->when + dive->duration.seconds + offset;
+ timestamp_t start = dive->when;
+ timestamp_t end = dive_endtime(dive);
+ return start - offset <= when && when <= end + offset;
}
bool dive_within_time_range(struct dive *dive, timestamp_t when, timestamp_t offset)
{
- return when - offset <= dive->when && dive->when + dive->duration.seconds <= when + offset;
+ timestamp_t start = dive->when;
+ timestamp_t end = dive_endtime(dive);
+ return when - offset <= start && end <= when + offset;
}
/* find the n-th dive that is part of a group of dives within the offset around 'when'.
@@ -2970,7 +3044,7 @@ bool dive_check_picture_time(struct dive *d, int shift_time, timestamp_t timesta
offset_t offset;
if (timestamp) {
offset.seconds = timestamp - d->when + shift_time;
- if (offset.seconds > -D30MIN && offset.seconds < (int)d->duration.seconds + D30MIN) {
+ if (offset.seconds > -D30MIN && offset.seconds < dive_totaltime(d) + D30MIN) {
// this picture belongs to this dive
return true;
}
diff --git a/dive.h b/dive.h
index 4eb44cfc9..3bcc7b0e2 100644
--- a/dive.h
+++ b/dive.h
@@ -562,6 +562,8 @@ static inline struct divecomputer *get_dive_dc(struct dive *dive, int nr)
return dc;
}
+extern timestamp_t dive_endtime(const struct dive *dive);
+
extern void make_first_dc(void);
extern int count_divecomputers(void);
extern void delete_current_divecomputer(void);
diff --git a/qt-ui/divelistview.cpp b/qt-ui/divelistview.cpp
index 2ee5f5dcd..39eab9c7a 100644
--- a/qt-ui/divelistview.cpp
+++ b/qt-ui/divelistview.cpp
@@ -22,6 +22,7 @@
#include "divelistview.h"
#include "divepicturemodel.h"
#include "metrics.h"
+#include "helpers.h"
// # Date Rtg Dpth Dur Tmp Wght Suit Cyl Gas SAC OTU CNS Loc
static int defaultWidth[] = { 70, 140, 90, 50, 50, 50, 50, 70, 50, 50, 70, 50, 50, 500};
@@ -575,12 +576,12 @@ static bool can_merge(const struct dive *a, const struct dive *b, enum asked_use
if (a->when > b->when)
return false;
/* Don't merge dives if there's more than half an hour between them */
- if (a->when + a->duration.seconds + 30 * 60 < b->when) {
+ if (dive_endtime(a) + 30 * 60 < b->when) {
if (*have_asked == NOTYET) {
if (QMessageBox::warning(MainWindow::instance(),
MainWindow::instance()->tr("Warning"),
MainWindow::instance()->tr("Trying to merge dives with %1min interval in between").arg(
- (b->when - a->when - a->duration.seconds) / 60),
+ (b->when - dive_endtime(a)) / 60),
QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) {
*have_asked = DONTMERGE;
return false;