[PATCH 2/3] Fix get_cylinder_index() gasmix comparisons

Linus Torvalds torvalds at linux-foundation.org
Thu Mar 28 10:16:31 PDT 2013


From: Linus Torvalds <torvalds at linux-foundation.org>
Date: Thu, 28 Mar 2013 09:56:32 -0700
Subject: [PATCH 2/3] Fix get_cylinder_index() gasmix comparisons

get_cylinder_index() looks up which cylinder to use based on the
gaschange event that describes the mix.  However, it was both buggy and
not very good.

It was buggy because it didn't understand about our air rules, and it
was not very good because it required an exact match (after rounding our
permille-based numbers to percent).

So fix it to use the right permille values, and look for a closest match
(using the normal sum-of-squares distance function - although I wonder
if we should consider helium percentages to be "more important" and give
them a stronger weight).

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

This fixes the Uemis profile display for the test-case of Dirk's two dives 
getting merged, where the Uemis and Petrel dive computers had different 
ideas of cylinder numbering.

The merging was indeed done correctly by the previous commit, but the 
gaschanges confused the profile code because it compared the mixes in the 
cylinders incorrectly against the gaschange event.

 dive.h    | 10 ++++++++++
 profile.c | 40 ++++++++++++++++++++++++----------------
 2 files changed, 34 insertions(+), 16 deletions(-)

diff --git a/dive.h b/dive.h
index 25cad4bfc210..7d08828a8a51 100644
--- a/dive.h
+++ b/dive.h
@@ -215,6 +215,16 @@ static inline int mbar_to_PSI(int mbar)
 	return to_PSI(p);
 }
 
+static inline int get_o2(const struct gasmix *mix)
+{
+	return mix->o2.permille ? : O2_IN_AIR;
+}
+
+static inline int get_he(const struct gasmix *mix)
+{
+	return mix->he.permille;
+}
+
 static inline gboolean is_air(int o2, int he)
 {
 	return (he == 0) && (o2 == 0 || ((o2 >= O2_IN_AIR - 1) && (o2 <= O2_IN_AIR + 1)));
diff --git a/profile.c b/profile.c
index bcba6c84054e..6be4b13ef16c 100644
--- a/profile.c
+++ b/profile.c
@@ -1509,28 +1509,36 @@ static void fill_missing_tank_pressures(struct dive *dive, struct plot_info *pi,
 static int get_cylinder_index(struct dive *dive, struct event *ev)
 {
 	int i;
+	int best = 0, score = INT_MAX;
+	int target_o2, target_he;
 
 	/*
-	 * Try to find a cylinder that matches the O2 percentage
-	 * in the gas change event 'value' field.
-	 *
-	 * Crazy suunto gas change events. We really should do
-	 * this in libdivecomputer or something.
-	 *
-	 * There are two different gas change events that can get
-	 * us here - GASCHANGE2 has the He value in the high 16
-	 * bits; looking at the possible values we can actually
-	 * handle them with the same code since the high 16 bits
-	 * will be 0 with the GASCHANGE event - and that means no He
+	 * Crazy gas change events give us odd encoded o2/he in percent.
+	 * Decode into our internal permille format.
+	 */
+	target_o2 = (ev->value & 0xFFFF) * 10;
+	target_he = (ev->value >> 16) * 10;
+
+	/*
+	 * Try to find a cylinder that best matches the target gas
+	 * mix.
 	 */
 	for (i = 0; i < MAX_CYLINDERS; i++) {
 		cylinder_t *cyl = dive->cylinder+i;
-		int o2 = (cyl->gasmix.o2.permille + 5) / 10;
-		int he = (cyl->gasmix.he.permille + 5) / 10;
-		if (o2 == (ev->value & 0xFFFF) && he == (ev->value >> 16))
-			return i;
+		int delta_o2, delta_he, distance;
+
+		if (cylinder_nodata(cyl))
+			continue;
+
+		delta_o2 = get_o2(&cyl->gasmix) - target_o2;
+		delta_he = get_he(&cyl->gasmix) - target_he;
+		distance = delta_o2 * delta_o2 + delta_he * delta_he;
+		if (distance >= score)
+			continue;
+		score = distance;
+		best = i;
 	}
-	return 0;
+	return best;
 }
 
 struct event *get_next_event(struct event *event, char *name)
-- 
1.8.2.230.g2bba2f0



More information about the subsurface mailing list