[FIXED PATCH] Don't show a SAC-rate of "0.00cuft/min"

Linus Torvalds torvalds at linux-foundation.org
Tue Jul 29 16:18:48 PDT 2014


When we have no volume of has used, that doesn't actually mean you aren't
breathing. It means that that cylinder doesn't have pressure information
or perhaps wasn't used.

Showing it as "0.00cuft/min" (or liter/min) is just completely bogus, and
actively visually misleading. Leave it empty.

This showed up both in the divelist, and in the the dive statistics page.
The dive statistics case had a special case for "unknown", but only for
the first gas. I don't think that was actually all that sane, and the
logic was really odd - if you had gases that weren't used (or pressures
not known) intermixed with gases you *did* have pressure for, the
statistics thing did odd/wrong things.

This makes all the cylinders act the same way, leaving unknown gas use
(and thus SAC) just empty for that gas.

It also fixes the SAC calculation case where we don't have real samples, 
and the profile is a fake profile - possibly with gas changes in between 
the fake points. We now make the SAC calculations match what we show - 
which is admittedly not at all necessarily what the dive was, but at 
least we're consistent.

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

It turns out that the whole statistics gas view was completely broken, 
which is why it took me a while to get the fixed patch out.

The reason the original patch was broken was that the statistics window 
did the SAC string and used gas calculations on its own, but then used an 
external function (get_gaslist()) to generate the string of used gases. 
And the logic didn't really match. 

This gets rid of that "get_gaslist()" function that was _only_ used for 
this, and instead generates the list of used gases in the same loop (and 
using the same inclusion logic) as the list of SAC-rates and gas 
volume usage. So now everything lines up.

This *also* fixes the per_cylinder_mean_depth() function for when you have 
cylinder change events, but no actual samples. We'd *show* that in the 
dive profile window, and it confused the heck out of me when we then 
wouldn't show any gas use - even though we clearly did have actual gas use 
information. And it was because per_cylinder_mean_depth() wouldn't fill in 
any of the mean depth information, because it didn't find any samples in 
the profile (because there are none in the dive).

Whatever. The patch is a bit larger, but I really do think it makes more 
sense. And I did test it under many more circumstances, and it gave sane 
results for all of them.

And yeah, I do realize that this is unlikely to be 4.2 material.

 dive.c            | 17 ++++++++++++++++-
 dive.h            |  1 -
 qt-ui/maintab.cpp | 30 ++++++++++++++++--------------
 qt-ui/models.cpp  |  2 ++
 statistics.c      | 27 ---------------------------
 5 files changed, 34 insertions(+), 43 deletions(-)

diff --git a/dive.c b/dive.c
index 863029cbf077..610789bdb897 100644
--- a/dive.c
+++ b/dive.c
@@ -7,6 +7,7 @@
 #include "gettext.h"
 #include "dive.h"
 #include "libdivecomputer.h"
+#include "device.h"
 
 /* one could argue about the best place to have this variable -
  * it's used in the UI, but it seems to make the most sense to have it
@@ -586,14 +587,28 @@ void per_cylinder_mean_depth(struct dive *dive, struct divecomputer *dc, int *me
 		duration[0] = dc->duration.seconds;
 		return;
 	}
+	if (!dc->samples)
+		dc = fake_dc(dc);
 	for (i = 0; i < dc->samples; i++) {
 		struct sample *sample = dc->sample + i;
 		int time = sample->time.seconds;
 		int depth = sample->depth.mm;
-		if (ev && time >= ev->time.seconds) {
+
+		/* Make sure to move the event past 'lasttime' */
+		while (ev && lasttime >= ev->time.seconds) {
 			idx = get_cylinder_index(dive, ev);
 			ev = get_next_event(ev->next, "gaschange");
 		}
