Commit graph

314 commits

Author SHA1 Message Date
Linus Torvalds
d85d8421e0 Split up helper functions for interpolating gas pressure
This splits up the function to create the estimated pressures for
missing tank pressure information.

The code now has a separate pass to create the beginning and ending
pressures for segments that lack them, and fill them in to match the
overall SAC-rate for that cylinder.

In the process, it also fixes the calculation of the interpolated gas
pressure: you can see this in test-dive 13, where we switch back to the
first tank at the end of the dive.  It used to be that the latter
segment of that cylinder showed in a different color from the first
segment, showing that we had a different SAC-rate.  But that makes no
sense, since our interpolation is supposed to use a constant SAC-rate
for each cylinder.

The bug was that the "magic" calculation (which is just the pressure
change rate over pressure-time) was incorrect, and used the current
cylinder pressure for start-pressure calculation.  But that's wrong,
since we update the current cylinder pressure as we go along, but we
didn't update the total pressure_time.

With the separate phase to calculate the segment beginning/ending
pressures, the code got simplified and the bug stood out more.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-01-06 22:17:13 -08:00
Linus Torvalds
25209bfbb4 Fix pressure_time calculation for SAC-rate
The code was using bar, not atm to calculate the pressure_time
multiplier.  But SAC-rate is relative to atm.

We could do the correction at the end (and keep the pressure_time in
"bar-seconds"), but let's just use the expected units during the
integration.  Especially since this also makes a helper function to do
the calculations (with variables to keep the units obvious) instead of
having multi-line expressions that have the wrong units.

This fixes what I thought were rounding errors for the pressure graphs.
They were just unit confusion.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-01-06 22:16:59 -08:00
Linus Torvalds
98ed131bda Split up and re-organize the plot entry calculations
This splits up the (very complex) function that calculates all the plot
info data, so that the gas pressure logic is in several helper
functions, and the deco and partial pressure calculations are in a
function of their own.

That makes the code almost readable.

This also changes the cylinder pressure calculations so that if you have
manually set the beginning and end pressures, those are the ones we will
show (by making them fake "sensor pressures").  We used to shopw some
random pressure that was related to the manually entered ones only
distantly (through various rounding phases and the SAC-rate calculations).

That does make the rounding errors more obvious in the graph, but we can
fix that separately.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-01-06 22:16:43 -08:00
Linus Torvalds
d7925dac44 Do a better job at creating plot info entries
This simplifies - and improves - the code to generate the plot info
entries from the samples.

We used to generate exactly one plot info entry per sample, and then -
because the result doesn't have high enough granularity - we'd
generate additional plot info entries at gas change events etc.

Which resulted in all kinds of ugly special case logic. Not only for
the gas switch, btw: you can see the effects of this in the deco graph
(done at plot entry boundaries) and in the gas pressure curves.

So this throws that "do special plot entries for gas switch events"
code away entirely, and replaces it with a much more straightforward
model: we generate plot entries at a minimum of ten-second intervals.
If you have samples more often than that, you'll get more frequent
plot entries, but you'll never get less than that "every ten seconds".

As a result, the code is smaller and simpler (99 insertions, 161
deletions), and actually does a better job too.

You can see the difference especially in the test dives that only have
a few entries (or if you create a new dive without a dive computer,
using the "Add Dive" menu entry). Look at the deco graph of test-dive
20 before and after, for example. You can also see it very subtly in
the cylinder pressure curves going from line segments to curves on
that same dive.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-01-06 14:42:19 -08:00
Linus Torvalds
635f190302 Fix profile display for dives with no samples
For dives with no samples, we crate a fake dive computer with a set of
made-up samples and use those to display the profile.

However, the actual calculations to do the maximum duration and depth
etc were always done with the "real" dive information, which is empty.
As a result, the scale of the plot ended up being bogus, and part of
the dive would be missing.

Trivially fix by just passing the same dive computer information to
calculate_max_limits() that we use for everything else.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-01-05 00:18:30 -08:00
Dirk Hohndel
cca847791a First stab at simplistic dive planning
This comes with absolutely no gui - so the plan literally needs to be
compiled into Subsurface. Not exactly a feature, but this allowed me to
focus on the planning part instead of spending time on tedious UI work.

A new menu "Planner" with entry "Test Planner" calls into the hard-coded
function in planner.c. There a simple dive plan can be constructed with
calls to plan_add_segment(&diveplan, duration, depth at the end, fO2, pO2)

Calling plan(&diveplan) does the deco calculations and creates deco stops
that keep us below the ceiling (with the GFlow/high values currently
configured). The stop levels used are defined at the top of planner.c in
the stoplevels array - there is no need to do the traditional multiples of
3m or anything like that.

The dive including the ascents and deco stops all the way to the surface
is completed and then added as simulated dive to the end of the divelist
(I guess we could automatically select it later) and can be viewed.

This is crude but shows the direction we can go with this. Envision a nice
UI that allows you to simply enter the segments and pick the desired
stops.

What is missing is the ability to give the algorithm additional gases that
it can use during the deco phase - right now it simply keeps using the
last gas used in the diveplan.

All that said, there are clear bugs here - and sadly they seem to be in
the deco calculations, as with the example given the ceiling that is
calculated makes no sense. When displayed in smooth mode it has very
strange jumps up and down that I wouldn't expect. For example with GF
35/75 (the default) the deco ceiling when looking at the simulated dive
jumps from 16m back up to 13m around 14:10 into the dive. That seems very
odd.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-01-04 23:56:55 -08:00
Dirk Hohndel
1b22ac16f2 Clean up DEBUG code
It's still a mess (and the symbols aren't used consistently), but it's a
tiny bit more logical...

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-01-04 11:56:43 -08:00
Dirk Hohndel
65c85b39ea Make sure that the calculated deco ends at 0
Without this the cairo_close_path call could do silly looking things
(intersecting polygons...).

Reported-by: "Robert C. Helling" <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-01-04 11:54:38 -08:00
Dirk Hohndel
6dc247ff78 Fix deco calculations to correctly use GF values and add CC support
The old implementation was broken in several ways.

For one thing the GF values are percentages, so they should normally be
0 < GF < 1 (well, some crazy people like to go above that).

With this most of the Bühlmann config constants were wrong.

Furthermore, after we adjust the pressure tolerance based on the gradient
factors, we need to convert this back into a depth (instead of passing
back the unmodified depth - oops).

Finally, this commit adds closed circuit support to the deco calculations.

Major progress and much more useful at this stage.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-01-04 11:13:14 -08:00
Dirk Hohndel
2c33603256 Consider previous dives when calculating deco
This also initializes the N2 tissue saturations to correct numbers
(setting them to zero was clearly silly).

With this commit we walk back in the dive_table until we find a surface
intervall that's longer than 48h. Or a dive that comes after the last one
we looked at; that would indicate that this is a divelist that contains
dives from multiple divers or dives that for other reasons are not
ordered. In a sane environment one would assume that the dives that need
to be taken into account when doing deco calculations are organized as one
trip in the XML file and so this logic should work.

One major downside of the current implementation is that we recalculate
everything whenever the plot_info is recreated - which happens quite
frequently, for example when resizing the window or even when we go into
loup mode. While this isn't all that compute intensive, this is an utter
waste and we should at least cache the saturation inherited from previous
dives (and clear that number when the selected dive changes). We don't
want to cache all of it as the recreation of the plot_info may be
triggered by the user changing equipment (and most importantly, gasmix)
information. In that case the deco data for this dive does indeed have to
be recreated. But without changing the current dive the saturation after
the last surface intervall should stay the same.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-01-03 20:45:20 -08:00
Dirk Hohndel
5ba250bd48 Use gradient factors in deco calculation
Usually dive computers show the ceiling in terms of the next deco stop -
and those are in 3m increments. This commit also adds the ability to chose
either the typical 3m increments or the smooth ceiling that the Bühlmann
algorithm actually calculates.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-01-03 20:44:37 -08:00
Dirk Hohndel
aab67e2a5b Add configurable visualization of calculated ceiling
This is on top of the deco information reported by the dive computer (in a
different color - currently ugly green). The user needs to enable this via
the Tec page of the preferences.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-01-03 20:43:19 -08:00
Dirk Hohndel
3c31d0401d First stab at deco calculations
This seems to give us roughly the right data but needs a lot more testing.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-01-03 20:43:14 -08:00
Dirk Hohndel
8f364d0094 Use the Left and Right keys to switch between divecomputers
The existing code had the somewhat retarded Ctrl-C binding for displaying
the next divecomputer and no way to go back to the previous one. With this
commit we use our keyboard grab to map Left and Right to previous and next
divecomputer. Much nicer.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2013-01-01 10:20:22 -08:00
Linus Torvalds
d720e133d8 First step in cleaning up cylinder pressure sensor logic
This clarifies/changes the meaning of our "cylinderindex" entry in our
samples. It has been rather confused, because different dive computers
have done things differently, and the naming really hasn't helped.

