[PATCH 1/2] Use dive computer model/ID when trying to merge dives

Linus Torvalds torvalds at linux-foundation.org
Sun Dec 16 11:13:11 PST 2012


From: Linus Torvalds <torvalds at linux-foundation.org>
Date: Sun, 16 Dec 2012 10:55:58 -0800
Subject: [PATCH 1/2] Use dive computer model/ID when trying to merge dives

If we havd divecomputer model and dive ID information available, use
that to match existing dives when trying to merge them.

Otherwise fall back to the fuzzy time-based merging logic.

Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
---

This seems to do the right thing. Not heavily tested, though, so please 
read through the logic and see if it all looks sane..

 dive.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
 dive.h |  3 +++
 2 files changed, 67 insertions(+), 12 deletions(-)

diff --git a/dive.c b/dive.c
index fce6b1a35ed1..2a5b17580c30 100644
--- a/dive.c
+++ b/dive.c
@@ -1110,19 +1110,64 @@ static int similar(unsigned long a, unsigned long b, unsigned long expected)
 	return 0;
 }
 
-static int same_dive_computer(struct dive *a, struct dive *b)
+/*
+ * Match two dive computer entries against each other, and
+ * tell if it's the same dive. Return 0 if "don't know",
+ * positive for "same dive" and negative for "definitely
+ * not the same dive"
+ */
+int match_one_dc(struct divecomputer *a, struct divecomputer *b)
 {
-	/* No model info in one or the other? Assume they're the same */
-	if (!a->dc.model || !b->dc.model)
-		return 1;
-	if (strcasecmp(a->dc.model, b->dc.model))
+	/* Not same model? Don't know if matching.. */
+	if (!a->model || !b->model)
+		return 0;
+	if (strcasecmp(a->model, b->model))
 		return 0;
-	/* No device ID? Assume same.. */
-	if (!a->dc.deviceid || !b->dc.deviceid)
-		return 1;
+
+	/* Different device ID's? Don't know */
+	if (a->deviceid != b->deviceid)
+		return 0;
+
+	/* Do we have dive IDs? */
+	if (!a->diveid || !b->diveid)
+		return 0;
+
+	/*
+	 * If they have different dive ID's on the same
+	 * dive computer, that's a definite "same or not"
+	 */
+	return a->diveid == b->diveid ? 1 : -1;
+}
+
+/*
+ * Match every dive computer against each other to see if
+ * we have a matching dive.
+ *
+ * Return values:
+ *  -1 for "is definitely *NOT* the same dive"
+ *   0 for "don't know"
+ *   1 for "is definitely the same dive"
+ */
+static int match_dc_dive(struct divecomputer *a, struct divecomputer *b)
+{
+	do {
+		struct divecomputer *tmp = b;
+		do {
+			int match = match_one_dc(a, tmp);
+			if (match)
+				return match;
+			tmp = tmp->next;
+		} while (tmp);
+		a = a->next;
+	} while (a);
 	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
  * look like they are the same dive?
@@ -1154,7 +1199,7 @@ static int same_dive_computer(struct dive *a, struct dive *b)
  */
 static int likely_same_dive(struct dive *a, struct dive *b)
 {
-	int fuzz;
+	int fuzz, match;
 
 	/*
 	 * Do some basic sanity testing of the values we
@@ -1165,11 +1210,18 @@ static int likely_same_dive(struct dive *a, struct dive *b)
 	    !similar(a->duration.seconds, b->duration.seconds, 5*60))
 		return 0;
 
+	/* See if we can get an exact match on the dive computer */
+	match = match_dc_dive(&a->dc, &b->dc);
+	if (match)
+		return match > 0;
+
 	/*
-	 * Allow a minute difference by default (minute rounding etc),
-	 * and more if the dive computers are clearly different.
+	 * Allow a time difference due to dive computer time
+	 * setting etc. Check if they overlap.
 	 */
-	fuzz = same_dive_computer(a, b) ? 60 : 5*60;
+	fuzz = max_time(a->duration, b->duration) / 2;
+	if (fuzz < 60)
+		fuzz = 60;
 
 	return ((a->when <= b->when + fuzz) && (a->when >= b->when - fuzz));
 }
diff --git a/dive.h b/dive.h
index d504790ae49c..3d8fa6addb39 100644
--- a/dive.h
+++ b/dive.h
@@ -448,6 +448,9 @@ static inline struct dive *get_dive_by_diveid(int diveid, int deviceid)
 	return NULL;
 }
 
+/* Check if two dive computer entries are the exact same dive (-1=no/0=maybe/1=yes) */
+extern int match_one_dc(struct divecomputer *a, struct divecomputer *b);
+
 /*
  * Iterate over each dive, with the first parameter being the index
  * iterator variable, and the second one being the dive one.
-- 
1.8.0.dirty



More information about the subsurface mailing list