diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-24 10:50:18 -0800 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2013-02-24 11:09:52 -0800 |
commit | 6d548d20285bce74f1a75f2623d55094871c1a81 (patch) | |
tree | 014695b2b03927e6251e72a40bec7c545b1ac1e2 | |
parent | f4bf16d5db5151a9b1a2fc1523ec930baf98e9b3 (diff) | |
download | subsurface-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.c | 65 | ||||
-rw-r--r-- | dives/sac-test.xml | 19 |
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> |