There are two totally different - and independent - cylinder "indexes":

 - the pressure sensor index, which indicates which cylinder the sensor
   data is from.

 - the "active cylinder" index, which indicates which cylinder we actually
   breathe from.

These two values really are totally independent, and have nothing
what-so-ever to do with each other. The sensor index may well be fixed:
many dive computers only support a single pressure sensor (whether
wireless or wired), and the sensor index is thus always zero.

Other dive computers may support multiple pressure sensors, and the gas
switch event may - or may not - indicate that the sensor changed too. A
dive computer might give the sensor data for *all* cylinders it can read,
regardless of which one is the one we're actively breathing. In fact, some
dive computers might give sensor data for not just *your* cylinder, but
your buddies.

This patch renames "cylinderindex" in the samples as "sensor", making it
quite clear that it's about which sensor index the pressure data in the
sample is about.

The way we figure out which is the currently active gas is with an
explicit has change event. If a computer (like the Uemis Zurich) joins the
two concepts together, then a sensor change should also create a gas
switch event. This patch also changes the Uemis importer to do that.

Finally, it should be noted that the plot info works totally separately
from the sample data, and is about what we actually *display*, not about
the sample pressures etc. In the plot info, the "cylinderindex" does in
fact mean the currently active cylinder, and while it is initially set to
match the sensor information from the samples, we then walk the gas change
events and fix it up - and if the active cylinder differs from the sensor
cylinder, we clear the sensor data.

[Dirk Hohndel:  this conflicted with some of my recent changes - I think
		I merged things correctly...]

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-30 20:44:47 -08:00
Dirk Hohndel
e3ab1c0701 Update deco handling
This commit makes deco handling in Subsurface more compatible with the way
libdivecomputer creates the data. Previously we assumed that having a
stopdepth or stoptime and no ndl meant that we were in deco. But
libdivecomputer supports many dive computers that provide the deco state
of the diver but with no information about the next stop or the time
needed there. In order to be able to model this in Subsurface this adds an
in_deco flag to the samples. This is only stored to the XML file when it
changes so it doesn't add much overhead but will allow us to display some
deco information on dive computers like the Atomic Aquatics Cobalt or many
of the Suuntos (among others).

The commit also removes the old event based deco code that was commented
out already. And fixes the code so that the deco / ndl information is
stored for the very last sample as well.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-30 18:17:21 -08:00
Dirk Hohndel
2581b3870f Make the tooltip text for gaschange events more informative
We now print out "air", "nn% O2", or "(nn/xx)" for trimix.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-29 11:44:11 -08:00
Dirk Hohndel
e726c9d65c Add settings section to XML file format and store dive computer IDs
We only store the model/deviceid/nickname for those dive computers that
are mentioned in the XML file. This should make the XML files nicely
selfcontained.

This also changes the code to consistently use model & deviceid to
identify a dive computer. The deviceid is NOT guaranteed to be collision
free between different libdivecomputer backends...

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-26 16:46:21 -08:00
Dirk Hohndel
8d2abc05f6 Remove nickname from divecomputer data structure
Having it there with the model information seemed to make sense but on
second thought it's the wrong spot to keep that information, especially
since we were storing it in the XML file in every single dive.

This change removes the nickname member from the divecomputer and makes
the rest of the code reasonably self consistent. It does not add much of
the new code for the new design to handle nicknames.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-21 20:58:47 -08:00
Linus Torvalds
d8fd8b2099 Add a "View next dive computer" menu item
This adds the capability to actually view all your dive computers, by
adding a menu item under "Log"->"View"->"Next DC" to show the next dive
computer.

Realistically, if you actually commonly use this, you'd use the
accelerator shortcut.  Which right now is Ctrl-C ("C for Computer"),
which is probably a horrible choice.

I really would want to have nice "next/prev dive" accelerators too,
because the cursor keys don't work very well with the gtk focus issues.
Being able to switch between dives would also make the "just the dive
profile, maam" view (ctrl-2) much more useful.

The prev/next dive in the profile view should probably be done with a
keyboard action callback, which also avoids some of the limitations of
accelerators (ie you can make any key do the action).  Some gtk person,
please?

Anyway, this commit only does the dive computer choice thing, and only
using the accelerators.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-17 08:29:39 -10:00
Dirk Hohndel
a691a8e5a3 Improve visual appearance of horizontal marker lines
This changes two things to improve the appearance of the profile:
- the partial pressure scale is now in 0.5 increments if the total is <= 4
  and in 1.0 increments if it is > 4.
- the depth marker lines end slightly below the depth chart so that we no
  longer have overlap between the depth scale and the partial pressure
  scale.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-16 22:05:11 -10:00
Lubomir I. Ivanov
33ae98c96f Attempt to free plot data entries in each call to create_plot_info()
In profile.c:create_plot_info(), store the last address in which
memory was allocated for the plot data entries in the static
variable "last_pi_entry". If "last_pi_entry" isn't a NULL
pointer in each call to create_plot_info(), free memory at that
address.

Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-16 16:00:09 -10:00
Dirk Hohndel
713a4fcff6 Add the ability to set a nickname for a dive computer
We maintain a list of dive computers that we know about (by deviceid) and
their nicknames in our config. If the user downloads dive from a dive
computer that we haven't seen before, we give them the option to set a
nickname for that dive computer. That nickname is displayed in the profile
(and stored in the XML file, assuming it is not the same as the model).

This implementation attempts to make sure that it correctly deals with
utf8 nicknames.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-13 21:33:30 -10:00
Dirk Hohndel
0b69bd474d Only display a depth scale appropriate for the depth of the dive
Showing the depth scale all the way to the bottom of the profile plot
looks strange when there are partial pressure graphs down there. So
instead we only plot down to the next marker below the maximum depth of
the actual dive.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-11 15:58:37 -08:00
Dirk Hohndel
c26fa209e3 Show CNS value in the profile mouseover
If we have per-sample CNS values, then show them in the profile tooltip.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-11 13:40:49 -08:00
Dirk Hohndel
91577f11b5 Merge branch 'cns' into cns-merge
I foolishly changed visible_columns in both the (ill-named) cns branch and
master...

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>

Conflicts:
	divelist.c
	gtk-gui.c
	profile.c
2012-12-11 13:09:48 -08:00
Linus Torvalds
c6ca263fb0 Calculate dive maxima/minima independent of dive computer
This splits the dive time, depth, pressure and temperature maxima and
minima setup from the per-dive-computer "create_plot_info()" function
into one setup function that walks _all_ the dive computers, so that we
have a global maxima and minima.

That way the graph scaling we set up will now fit the data from all dive
computers rather than just the particular one we are plotting.  So if
you switch back-and-forth between computers, the scale (which is defined
by the extremes) remains the same.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-11 11:04:18 -08:00
Dirk Hohndel
0ae16899de Don't draw tooltips if no profile is displayed
This fixes ticket 33

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-10 11:02:33 -08:00
Dirk Hohndel
92c0d8c516 Move global variables covered by Preferences into one structure
Now we can simply remember the state of all the preferences at the
beginning of preferences_dialog() and restore them if the user presses
'Cancel'.