+
+		/* Do we need to fake a midway sample at an event? */
+		if (ev && time > ev->time.seconds) {
+			int newtime = ev->time.seconds;
+			int newdepth = interpolate(lastdepth, depth, newtime - lasttime, time - lasttime);
+
+			time = newtime;
+			depth = newdepth;
+			i--;
+		}
 		/* We ignore segments at the surface */
 		if (depth > SURFACE_THRESHOLD || lastdepth > SURFACE_THRESHOLD) {
 			duration[idx] += time - lasttime;
diff --git a/dive.h b/dive.h
index 204cb2fee33f..855a9b99f168 100644
--- a/dive.h
+++ b/dive.h
@@ -116,7 +116,6 @@ static inline int get_he(const struct gasmix *mix)
 
 extern void sanitize_gasmix(struct gasmix *mix);
 extern int gasmix_distance(const struct gasmix *a, const struct gasmix *b);
-extern struct gasmix *get_gasmix_from_event(struct event *ev);
 
 static inline bool gasmix_is_air(const struct gasmix *gasmix)
 {
diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp
index bf108a9c170d..3ff0d6ef882d 100644
--- a/qt-ui/maintab.cpp
+++ b/qt-ui/maintab.cpp
@@ -462,28 +462,30 @@ void MainTab::updateDiveInfo(bool clear)
 		ui.airTemperatureText->setText(get_temperature_string(displayed_dive.airtemp, true));
 		volume_t gases[MAX_CYLINDERS] = {};
 		get_gas_used(&displayed_dive, gases);
-		QString volumes = get_volume_string(gases[0], true);
+		QString volumes;
 		int mean[MAX_CYLINDERS], duration[MAX_CYLINDERS];
 		per_cylinder_mean_depth(&displayed_dive, select_dc(&displayed_dive), mean, duration);
 		volume_t sac;
-		QString SACs;
-		if (mean[0] && duration[0]) {
-			sac.mliter = gases[0].mliter / (depth_to_atm(mean[0], &displayed_dive) * duration[0] / 60.0);
-			SACs = get_volume_string(sac, true).append(tr("/min"));
-		} else {
-			SACs = QString(tr("unknown"));
-		}
-		for (int i = 1; i < MAX_CYLINDERS && gases[i].mliter != 0; i++) {
-			volumes.append("\n" + get_volume_string(gases[i], true));
+		QString gaslist, SACs, separator;
+
+		gaslist = ""; SACs = ""; volumes = ""; separator = "";
+		for (int i = 0; i < MAX_CYLINDERS; i++) {
+			if (!is_cylinder_used(&displayed_dive, i))
+				continue;
+			gaslist.append(separator); volumes.append(separator); SACs.append(separator);
+			separator = "\n";
+
+			gaslist.append(gasname(&displayed_dive.cylinder[i].gasmix));
+			if (!gases[i].mliter)
+				continue;
+			volumes.append(get_volume_string(gases[i], true));
 			if (duration[i]) {
 				sac.mliter = gases[i].mliter / (depth_to_atm(mean[i], &displayed_dive) * duration[i] / 60);
-				SACs.append("\n" + get_volume_string(sac, true).append(tr("/min")));
-			} else {
-				SACs.append("\n");
+				SACs.append(get_volume_string(sac, true).append(tr("/min")));
 			}
 		}
 		ui.gasUsedText->setText(volumes);
-		ui.oxygenHeliumText->setText(get_gaslist(&displayed_dive));
+		ui.oxygenHeliumText->setText(gaslist);
 		ui.dateText->setText(get_short_dive_date_string(displayed_dive.when));
 		ui.diveTimeText->setText(QString::number((int)((displayed_dive.duration.seconds + 30) / 60)));
 		if (prevd)
diff --git a/qt-ui/models.cpp b/qt-ui/models.cpp
index 9d43da624f13..6cf5c2bd24b3 100644
--- a/qt-ui/models.cpp
+++ b/qt-ui/models.cpp
@@ -1250,6 +1250,8 @@ QString DiveItem::displaySac() const
 	const char *unit;
 	int decimal;
 	double value = get_volume_units(dive->sac, &decimal, &unit);
+	if (!value)
+		return "";
 	return QString::number(value, 'f', decimal).append(unit).append(tr("/min"));
 }
 
diff --git a/statistics.c b/statistics.c
index 21b386b21554..01adf4f14497 100644
--- a/statistics.c
+++ b/statistics.c
@@ -331,33 +331,6 @@ void get_gas_used(struct dive *dive, volume_t gases[MAX_CYLINDERS])
 	}
 }
 
-#define MAXBUF 80
-/* for the O2/He readings just create a list of them */
-char *get_gaslist(struct dive *dive)
-{
-	int idx, offset = 0;
-	static char buf[MAXBUF];
-
-	buf[0] = '\0';
-	for (idx = 0; idx < MAX_CYLINDERS; idx++) {
-		cylinder_t *cyl;
-		if (!is_cylinder_used(dive, idx))
-			continue;
-		cyl = &dive->cylinder[idx];
-		if (offset > 0) {
-			strncpy(buf + offset, "\n", MAXBUF - offset);
-			offset = strlen(buf);
-		}
-		strncpy(buf + offset, gasname(&cyl->gasmix), MAXBUF - offset);
-		offset = strlen(buf);
-	}
-	if (*buf == '\0')
-		strncpy(buf, translate("gettextFromC", "air"), MAXBUF);
-
-	buf[MAXBUF - 1] = '\0';
-	return buf;
-}
-
 /* Quite crude reverse-blender-function, but it produces a approx result */
 static void get_gas_parts(struct gasmix mix, volume_t vol, int o2_in_topup, volume_t *o2, volume_t *he)
 {


More information about the subsurface mailing list