summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Linus Torvalds <torvalds@linux-foundation.org>2013-02-24 10:50:18 -0800
committerGravatar Dirk Hohndel <dirk@hohndel.org>2013-02-24 11:09:52 -0800
commit6d548d20285bce74f1a75f2623d55094871c1a81 (patch)
tree014695b2b03927e6251e72a40bec7c545b1ac1e2
parentf4bf16d5db5151a9b1a2fc1523ec930baf98e9b3 (diff)
downloadsubsurface-6d548d20285bce74f1a75f2623d55094871c1a81.tar.gz
Correctly calculate SAC rate in the presense of surface events
This assumes that you are not breathing your cylinders while at the surface, which may or may not be correct, but is usually the right thing. Regardless, we're better off giving a conservative (higher) SAC rate estimate for a diver that breathes his cylinder at the surface too than giving an artificially low one because the diver ended up using his snorkel and we didn't take that into account. NOTE! This basically calculates a better duration and average depth than the ones we end up showing in the dive list. Maybe we should actually show this "no-surface-time" duration and average depth instead of the ones we do show? That's a separate question, though. Added a test-case for the surface case to the sac-test.xml dives. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
-rw-r--r--divelist.c65
-rw-r--r--dives/sac-test.xml19
2 files changed, 65 insertions, 19 deletions
diff --git a/divelist.c b/divelist.c
index 143f4d43c..501cf0487 100644
--- a/divelist.c
+++ b/divelist.c
@@ -719,38 +719,65 @@ static double calculate_airuse(struct dive *dive)
return airuse;
}
+/*
+ * Calculate how long we were actually under water, and the average
+ * depth while under water.
+ *
+ * This ignores any surface time in the middle of the dive.
+ */
+static int calculate_duration(struct dive *dive, struct divecomputer *dc, int *meandepth)
+{
+ int duration, i;
+ int lasttime, lastdepth, depthtime;
+
+ duration = 0;
+ lasttime = 0;
+ lastdepth = 0;
+ depthtime = 0;
+ for (i = 0; i < dc->samples; i++) {
+ struct sample *sample = dc->sample + i;
+ int time = sample->time.seconds;
+ int depth = sample->depth.mm;
+
+ /* We ignore segments at the surface */
+ if (depth > SURFACE_THRESHOLD || lastdepth > SURFACE_THRESHOLD) {
+ duration += time - lasttime;
+ depthtime += (time - lasttime)*(depth+lastdepth)/2;
+ }
+ lastdepth = depth;
+ lasttime = time;
+ }
+ if (duration) {
+ if (meandepth)
+ *meandepth = depthtime / duration;
+ return duration;
+ }
+
+ /* No samples? */
+ if (meandepth)
+ *meandepth = dive->meandepth.mm;
+ return dive->duration.seconds;
+}
+
/* 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;
- int duration, i;
+ int duration, meandepth;
airuse = calculate_airuse(dive);
if (!airuse)
return 0;
- duration = dc->duration.seconds;
- if (!duration)
- return 0;
+
+ duration = calculate_duration(dive, dc, &meandepth);
/* find and eliminate long surface intervals */
+ if (!duration)
+ return 0;
- for (i = 0; i < dc->samples; i++) {
- if (dc->sample[i].depth.mm < 100) { /* less than 10cm */
- int end = i + 1;
- while (end < dc->samples && dc->sample[end].depth.mm < 100)
- end++;
- /* we only want the actual surface time during a dive */
- if (end < dc->samples) {
- end--;
- duration -= dc->sample[end].time.seconds -
- dc->sample[i].time.seconds;
- i = end + 1;
- }
- }
- }
/* Mean pressure in ATM (SAC calculations are in atm*l/min) */
- pressure = (double) depth_to_mbar(dc->meandepth.mm, dive) / SURFACE_PRESSURE;
+ pressure = (double) depth_to_mbar(meandepth, dive) / SURFACE_PRESSURE;
sac = airuse / pressure * 60 / duration;
/* milliliters per minute.. */
diff --git a/dives/sac-test.xml b/dives/sac-test.xml
index b5f0149bb..14ee3f17b 100644
--- a/dives/sac-test.xml
+++ b/dives/sac-test.xml
@@ -46,5 +46,24 @@ We have exactly 100 ATM of gas in 15l of cylinder, average 20m for 25min</notes>
<sample time='25:00 min' depth='0.0 m' />
</divecomputer>
</dive>
+<dive number='4' date='2013-02-24' time='12:26:04' duration='25:00 min'>
+ <location>SAC test dive 3</location>
+ <notes>SAC should be 20l/min (0.7063 cuft/min)
+This adds a 5-minute surface time to the middle of the dive.
+We have exactly 100 ATM of gas in 15l of cylinder, average 20m for 25min</notes>
+ <cylinder size='10 l' description='10l' start='202.6 bar' end='101.3 bar' />
+ <cylinder size='5 l' description='10l' start='202.6 bar' end='101.3 bar' />
+ <divecomputer>
+ <event time='22:00 min' name='gaschange' />
+ <depth max='20.0 m' mean='10.0 m' />
+ <sample time='0:00 min' depth='0.0 m' />
+ <sample time='5:00 min' depth='20.0 m' />
+ <sample time='10:00 min' depth='40.0 m' />
+ <sample time='15:00 min' depth='0.0 m' />
+ <sample time='20:00 min' depth='0.0 m' />
+ <sample time='25:00 min' depth='40.0 m' />
+ <sample time='30:00 min' depth='0.0 m' />
+ </divecomputer>
+</dive>
</dives>
</divelog>