Fixes #21

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-10 10:26:06 -08:00
Dirk Hohndel
9463e7895b Don't print partial pressure values in the profile
Instead provide a scale on the right in a highly transparent grey and rely
on the tooltip available with mouse-over to pinpoint the value at certain
spots with much better accuracy.

Fixes #30

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-09 14:36:56 -08:00
Dirk Hohndel
8dfc4dccc5 Don't print an initial gaschange event that just tells us the gas used
Some dive computers appear to tell us the gas used in a gaschange event
right at the beginning of the dive. We arbitrary have a cut-off that says
"a gas change in the first 30 seconds shouldn't get a marker".

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-08 21:23:45 -08:00
Dirk Hohndel
07b74007f1 Correct partial pressure calculations
Regardless what the dive computer tells us, don't believe that pO2 was
higher than the ambient pressure. This gives much more realistic values.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-08 21:23:45 -08:00
Dirk Hohndel
02844c3a10 Correctly parse the two different gas change events
This now takes the He percentage into account when matching tanks. Given
the encoding of fO2 and fHe in the GASCHANGE2 event, we can simply mask
and shift as if we have a GASCHANGE2 event and things will automatically
work correctly for the regular GASCHANGE event.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-08 21:23:27 -08:00
Dirk Hohndel
9bcd21bf67 Draw pO2 profile last
This way it sits on top of the other partial pressure plots and is a bit
easier to read.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-08 14:07:10 -08:00
Dirk Hohndel
40d05ed768 Show two decimal digits in pO2, pN2 and pHe in the tooltip
Tec divers seem to like a little bit more precision - and the dive
computers certainly provide it (or we can calculate it).

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-08 13:58:14 -08:00
Dirk Hohndel
3b425b4c13 Plot pO2 graph based on sample information, if available
This should give closed circuit divers with a supported dive computer
correct partial pressure plots.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-07 21:05:21 -08:00
Dirk Hohndel
a0f28aa422 Add option to make ceiling visually stand out more in the profile
While having the background "come down" seemed like a good visualization
of the ceiling, some divers appear to prefer something more dramatic. This
adds an option to the Tec Settings to have the ceiling shown in red
instead of the default background color.

Suggested-by: Jan Schubert <Jan.Schubert@GMX.li>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-07 11:39:15 -08:00
Dirk Hohndel
982abb5596 Move partial pressure plots up slightly
This way they don't clash with the dive computer model information that
was added by commit a23ec27ca7bb "Add dive computer name to the dive
plot".

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-07 10:49:02 -08:00
Linus Torvalds
0d1f396f3a Move 'plot_info' into 'struct graphics_context'
.. and then allocate just the plot-info entry array dynamically.

We want to have a longer lifetime for the basic plot_info data
structure, because we want to do computer selection and maximum
time/depth/temperature computations *before* we start plotting anything,
and before we allocate the plot entry array.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-07 10:31:26 -08:00
Linus Torvalds
22aa6fa4ef Add dive computer name to the dive plot
I want to have some way to show multiple dive computers, so start off by
adding the name of the current one.  So if we change dive computers,
we'll see it.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-07 10:31:22 -08:00
Dirk Hohndel
dcb6574dc4 Improve deco handling and add NDL support
This commit changes the code that was recently introduced to deal with
deco ceilings. Instead of handling these through events we now store the
ceiling (which in reality is the deepest deco stop with all known dive
computers) and the stop time at that ceiling in the samples.

This also adds support for NDL (non stop dive limit) which both dive
computers that appear to give us ceiling / deco information appear to
give us as well (when the diver isn't in deco).

If the mouse hovers over the profile we now add support for displaying the
NDL, the current deco obligation and (if we are able to tell from the
data) whether we are at a safety stop.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-12-04 21:05:26 -08:00
Dirk Hohndel
10fac7a6af Updating events for libdivecomputer 0.3 (and tracking uemis support)
I was a little too eager to add the deco feature to Subsurface. Jef and I
went back and forth a few more times and the definition of those events
changed. I guess I shouldn't have commited that code until the
corresponding libdivecomputer code had been pushed.

This commit now brings us in sync with the current master of
libdivecomputer (but should compile with 0.2 as well - only deco events
won't work then).

One issue that I see is that deco / ndl aren't really a good fit for the
event model. I actually disabled the drawing of the little yellow
triangles for ndl events as for example on the Uemis those events are
created whenever the remaining non stop time changes - and that can be
every few seconds.

The correct solution may be to treat this as a function of the samples,
but for now this works and is tested with both OSTC and Uemis SDA.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-28 21:13:21 -07:00
Linus Torvalds
df3671390d Fix dive computer event handling if there are no samples
This actually triggers for one of our insane test dives (test15): it has
no samples, so we created a fake dive computer entry with the a fake
profile in it, but we didn't copy the events over.

Having a dive with no samples, yet having events from the dive computer,
sounds pretty bogus.  But that test-case did show that when that bogus
situation happens, we had two independent buglets: (a) we didn't insert
the entries in the fake dive computer entry we used and (b) we would
then mix up the events of the fake dive computer entry with the first
dive computer of a dive.

Fix this, just to make test15 happy again.  And eventually, when we
actually plot the information for multiple dive computers, fixing case
(b) would become necessary even for real dives.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-26 21:45:38 -07:00
Linus Torvalds
25b4fee655 Move events and samples into a 'struct divecomputer'
For now we only have one fixed divecomputer associated with each dive,
so this doesn't really change any current semantics.  But it will make
it easier for us to associate a dive with multiple dive computers.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-23 19:36:27 -08:00
Dirk Hohndel
a154d1ccdc Tweak partial pressure plot to avoid printing values ontop of eachh other
This still can look too busy on shallow long dives with moderate vertical
movement.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-12 20:01:12 -08:00
Dirk Hohndel
79798dc15b Improve visual appearance of temperature plot
Prervent tiny temperature changes from being exaggerated in the plot.

Also, shift pressure plot around a bit (if necessary) to prevent it from
ending in the same space as the temperature plato on the profile graph.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-12 18:46:14 -08:00
Dirk Hohndel
ec042222f0 Handle dives without samples correctly
The code in commit f99e1b476b18 "Trim the dive to exclude surface time at
beginning and end" failed rather badly if a dive has no samples at all -
which is true for many of our test dives.

This makes sure that we don't exclude data points if we never set up start
and end times.

Reported-by: Lubomir I. Ivanov <neolit123@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-11 17:56:32 +01:00
Linus Torvalds
7fc1213aab Add back mysteriously deleted "} else {" line
Commit 6c52e8a2e5 ("Add plotting of the deco ceiling") for some
totally unexplained reason deleted one "else" statement, resulting in
some plot events not having a time at all.  Which causes various really
odd issues if you hit that situation, including divide-by-zero etc due
to the difference in times between events being nonsensical.

It's just some odd mistake that was entirely unrelated to the other
changes in that commit.

Add the missing line back in.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-11 17:22:18 +01:00
Dirk Hohndel
502e2b0e86 Add more data to our tool-tip display in the profile window
This shows the values for all the graphs that are shown (depth,
temperature, tank pressure, pO2, pN2m pHe), but also correctly doesn't
display them when they are turned off or no data is available (prior to
this commit, tank pressure was always shown, even if no pressure samples
were available for the dive).

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-11 17:18:14 +01:00
Linus Torvalds
80485114ba Fix possible array bound violation for insanely long dives
When we calculate the interval for the tick-marks for the dive, we need
to limit 'i' to be within the size of the array.  The code does that
with a "i < 8" check, but the fact is, we must never increment past the
last entry, which is 7 (the size of the array is 8, but the last valid
index is 7).

This only happens for unrealistically long dives.  Which you can trigger
either by inputting insane values for a manually created dive, or by
merging two dives that are consecutive, but not close to each other
time-wise (eg on different days ;)

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-11 15:08:56 +01:00
Linus Torvalds
01e8984d7d Create tool-tip with depth/pressure for the whole profile area
This extends on our current tooltip logic (which shows events when you
mouse over them) to show tooltips for the whole profile area.

If you mouse over an event, that is still shown in the tooltip, but
even in the absense of events, the tooltip will be active, and mousing
over the profile area will show the time, depth and pressure.

This can certainly be improved upon further, but even in this form it is
useful.

Fixes #9

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-11 14:44:10 +01:00
Dirk Hohndel
7c09991876 Trim the dive to exclude surface time at beginning and end
We don't change any of the samples, we just don't plot (or consider for
dive time / mean calculations) the samples at the beginning or end of the
dive that are less than a certain threshold under water. Right now that's
an arbitrary 75cm which seems to Do The Right Thing(tm) for the dives I
tried this with - but I'm happy to look at other values if this causes
problems for people with dive computers I do not have access to.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-11 10:36:46 +01:00
Dirk Hohndel
e167108c76 Add depth to mbar helper function
This ensures that we use consistent math to get the absolute pressure at a
certain depth.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-11 08:50:56 +01:00
Dirk Hohndel
836bbad7a6 Add threshold feature for partial pressure graphs
The tec diving preference pane now allows us to set a partial pressure
threshold for each of the three gases. When the partial pressure surpasses
that value, the graph becomes red.

Fixes #12

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-10 17:58:42 +01:00
Dirk Hohndel
6ad73a8f04 Improve logic handling events
We now throw away redundant events, just as we throw away other redundant
data coming from the dive computer. Events are considered redundant if
they are less than 61 seconds apart and identical.

This also improves the display of the remaining events in the profile as
we now show the value of the event, if it is present (for example for a
deco event we show the duration of the deepest stop).

Finally, for events that define a range (so they set the beginning flag
and assume and end flag some time later) we no loger show the triangle but
assume that some other code handles visualizing them (as happens for the
ceiling events).

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-10 11:54:15 +01:00
Dirk Hohndel
7db08ae128 Instead of the ugly red boxes make the surface come down to ceiling
Based on suggestions from Linus (and a few iterations) we now simply have
the surface (i.e., background color / pattern) come down to where the
ceiling is. And we only do the angry red shading when the diver violates
the ceiling.

I think this looks much better.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-10 11:54:14 +01:00
Dirk Hohndel
6c52e8a2e5 Add plotting of the deco ceiling
Plot a red-shaded area on top of the depth profile to indicate the deco
ceiling (i.e., the area into which it isn't save to ascend at this point
of the dive.

So far this is of very limited use as libdivecomputer doesn't give us the
necessary information to plot this. I have sent patches for the OSTC to
Jef, hoping that he will include them in an update. I don't know how many
other dive computers will make this data available - I still need to add
this to our native Uemis support.

This commit also fixes two cut and paste errors in the previous commit
6540be9bd924 "Process ceiling events and store ceiling data in plot_info".

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-10 11:54:14 +01:00
Dirk Hohndel
7c9b89e442 Process ceiling events and store ceiling data in plot_info
This just creates the infrastructure but doesn't yet do anything useful
with the data.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-10 11:54:07 +01:00
Dirk Hohndel
51003eaed7 Fix partial pressure calculation
The existing implementation failed on dive computers that did gas changes
based on events (instead of tracking them in the sample data like the
Uemis Zurich does that I tested the code with).

This commit moves the calculations slightly later in create_plot_info()
after the gas change events are processed and the plot_info data has been
fixed up. Now this works with the data from Linus' Suunto as well.

Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-07 15:06:18 +01:00
Dirk Hohndel
0d33337a20 Remove pN2 debug printout and add disabled code for partial pressure scale
The pN2 print shouldn't have been committed, but I don't want to try and
rewrite all the commit history. Oh well.

The pressure scale I am ambivalent about. It seems that it should be
useful - but that would require guide lines that coincide with the values
which would really throw off the visual for me. So I added the code, but
left it disabled.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-06 06:46:14 +01:00
Dirk Hohndel
1218e7a5e9 Don't print mean depth across the whole profile area
I can't remember why we initially did this instead of ending the
horizontal red line whith the last data point of the pressure profile. But
especially nuw with more graphs shown the one line that extends past the
end of the dive looked really silly.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-06 06:46:14 +01:00
Dirk Hohndel
af939ee4c8 Be smarter about printing gas partial pressure text
We always want to print absolute maxima and minima - but not when multiple
consecutive data points all have the same value (this happens, for
example, when printing a pHe plot on non-helium dives - or when the dive
profile includes a brief surface intervall which causes all the partial
pressures to be at their minimum).

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-06 06:46:05 +01:00
Dirk Hohndel
d2edc681a4 Fine tune the vertical spacing of the graphs
Whatever I pick here, there will be dives where the different graphs end
up interfering with each other. I don't think there isn't an easy, generic
solution for this (but I can envision awesome non-easy solutions - they
just don't seem to be worth the effort).

But for most dives that I played with this seems to work pretty well.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-05 20:44:51 -08:00
Dirk Hohndel
853277ba9d Plot text values for partial pressure graphs
The algorithms attempt to identify "interesting" points where the user
might want to know the value of the graph.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-05 08:56:18 -08:00
Dirk Hohndel
5f2f415cdb Add pHe and pN2 plotting
Adjust the color for pN2 to the standard for this gas (black). We keep pO2
green (even though the ISO 32 color for that would be white). pHe is
marked in brown (which is the matching standard color).

Calculate correct partial pressures for the synthetic plot info points at
the beginning and end of the dive.

Minor fine tuning to the positioning / scaling of the temperature plot
when partial pressures are plotted.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-01 15:39:15 -07:00
Dirk Hohndel
f806cdbe2e Fix the pO2 calculation when diving with air
So few of my dives are on air that at first I didn't notice - but for
those dives we set the o2 permille to 0 - which of course causes incorrect
(and extremely deadly) pO2 of 0...

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-01 12:05:31 -07:00
Dirk Hohndel
01fd6a57bc Add vertical space to depth plot if we are showing partial pressure graphs
Fairly simplistic change that modifies the way we calculate the "maxdepth"
for a particular dive as that is used to scale the plot vertically.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-01 11:44:18 -07:00
Dirk Hohndel
bdc6b6ba24 Change preferences into a notebook and add second page for tec settings
Not sure this is the best naming scheme (General Settings / Tec Settings)
but it's a start.

The idea is to have the settings that a recreational diver might care
about on the first page, and all the other stuff on the second one. Let's
see how this works out long term. For now I moved OTU over and added
toggles for the different partial pressure graphs (only the pO2 one is
implemented so far).

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-01 11:11:05 -07:00
Dirk Hohndel
1b606ae226 First stab at plotting a pO2 graph
So far this is done unconditionally. This already starts some of the
infrastructure for other gases, but so far only O2 is handled.
We also need a pressure scale on the right to make this useful - or we
need to do peek / trough pressure prints like we do for temperature and
depth.

Finally, I think I want to move the plot further down, maybe make the
whole plot area taller if we are plotting partial gas pressures as well.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-01 10:04:12 -07:00
Dirk Hohndel
029db4aae2 Add depth scale to the dive profile
This is intended to be unobtrusive, but add more information for people
who aren't satisfied with the numeric value we put inside the plot to mark
local peaks and troughs.

See ticket #9

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-10-29 10:56:20 -07:00
Dirk Hohndel
016365c5f1 Fix the way we handle translated event names
Here is what Linus reported:

 I think you have made a mistake in trying to translate some of
 libdivecomputer.c

 Translating some of those things based on locale is *wrong*, because
 they are saved in the XML file.

 That covers at least the warnings: they'll get translated when you
 import them, and then saved to the XML file as that translation, but
 now if you start subsurface in another locale, they will not get
 translated back.

 So translating XML file contents is fundamentally buggy. It just
 shouldn't be done.

 So all the "translations" for the event handling are buggy, and
 generate crap. Please don't do that. Leave them as English.

And of course he is absolutely right. However, instead of not translating
them at all, this commit fixes things a better way - we now mark the
strings for translation but store the original English strings everywhere
(in the in-memory data structure as well as in the XML file). Only when we
actually display something on the screen (in a tooltip or in the filter
dialog) do we actually translate the strings into the native language.

This should address both Linus' issue and the desire to have localized
event texts.

Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-10-21 11:40:30 -07:00
Dirk Hohndel
99846da77f Conversion to gettext to allow localization
This is just the first step - convert the string literals, try to catch
all the places where this isn't possible and the program needs to convert
string constants at runtime (those are the N_ macros).

Add a very rough first German localization so I can at least test what I
have done. Seriously, I have never used a localized OS, so I am certain
that I have many of the 'standard' translations wrong. Someone please take
over :-)

Major issues with this:

- right now it hardcodes the search path for the message catalog to be
  ./locale - that's of course bogus, but it works well while doing initial
  testing. Once the tooling support is there we just should use the OS
  default.

- even though de_DE defaults to ISO-8859-15 (or ISO-8859-1 - the internets
  can't seem to agree) I went with UTF-8 as that is what Gtk appears to
  want to use internally. ISO-8859-15 encoded .mo files create funny
  looking artefacts instead of Umlaute.

- no support at all in the Makefile - I was hoping someone with more
  experience in how to best set this up would contribute a good set of
  Makefile rules - likely this will help fix the first issue in that it
  will also install the .mo file(s) in the correct place(s)

  For now simply run

  msgfmt -c -o subsurface.mo deutsch.po

  to create the subsurface.mo file and then move it to
  ./locale/de_DE.UTF-8/LC_MESSAGES/subsurface.mo

  If you make changes to the sources and need to add new strings to be
  translated, this is what seems to work (again, should be tooled through
  the Makefile):

  xgettext -o subsurface-new.pot -s -k_ -kN_ --add-comments="++GETTEXT" *.c
  msgmerge -s -U po/deutsch.po subsurface-new.pot

  If you do this PLEASE do one commit that just has the new msgid as
  changes in line numbers create a TON of diff-noise. Do changes to
  translations in a SEPARATE commit.

- no testing at all on Windows or Mac
  It builds on Windows :-)

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-10-11 10:03:03 +09:00
Lubomir I. Ivanov
50eac41129 Use GTK_UNIT_INCH when printing to provide consistency across OS
Tests have shown that the most multi-platform way to do printing with GTK is
to use GTK_UNIT_INCH (or GTK_UNIT_MM) with GtkPrintOperation. Tested on
Linux, OSX, Windows.

However this requires the appropriate scaling for Pango and Cairo to be done,
with separate plotting logic for printing and drawing on the screen. To achieve
that, profile.c:plot() now accepts a scaling parameter from type
"scale_mode_t" defined in "display.h".

Also due to new scale, small decimal numbers (such as 6.12345) cannot be well
stored in "cairo_rectangle_int_t" therefore it is replaced with
"cairo_rectangle_t", which uses doubles to provide Cairo with a drawing
area.

Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>

Minor whitespace cleanup.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-09-11 07:26:38 -07:00
Mikko Rasa
d6b50e30e4 Fix profile and average depth for freedives
Freedives can easily exceed the assumed ascent/descent rate, which
results in wacky dive profiles.  Add a check to make the ascent and
descent fit within the duration of the dive.
2012-08-29 19:12:18 +03:00
Linus Torvalds
9d46581913 Merge branch 'freediving-tweaks' of git://github.com/mguentner/subsurface
Merge freediving tweaks (zoom in on short dives etc) from Maximilian
Güntner.

Trivial conflicts in display.h due to unrelated printing stuff just
happening to be added nearby.

* 'freediving-tweaks' of git://github.com/mguentner/subsurface:
  moved zoomed_plot to display.h
  plot the time with a fixed padding (leading zero)
  updated/corrected comment
  added "Zoom" button and improved scaling
  fixed indentation
  use increments that make sense for 600 seconds
  Plot shorter (apnea) dives with a reasonable scale
2012-08-28 13:20:23 -07:00
Linus Torvalds
9380f78c82 Do some whitespace cleanup
The previous commit was a patch from Lubomir, which also had some
whitespace fixes (to go with some new whitespace bugs to replace them)
in it.

I removed the whitespace changes from that patch (don't mix whitespace
fixes with other fixes, unless they are on the same lines!) but decided
to look for other whitespace issues, and this is the result.

I left the non-C files alone, some of the spec and script files also
have whitespace at the end of lines etc.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-08-26 14:41:05 -07:00
Maximilian Güntner
1c1ad77f83 plot the time with a fixed padding (leading zero)
Signed-off-by: Maximilian Güntner <maximilian.guentner@gmail.com>
2012-08-22 01:23:54 +02:00
Maximilian Güntner
0c0ec7e4f6 Merge branch 'master' into freediving-tweaks
Signed-off-by: Maximilian Güntner <maximilian.guentner@gmail.com>
2012-08-22 01:15:41 +02:00
Linus Torvalds
972669d636 Rework dive selection logic
This completely changes how we keep track of selected dives: instead of
having an array listing the selection ("selectiontracker") or trusting
the gtk selection information, just save the information about whether a
dive is selected in the dive itself.

That makes it trivial to keep track of the state of selection across
group collapse/expand events, or when changing the tree view model.  It
also ends up simplifying the code and logic in other ways.

HOWEVER, it does currently (re-)introduce an annoying oddity with gtk:
if you collapse a dive trip that has individual selections, gtk will
forget those selections ("out of sight, out of mind"), and when you do
*new* selections, the old hidden ones remain.

So there's some games required to make gtk do sane things.  We may need
to either explicitly drop selections when collapsing trips, or make sure
the group entry gets selected when collapsing a group that has
selections in it. Or something.

There may be other issues introduced by this too.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-08-20 05:48:07 -07:00
Linus Torvalds
52c3d11d2c Make fill_missing_tank_pressures robust against missing cylinder info
The code iterates over a list that can be NULL, but happily dereferenced
it anyway.  Oops.

This function really should be split up and commented more.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-08-18 09:05:51 -07:00
Linus Torvalds
d0e27c6c53 Merge branch 'misc-fixes' of git://github.com/DataBeaver/subsurface
Pull miscellaneous fixes, mostly UI stuff from Mikko Rasa.

Both this and the pull from Pierre-Yves Chibon created a "Save As" menu
entry and logic.  As a result, there were a fair number of conflicts,
but I tried to make the end result somewhat reasonable.  I might have
missed some semantic conflict, though.

Series-acked-by: Henrik Brautaset Aronsen <subsurface@henrik.synth.no>

* 'misc-fixes' of git://github.com/DataBeaver/subsurface:
  Add a separate "Save as" entry to the menu
  Changes to menu icons
  Improved depth info for dives without samples
  Divide the panes evenly in view_three
2012-08-17 10:57:24 -07:00
Dirk Hohndel
f6dfb0094c Fix right click edit in Dive Notes area for multiple dives
This fixes the bug that triggered the SIGSEGV that Linus worked around
earlier. I had forgotten to update this call path to the
edit_multi_dive_info function.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-08-16 12:51:32 -07:00
Mikko Rasa
a5e822a4d6 Improved depth info for dives without samples
This calculates a mean depth for the dive with a fixed ascent/descent
rate and an assumption that all of the bottom time is at the maximum
depth.  It's not much, but it allows some derived values such as SAC to
make more sense.

The depth profile for such dives is now also generated with the same
assumptions instead of putting the samples at fixed percentages of the
dive duration.

Signed-off-by: Mikko Rasa <tdb@tdb.fi>
2012-07-31 21:12:19 +03:00
Maximilian Güntner
2cada118eb updated/corrected comment
Signed-off-by: Maximilian Güntner <maximilian.guentner@gmail.com>
2012-06-11 03:11:13 +02:00
Maximilian Güntner
7acd075bd5 added "Zoom" button and improved scaling
It should be possible to have a certain limit where we
stop zooming so that short dives are visible as such
at first glance. Therefore a "Zoom" button has been
added to the "Log" menu along with a shortcut (Ctrl + "0").
The user can now zoom/unzoom the plot and is still able to
quickly distinguish short dives from normal ones when
browsing the log.

Signed-off-by: Maximilian Güntner <maximilian.guentner@gmail.com>
2012-06-11 02:45:36 +02:00
Maximilian Güntner
0a7fa8ea50 fixed indentation
Signed-off-by: Maximilian Güntner <maximilian.guentner@gmail.com>
2012-06-09 22:40:12 +02:00
Maximilian Güntner
b7ae9ad5b1 use increments that make sense for 600 seconds
599/12 = 50, no need to use 5*60.

Signed-off-by: Maximilian Güntner <maximilian.guentner@gmail.com>
2012-06-09 15:05:41 +02:00
Maximilian Güntner
4229e89fc1 Plot shorter (apnea) dives with a reasonable scale
The time marker increments have also been changed to better values.
Also, display more time information for short dives.

Signed-off-by: Maximilian Güntner <maximilian.guentner@gmail.com>
2012-06-08 02:54:02 +02:00
Dirk Hohndel
3d75c73f36 More removal of unused arguments
Just trying to clean up the code a bit.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-01-05 08:16:50 -08:00
Dirk Hohndel
4e4e3cc43a Small improvement to plot info debugging code
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-12-12 10:13:03 -08:00
Linus Torvalds
ce6c3ee56d Merge branch 'grid-to-back' of git://github.com/henrik242/subsurface
* 'grid-to-back' of git://github.com/henrik242/subsurface:
  Move depth/time grid back
2011-12-06 10:58:06 -08:00
Henrik Brautaset Aronsen
34a0f5255a Move depth/time grid back
The temperature profile was behind the white depth/time grid.

Signed-off-by: Henrik Brautaset Aronsen <subsurface@henrik.synth.no>
2011-12-06 19:45:38 +01:00
Henrik Brautaset Aronsen
3f624a2eb3 Remove commented code
I left some printer-spesific commented code in there.  Away with it.

Signed-Off-By: Henrik Brautaset Aronsen <subsurface@henrik.synth.no>
2011-12-01 12:28:38 +01:00
Henrik Brautaset Aronsen
b65f8230da Clean up color definitions
Fix ugly printout, give colors proper names, make grid lines and alert
marker easier to see, and specify printer colors independently.

Signed-Off-By: Henrik Brautaset Aronsen <subsurface@henrik.synth.no>
2011-12-01 12:14:21 +01:00
Henrik Brautaset Aronsen
fc6fec59ba Define all colors in one place
The profile colors were defined all over the place, so I put them all in one spot.  I'm unsure if this is the best solution to that problem, but I guess it's a step in the right direction.

Signed-Off-By: Henrik Brautaset Aronsen <subsurface@henrik.synth.no>
2011-11-28 18:19:50 +01:00
Henrik Brautaset Aronsen
36db51f2e7 Prettier profile colors
The profile colors aren't very pretty, and the grid lines are too thick.
This commit tries to improve that.

Signed-Off-By: Henrik Brautaset Aronsen <subsurface@henrik.synth.no>
2011-11-28 13:58:18 +01:00
Dirk Hohndel
0d1f8f9a5d Don't colorize the pressure plot when printing
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-11-21 12:35:42 -08:00
Dirk Hohndel
0f13971869 Add debugging function to dump tank pressure tracking data
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-11-21 12:29:16 -08:00
Linus Torvalds
a643e740dc Do proper rounding in interpolated pressure calculations
We do all the pressures in mbar, which has plenty of precision for
interpolated pressures - even when we then do our discrete integration
over many samples.

However, when we calculate those interpolated pressure points, we should
make sure that we round the result correctly, otherwise the consistent
rounding errors (from truncating the FP value into our integer mbar
values) will result in a final pressure that is noticeably off in ugly
ways (ie "end pressure set by hand to 750 mbar, but shown as 748").

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-11-20 10:27:33 -08:00
Linus Torvalds
bb421a416d Revert "Correctly plot the tank end pressure if it was set manually"
This reverts commit abdee5b1b8.

There's no point in doing random hacks.  Instead, do the intermediate
pressure calculations with proper rounding instead of always truncating
to mbar.  With the math done correctly we have enough precision that the
end result of the pressure interpolation doesn't have the kind of errors
that caused Dirk to try to fix things up later.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-11-20 10:27:19 -08:00
Dirk Hohndel
855df669d9 Fix error when gaschange event is one second before next sample
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-11-19 13:18:10 -08:00
Dirk Hohndel
abdee5b1b8 Correctly plot the tank end pressure if it was set manually
While printing the last pressure in the calculated sequence may seem more
logical, given that the discrete series will create some amount of error
this simply looks wrong. Instead we pick the end pressure that was
manually set.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-11-19 12:47:07 -08:00
Dirk Hohndel
e7491d3bf5 Make pressure plot shading by sac rate consistent
Some parts of the existing code used the depth at the time of the sample
to calculate the sac rate - it makes much more sense to use the average
depth. But that requires us to loop over the entries and average the
individual sac rates per segment instead of just using the beginning and
end depth of the multi-segment interval we use for smoothing purposes.

This may seem like a subtle detail, but it does in fact matter when we
plot the synthetic tank pressure values that we create when we have no
tank pressure data in the samples.

Another detail we change here is to not artificially start with a forward
looking segment of the full SAC_WINDOW but instead just start with the
first two data points and then simply let the time window grow until it
hits SAC_WINDOW - at which point it becomes a sliding window.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-11-19 15:12:30 -05:00
Dirk Hohndel
e1019cafa8 Improve tank pressure sac coloring
This changes the algorithm that picks the sac color to consider
+/- 1 l/min to be the same color (before the color changed every
time you crossed above or below the average which looked silly with
our synthetic "constant sac" values as those are discrete and oscilate
around the average.

This also changes the order in which things are drawn so so that the
pressure plot goes over the depth profile plot (so the red shading of the
dive no longer changes the color of the tank pressure plot).

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-11-19 15:12:29 -05:00
Dirk Hohndel
4e876b3082 Be more consistent in our handling of rgb value tables
Use rgb_t for the sac colors, create a new set_source_rgb_struct function
and use that for the velocity values (in the depth plot) as well.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-11-19 15:12:29 -05:00
Dirk Hohndel
47a0e0e4be Color tank pressure plot based on relative sac
Linus suggested that instead of using absolute SAC values to base the
color on (which forced us to pre-define which SAC rates are green and
which are red) we should color the tank pressure plot relative to the avg
SAC rate of that dive - which I think makes the coloring much more useful
to spot when on your dive you were doing well and when you were not.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-11-18 09:57:49 -02:00
Dirk Hohndel
4cff1f5b90 Color pressure plot according to current SAC rate
Similar to color indicating vertical speed in the profile plot we now use
color in the tank pressure plot to indicate current SAC rate.

We use a 45 sec sliding window to make sure we cover at least two breaths
for each current SAC sample to avoid artificial oscillation based on
breathing rhythm for corputers with high sample resolution.

Not sure about the color coding that I'm using right now - it's green-ish
for SAC rates under 15l/min ~= .55cuft/min and turns yellow and red as you
go higher. That seems to work well for me, but for other divers this may
be way off (or at least not as useful). Maybe this should be configurable?
This is a lot more diver specific than the vertical velocity where there
are clear recommendations based on safety considerations on what is good
and bad.

As a side effect, this removes the color coding that showed you whether
you were looking at pressure data from samples (green) vs. interpolated
pressure data (yellow). Not sure if people really want to see that. We
might be able to indicate this differently (I am thinking different line
width or transparency or something along those line)

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-11-17 18:13:10 -02:00
Dirk Hohndel
2b0f30c3d4 This should fix the missing end pressure for broken dive computers
Some dive computers randomly drop samples. That was no problem unless it
was the LAST sample. We work around that now

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-11-09 20:15:48 -05:00
Linus Torvalds
c5073aa446 Remove unused 'minpressure/endpressure' fields from plot info
.. and fix the maxpressure to actually look at *all* the cylinders, so
that if you don't have sample data, but rely onmanually set cylinder
pressures, it now really is the max of all the cylinders.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-11-09 19:37:18 -05:00
Linus Torvalds
34d7950961 Merge branch 'bugfixes' of git://github.com/dirkhh/subsurface
* 'bugfixes' of git://github.com/dirkhh/subsurface:
  Fix breakage caused by Linus' changes to tank pressure handling
2011-11-09 19:23:59 -05:00
Dirk Hohndel
0d7ad02f87 Fix breakage caused by Linus' changes to tank pressure handling
We no longer look at the start and end pressure for a tank, if the tank
has valid pressure data in its samples (which makes sense). Sadly that
breaks the current pressure interpolation code. With this patch most of
those problems should be fixed.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-11-09 19:15:28 -05:00
Dirk Hohndel
4317bfaa11 Improve temperature text plotting in profile display
- make the text a lighter color so it stands out more
- change the heuristic when we print text to include both relative change
  in temperature and time since the last text was printed
- print the first temperature we encounter
- allow an ending temperature to be printed if the last printed
  temperature was before the 75% mark of the dive

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-11-09 13:31:57 -08:00
Dirk Hohndel
e38eb77e30 Correctly plot dives ending below the surface
I thought we had fixed this before - but I guess it got broken again
somewhere. We now make sure that the plot_info ends on an entry with
depth 0.

Added test14 to verify the fix.

Also fixed cut'n'paste errors in a few test dive files.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-11-09 07:53:10 -08:00
Dirk Hohndel
4b735521e2 Fix missing pressure plot at start of the dive in some situations
In some situations we could end up with no sample pressure and no
interpolated pressure at time = 0. This is now fixed.

Fix notes in test dive the exposed the issue.

Also change the code in create_plot_info to keep the number of samples and
the number of corresponding pi entries in separate variables. This avoids
future changes from breaking if they assume they can access
dive->sample[nr_samples - 1] (which is a reasonable assumption to make).

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-11-04 15:38:46 -07:00
Dirk Hohndel
c52b95d502 Improve tank pressure plot for computers that create "gaschange" events
This was exposed by the test dives, but it shows up in small ways with
real dives from some dive computers like the Suunto Vyper Air.

We now insert synthetic plot_info entries that match the gas change event;
to make this look smoother we insert either two events (one for the old
tank, one a second later for the new tank) if there is no sample at the
time of the event, or one additional event (and move the real sample back
by one second) if there is a sample at the time of the event.

This does expose another issue with some dives from Linus' computer where
the pressure in the samples dips below the end pressure noted for the tank
- which creates an odd "yellow up-tick" at the end of using the first tank
in the plot. Maybe we should not insert a synthetic "last of old tank"
event if we have a sample with valid pressure in the last NN seconds
before the gas change?

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-11-04 14:32:15 -07:00
Dirk Hohndel
edbba678b3 Don't repeat redundant minima or maxima in the profile plot
If we have more than four identical depth readings, the old code would see
those as local maxima and minima and print spurious depth values in the
profile plot.

Yes, in real sample data identical readings won't happen - but in
synthetic data they can and there this looks really bogus.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-11-04 14:25:20 -07:00
Dirk Hohndel
b26ca781b8 Use unit functions to get column headers, add unit function for pressure
Finally getting more consistent overall in how we convert between the
different units and how we decide which units to display.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-11-01 20:13:14 -07:00
Dirk Hohndel
18b8247cb3 Add new helper function to get temperature and unit
Designed along the lines of get_depth_units - except we don't define a
specific number of digits to show.

Use this in the one spot we need it right now in profile.c

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-11-01 19:52:12 -07:00
Linus Torvalds
ceed8b6bc9 Fix up end conditions for dives
We used to have the dive plot have two "filler" entries at the beginning
and the end, and indeed that is how they are allocated.  However, we fix
up "pi->nr" later to be "lastindex+1", where "lastindex" is the index of
the time we surface.

So when we loop over the plot entries, we actually need to loop all the
way to the end: use "i < pi->nr" instead of "i < pi->nr-2".

We still do have the two extra filler entries at the beginning, though.
So depending on the loop, we might want to start at entry 2.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-10-29 15:57:26 -07:00
Linus Torvalds
7c1deb37c7 Plot fake profile for non-sample dives
Right now it just plots something ridiculous, the code is really just
meant to be an example.  We migth be able to plot a traditional
staircase plot and make it look somewhat saner by taking mean depth into
account (if it exists).

Right now it just plots a (skewed) rectangular dive profile using the
max depth and total time. Which is obviously insane.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-10-29 14:09:27 -07:00
Linus Torvalds
b74cc4f523 Fix use of uninitialized variable if there are no samples
When creating the plot_info, the 'entry' variable pointing to the last
plot_info data was not initialized (because there was no data to fill
in), and was then incorrectly used to fill in the last tank pressure.

We also used to look at 'dive->sample[0].cylinderindex' even if no
sample[0] necessarily existed.

Reported-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-10-29 13:24:56 -07:00
Dirk Hohndel
98efa0794a Add menu item and dialog to select which events to display
Right now they are displayed in one hbox which doesn't work if you have
many events - but the code itself works and correctly toggles the events
on and off.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-10-25 02:51:16 -07:00
Dirk Hohndel
499cc0c87c Don't plot an event if an event is disabled in ev_namelist
We don't have a way to actually configure this in the app, yet, but
toggling the bits in the debugger shows that this works, so commit this
code now.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-10-25 01:25:12 -07:00
Dirk Hohndel
5ca49b0460 Remember the event names as we encounter them
First step to being able to filter the events that we display in the
profile. We could (in theory) walk all the dives in the divelist when we
need this data, but it seems much more convenient to have them in an array
in one place.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-10-25 01:05:08 -07:00
Linus Torvalds
a72408400c Merge branch 'ui' of git://github.com/dirkhh/subsurface
* 'ui' of git://github.com/dirkhh/subsurface:
  Disable sorting by dive number
  Fix oversight in preference implementation
  Make columns for temperature, cylinder, and nitrox optional
  Show dive number in dive list
  Improve time marker handling and add printing of some time labels
2011-10-24 07:03:22 +02:00
Dirk Hohndel
86fdd83e7b Improve time marker handling and add printing of some time labels
We now draw time markers at most every 5 min, but no more than 12 markers.
For convenience we do 5, 10, 15 or 30 min intervals.
This allows for 6h dives - enough (I hope) for even the craziest divers -
but just in case, for those 8h depth-record-breaking dives, we double the
interval if this still doesn't get us to 12 or fewer time markers.

We label the first and then every other time marker with the minute text.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-10-23 08:04:54 -07:00
Linus Torvalds
2b4fa480ae Handle 'gas change' events correctly
Dirk wrote the multi-cylinder support assuming that the dive computer
always gives the selected cylinder index in the sample data - that's
what his Uemis does, and it makes sense for any dive computer that
supports multiple pressure transmitters.

However, the other case is a dive computer where the pressure samples
are all from cylinder 0, and any other cylinder will have the starting
and ending pressure set by hand.  And the gas change events show when
the cylinder change happened.

So this creates a "turn gas change events into pressure sample fixups"
phase just before we actually analyze the pressures.  That way the
pressure analysis can alway sdo the right thing, regardless of how the
data was originally stores in the dive.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-10-23 18:01:30 +03:00
Linus Torvalds
2b2b6775de Split the cylinder pressure analysis into a second loop
For the dive computers that give cylinder change events, we want to
re-write the cylinder index and pressure information with the event
information before we start analyzing the pressures.  So instead of
filling the plot info and analyzing in one loop, split it up into two
phases.  We'll do the "fix up cylinder pressure info based on events" in
between those phases.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-10-23 18:01:16 +03:00
Dirk Hohndel
473fb14b56 Plot tank pressures for multiple tanks
The code keeps track of the segments of time when a specific tank was used
and interpolates the pressure values for that tank based on a simulated
average SAC rate for the times in which no pressure readings are
available.

This changes the way we used to plot the pressure when only beginning and
end pressure of a tank are known; it used to be a straight line, now it is
a sloped line where the steepness of the slope is proportional to the
depth at that point - which is much more realistic.

We also plot the pressures in two colors now. The old green for pressure
data that came from the input file (that is not the same thing as saying
it came from the computer - divelog for example appear to create pressure
readings in the samples even if it only has beginning and end pressure).
Interpolated values are plotted in yellow. If you have a sub-standard dive
computer which has a frequently failing pressure sensor, you can now tell
the parts of the plot where data was missing and we are filling in.

The function that prints the pressure text labels had to be completely
redone as it previously assumed one tank for the whole dive and
simplisticly printed that tank's start and end pressure at the beginning
and end of the profile plot with the y-values being the maximum and
minimum pressure...

This commit introduces a custom simplistic single linked list data
structure to keep track of the pressure information per segment - Linus
hated the idea of using GList for this purpose, and I have to admit that
in the end this was very straight forward to implement and made the code
easier to read and debug.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-10-23 05:30:33 -07:00
Dirk Hohndel
bf1dc48dfe Change plot_info to use depth (instead of val) for depth value
Also changed a couple of corresponding local variables

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-10-22 23:03:23 -07:00
Linus Torvalds
e919a0f2ea Add quick hack for "no sample pressure but tank index changed" case
This isn't right if you switch back to the same cylinder multiple times,
but for the first time it kind of works - just take the beginning
cylinder pressure if we have one.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-10-20 22:25:38 +03:00
Linus Torvalds
45d4d5ecde Fix up multi-cylinder code as per Dirk
Too much cut-and-paste, as Dirk points out.  With multiple cylinders,
we're not necessarily going to start at time zero.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-10-20 13:55:55 +03:00
Linus Torvalds
0a33d0bd7d Start some rough multi-cylinder pressure data plot infrastructure
It doesn't actually do multiple cylinders correctly yet, but it should
be a nice framework for it.  And accidentally (not) it also ends up
drawing the final line for the end pressure of a single-cylinder dive
that has been fixed up by hand too.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-10-19 09:47:46 -07:00
Dirk Hohndel
d78e6a4876 Change event symbol to bigger yellow triangle with exclamation point
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-10-04 15:14:54 -07:00
Dirk Hohndel
53f809ccca Replace event text with small red triangle and tooltip
We draw a little red triangle (of hardcoded size - not sure if this SHOULD
scale with the size of the plot... I like it better if it doesn't) to the
left of an event.

We then maintain an array of rectangles that each circumscribe one of
those event triangles and if the mouse pointer enters one of these
rectangles then we display (after a short delay) a tooltip with the event
text.

Manually creating these rectangles, maintaining the coordinate offset,
checking if we are inside one of these rectangles and then showing a
tooltip... this all seems like there should be gtk functions to do this by
default... but if there are then I failed to find them. So instead I
manually implemented the necessary logic.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-10-04 12:27:55 -07:00
Dirk Hohndel
b72ade0e78 Change plot routine to take a drawing_area as argument
Previously we passed in width and height and the routine itself decided to
keep 5% margin around each edge - oddly doing this with double precision,
even though this is all integer coordinates.

Instead we are now passing in a drawing_area. We are kind of abusing the
cairo_rectangle_int_t data type here - but it seemed silly to redefine a
new data type for this.
Width and height give the size of the TOTAL drawing area (as before).
x and y give the offset from the edges - so the EFFECTIVE drawing area is
width-2x and height-2y
This is in preparation for adding tooltips - those need to know the
coordinate offsets from the edges - so having this hard coded inside the
plot function didn't make sense anymore.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-10-04 12:14:26 -07:00
Dirk Hohndel
c487ea055d Distinguish internally between min pressure and end pressure
And don't artificially end dives on min pressure

This may be a problem for dive computers like Linus' Suunto Vyper Air
where the failure mode seems to be _high_ pressure readings (that's scary,
btw). If the transmitter fails at the end of the dive the pressure plot
ends with incorrect high pressure. But that's simply a bug with the dive
computer and not something that subsurface should hack around. Maybe we
should offer a way to edit the incorrect data points instead.

Always ending on the minimum pressure is definitely wrong as it causes
bogus plots when you do a valve shutdown during the dive (which means that
valid data gets plotted incorrectly).

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-09-30 06:49:24 -07:00
Dirk Hohndel
ab3c6731be Fix the profile coloring
We were missing the last sample (which is usually a fast ascent).
Also, reduced the velocity smoothing to 15 seconds as the 30 seconds were
hiding too much valid information

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-09-29 22:53:03 -07:00
Dirk Hohndel
912ce7941f Remove average depth from print
It looks confusing in black and white

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-09-28 15:53:16 -07:00
Linus Torvalds
bd0f274771 Show events on the dive profile
This is *really* ugly.  We really should just create some kind of widget
that when moused over will show the event.  Or something.  Rather than
putting text on top of other text: the events - when they happen - are
usually bunched together (PO2 warnings, max depth, fast ascent leading
to mandatory safety stop, you name it).

But at least this way we see that the data is there, even if we see it
in ugly ways.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-09-22 21:15:36 -07:00
Linus Torvalds
515a917152 Add helper function for doing depth unit calculations
.. and use it for printing too.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-09-21 12:12:54 -07:00
Linus Torvalds
fcc7a01c6e Fix array underrun when calculating velocity
That code is messy. And it was buggy. Noticed by valgrind.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-09-21 08:29:08 -07:00
Linus Torvalds
6eefcf40e6 Fix 'struct plot_info' memory leak
The plot_info was never freed, so every time you'd plot something, we'd
leak memory.

I'm running valgrind to see if there's anything bad going on.  So far it
all looks fairly benign.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-09-20 22:47:12 -07:00
Linus Torvalds
957aaf619f Fix up printing some more
Use the actual degree sign for temperatures (°F and °C), and make sure
everything uses the proper "set_source_rgb[a]()" wrappers to set the
colors.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-09-20 17:56:56 -07:00
Linus Torvalds
368623113c Print out only simplified depth profile
None of the colors, nothing like that.  Just a gray fill and a plain
black depth line.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-09-20 17:24:10 -07:00
Linus Torvalds
9cfe9aa8cd Clean up and simplify depth plot
Dirk wrote this before we have the 'plot_info' structure with the
cleaned-up dive info.  No need to maintain that separate array of depths
and seconds.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-09-20 17:17:30 -07:00
Linus Torvalds
e276b0602b Don't show the smoothed dive profile or the min/max info
It was good for debugging, it's not something we really want to show people.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-09-20 16:45:33 -07:00
Dirk Hohndel
682135838f Separate out the UI from the program logic
The following are UI toolkit specific:
gtk-gui.c   - overall layout, main window of the UI
divelist.c  - list of dives subsurface maintains
equipment.c - equipment / tank information for each dive
info.c      - detailed dive info
print.c     - printing

The rest is independent of the UI:
main.c i    - program frame
dive.c i    - creates and maintaines the internal dive list structure
libdivecomputer.c
uemis.c
parse-xml.c
save-xml.c  - interface with dive computers and the XML files
profile.c   - creates the data for the profile and draws it using cairo

This commit should contain NO functional changes, just moving code around
and a couple of minor abstractions.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-09-20 12:48:56 -07:00
Dirk Hohndel
e1171a57a7 Attempt to smooth out the velocity readings
If the velocity is slower than FAST then we look back up to 30 seconds and
calculate the velocity for the past 30 seconds instead.

For the first version I'm not doing the average of the changes but simply
the change from beginning to end.

The alternative would be to do another triangle smoothing or something
like that - but as we don't know how many samples we have in the 30 second
window, it's a little harder here.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-09-16 21:45:32 -07:00
Dirk Hohndel
d5b102bdf3 Flip tank pressure graph to show the RIGHT way
This annoyed me from the first moment Linus added the tank pressure graph.
As the pressure goes down, the graph needs to go down. Seriously.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2011-09-16 20:53:05 -07:00