Commit graph

156 commits

Author SHA1 Message Date
Michael Keller
6002387d7b Desktop: Add Multi-Tank Support for Profile Ruler.
Add support for tracking the gas usage across multiple tanks to the 'bar
used' and SAC values shown for the profile ruler.
The following rules are implemented:
- a tank is considered 'used' if at least one bar has been consumed;
- only used tanks are taken into account for calculations;
- 'bar used' is only shown if all tanks used have the same (or unknown)
  volume;
- SAC is only shown if all tanks used have a known volume.

Fixes #3902.

Reported-by: @pabdakine
Signed-off-by: Michael Keller <github@ike.ch>
2023-05-30 11:21:12 +02:00
Michael Andreen
9e95746797 profile: Fix so min pressure is not always 0
Signed-off-by: Michael Andreen <michael@andreen.dev>
2023-05-23 13:12:48 +02:00
Michael Andreen
7217506072 profile: Use all sensors to scale the pressure graph
It's possible for the first sensor to start with a pressure
significantly lower than other sensors.

Signed-off-by: Michael Andreen <michael@andreen.dev>
2023-05-23 13:12:48 +02:00
Berthold Stoeger
9f455b1457 selection: move current dive and divecomputer to selection.cpp
This tries to encapsulate the management of the current dive and
divecomputer in the selection code. The current dive is alreay
set by setSelection(). Add a new parameter to also set the
current divecomputer. If -1 is passed, then the current
computer number is remained. This will allow us to audit the code.
Because for now, the whole "current dive computer" thing seems
to be ill-defined.

This fixes a bug: the dive-computer number wasn't validated
when making a new dive the current dive. The new code has some
drawbacks though: when selecting a whole trip, the validation
will be called for all dives in the trip and thus the dive computer
number will depend on the dive with the lowest amount of dive
computers in the trip. This will need to be fixed.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2023-04-16 20:23:59 +02:00
Robert C. Helling
741099bdbb Show correct gas density in CCR mode
When collecting the data for the infobox, we have
already computed the current partial pressures of the
breathing gas taking into accoutn the divemode. Use
those rather than fractions (which for CCR mode are
those of diluent) to compute the gas density.

Reported-by: Pietro Tranquillini <p.tranquillini@gmail.com>
Signed-off-by: Robert C. Helling <helling@atdotde.de>
2022-11-08 10:43:47 -08:00
Robert C. Helling
34b61ad288 Use 10ft as deco step size in imperial units in profile
The calculation of the deco steps shown in the profile
infobox is somewhat independent of the planner. When
set to imperial units, the distance between deco stops
should be 10ft rather than 3m as 15m is only 49ft.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
2022-05-06 14:17:29 -07:00
Michael Andreen
386a3a35bc profile: Plot sensor data from other dive computers
If the current dive computer doesn't have a sensor for the cylinder then
check if another dive computer has sensor data available and use that
for the plot.

Signed-off-by: Michael Andreen <michael@andreen.dev>
2022-03-26 07:32:50 -07:00
Berthold Stoeger
f9b9582a64 core: fold display.h into profile.h
The only things in display.h were profile related, so the
split between these two files is not comprehensible.
In fact profile.h includes display.h, because it needs the
struct defined therein. Let's just merge these two files.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2022-03-13 15:07:33 -07:00
Berthold Stoeger
04241ebb9d core: remove select_dc() function
The only caller misused this function to get access to the
current divecomputer. Remove it, since selection of the
current divecomputer is handled by the MainWindow.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2022-03-13 15:07:33 -07:00
Berthold Stoeger
2645fa1495 profile: remove fast argument of create_plot_info_new()
This prevented calculation of the pressure data when dragging
planner handles. However, this lead to weird artifacts.

As an alternative, if this turns out to be too slow, we might
disable the plotting of the pressure curves instead.

That said, even on my super-slow fanless laptop, this performs
reasonably.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
725fda3cd1 profile: don't add excessive depth
The old get_maxdepth() function in profile.c was accounting for
two things:
- the partial pressure graphs
- rounding to sane value

Both are now taken care of by the profile itself. This leads to
excessive max-depths. Remove the code from profile.c.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
789eb2c620 profile: clear plot_info structure when freeing data
free_plot_info_data() frees the sample and pressure arrays
and accordingly sets the corresponding pointers to NULL.

However, it doesn't clear the element-count and thus leaves
the structure in an inconsistent state.

Clear the whole structure with memset(). I am not a fan of
doing so, but there are existing memset() calls in the
same source file, so let's keep it like that for consistency.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
01af4bcd00 profile: remove min/max entries from plot_data
These were the minimum and maximum of a 9-min window.
The profile now uses an adaptive peak-search, so this is not
used anymore.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
24cf6709e3 profile: simplify get_maxtime()
This function has accumulated quite some cruft. It seems to add
additional space to make place for certain chart features
(e.g. the average depth text item).

However, it makes no sense to solve this here, as only the
profile knows how much place is needed to display these
features.

Therefore, basically revert this to the original version,
which simply returns the maximum time for long dives
and a threshhold for short dives that depends on the
zoomed_plot setting.

The result looks more reasonable to me, as there is no
(varying!) empty space to the right of the profile.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Robert C. Helling
9fd531dcc5 Round gas depth properly
The D in MOD, EAD, END, and EADD stands for "depth" and
as such these should be mm in int rather than double.

The intermediate fn2 and fhe2, however, as intermediate
value should not be rounded to an integer.

The upshot of this is a litle more numerical stability.
It should lead to more stable values in TestProfile
when run on architectures with different floating
point precision.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
2021-12-06 22:29:04 +01:00
Josh Torres
7e6d9935f1 core: fix off-by-one causing incorrect profile display
In commit 4724c88 get_plot_details_new was updated to pass an index
instead of the entry into plot_string. This means we are passing "i" to
plot_string after the final increment of the for loop, instead of
getting the entry[i] within the loop before the final increment. This
means if we are mousing over the far right of the graph, where the time
based break is not hit, we will end up passing an index equal to nr-2
instead of nr-3, which is intended to shave off the final two rows
containing data not useful to the display.

There are a handful of ways to fix this. This commit intends to be
consistent with stylistic choices made elsewhere in the project.

Signed-off-by: Josh Torres <torres.josh.j@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-09-06 13:00:37 -07:00
Berthold Stoeger
7e11a35371 core: add a special NO_SENSOR value for sample::sensor
The sensor member of sample refers to a cylinder from which
the pressure was read. However, some dives don't even have
a cylinder. Therefore, introduce a special NO_SENSOR value
for these dives. Since the cylinder is given as a uint8_t,
0xff seems to be a sensible choice.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-07-19 10:13:51 -07:00
Berthold Stoeger
d0494beb5f planner: fix deco calculation
In 9bfc6d252, testing of the planner was changed to use the
planner_ds parameter instead of a global variable.

Unfortunately, two conditionals were inverted, leading to
an erroneous ceiling calculation when in the planner.

Restore the proper conditions. Moreover, instead of testing
the planner_ds parameter, use the already existing in_planner
flag, which is derived from said parameter.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-03-24 10:30:22 -07:00
Robert C. Helling
345959177f Max ceiling precision
We used to round the ceilings for the individual tissues with
%.1f but the maximal (and thus effective) ceiling only with
%.0f. This makes no sense or be rounded up (to the conservative
side).

This commit shows also the maximal ceiling with higher accuracy.

Reported-by: Peter Hübner
Signed-off-by: Robert C. Helling <helling@atdotde.de>
2021-03-01 21:33:25 +01:00
Berthold Stoeger
642d9c80b3 planner: pass in_planner argument to decoMode()
To remove reliance on global state, pass an "in_planner" argument
to decoMode(). Thus, calls to in_planner() can be removed.

This is a more-or-less automated change. Ultimately it would
probably be better to pass the current deco-mode to the affected
functions instead of calling decoMode() with an in_planner
parameter.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-17 07:26:55 -08:00
Berthold Stoeger
8103e947aa planner: pass in_planner argument to vpmb_next_gradient()
To remove reliance on global state, pass an "in_planner" argument
to vpmb_next_gradient(). Thus, calls to in_planner() can be removed.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-17 07:26:55 -08:00
Berthold Stoeger
93ecad1b04 planner: pass in_planner argument to add_segment()
To remove reliance on global state, pass an "in_planner" argument
to add_segment(). Thus, calls to in_planner() can be removed.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-17 07:26:55 -08:00
Berthold Stoeger
9fb37ea27f planner: remove print_mode parameter from calculate_deco_information()
Only 'false' was ever passed as value.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-17 07:26:55 -08:00
Berthold Stoeger
84f48b7290 cleanup: constify create_plot_info_new()
This only read accesses the dive and constructs a plot-info
structure. Make the dive parameter const.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20 10:01:50 -08:00
Berthold Stoeger
1a0f6f53ed undo: set dive mode to CCR in undo command, not profile code
When setting a CCR setpoint, the profile code(!) would turn
the dive into a CCR dive. Not only should the display layer
not alter dives, this also means that the action is not
undoable.

Move that to the appropriate undo command, where it makes
more sense, but obviously also makes things more complicated.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-11 09:31:36 -08:00
Dirk Hohndel
6add24fe3e mobile: enable deco information calculation on mobile
This simply allows us to calculate the information, it doesn't do
anything to actually display it, yet.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-01-10 15:57:39 -08:00
Berthold Stoeger
88c6ce988d profile: pass dive to RulerItem
Instead of accessing the global displayed_dive variable
in RulerItem, pass the dive. This is a step in making the
profile reentrant.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-10 15:57:39 -08:00
Berthold Stoeger
54e8fe5d9e profile: pass dive to ToolTipItem::refresh()
Don't access the global displayed_dive variable in a step
to make the profile reentrant.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-10 15:57:39 -08:00
Berthold Stoeger
09287809eb profile: move adding of ceiling-violation-event
The profile item that shows the ceilings adds a warning event
if the ceiling is violated. This is very unfortunate.

Improve this situation by adding the event up to the function
that calculates the ceiling. This is still not how it should
be - the display layer should not modify the dive that it
displays.

To make this clear, add a comment that details that this
is a contract between planner and display layer: The planner
uses a dive that can be trampled upon by the profile.
Still, this should be solved differently.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-10 15:57:39 -08:00
Berthold Stoeger
9bfc6d2520 profile: use a parameter to determine planner state
The in_planner() function is incompatible with a reentrant
profile, since it accesses a global variable. In
create_plot_info_new() it is essentially redundant, because
there is a planner_ds (ds = deco_state) parameter that
is used only when in the planner. Therefore use that as
the in_planner indicator: when non-null, the profile is
showing a planned dive.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-10 15:57:39 -08:00
Berthold Stoeger
94a57d9a1d cleanup: make calculate_deco_information() of static linkage
This function was not used outside of profile.c

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-10 15:57:39 -08:00
Berthold Stoeger
f728923c79 cleanup: move interpolate inline function to its own header file
This is not really related to struct dive, so let's move it.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-10-25 13:59:52 -07:00
Berthold Stoeger
0e196310f9 cleanup: split out divecomputer functions from dive.c
Since dive.c is so huge, split out divecomputer-related functions
into divecomputer.[c|h], sample.[c|h] and extradata.[c|h].

This does not give huge compile time improvements, since
struct dive contains a struct divecomputer and therefore
dive.h has to include divecomputer.h. However, it make things
distinctly more clear.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-10-25 13:59:52 -07:00
Berthold Stoeger
8212acc992 cleanup: break out event-related code into event.[c|h]
In an effort to reduce the size of dive.h and dive.c, break out
the event related functions. Moreover event-names were handled
by the profile-code, collect that also in the new source files.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-10-25 13:59:52 -07:00
Berthold Stoeger
c8334ad11b cleanup: make analyze_plot_info local to profile.c
No external caller of this function exists. Moreover, turn the return
type to void, as it only returned the passed-in plot_info and no
caller used that.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-01 08:53:45 -07:00
Berthold Stoeger
21e2488d2d cleanup: const-ify a few functions in planner.c
It make debugging much easier if the function signature tells you
that a parameter is not altered.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-01 08:53:45 -07:00
Berthold Stoeger
d787e8812c profile: for maxtime calculation include the sample after the last event
When plotting profiles with surface segments, there were strange
artifacts. As we found out with Robert, these were due to the fact
that the calculated maxtime was set to the last event which is just one
second inside the surface segment. This terribly confused the profile
code. For example, it didn't properly allocate samples for the surface
segment.

Thus, when calculating maxtime, consider the last sample beyond the
last event.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-01 12:36:28 +02:00
Berthold Stoeger
d81df0dd19 profile: avoid invalid accesses in setup_gas_sensor_pressure
Since we removed MAX_CYLINDERS, we have the possibility of dives
with no cylinders. In such a case, setup_gas_sensor_pressure()
would do invalid read- and write-accesses. Therefore, return
early in such a case.

Reported-by: Chirana Gheorghita Eugeniu Theodor <office@adaptcom.ro>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-04-20 12:59:06 -07:00
Dirk Hohndel
f9f4a9c232 debug output: ensure our debug output is captured on Android
I would have bet money that Android used to send stderr to the logcat
log, but apparently it doesn't (anymore?). So in order to be able to
have a chance to debug weird cloud storage issues on Android, let's do
some wholesale replacement of fprintf(stderr,...) with our own version
of the INFO macro that we long ago borrowed from libdivecomputer (and
rename it to ensure we don't have a conflict there).

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-04-18 09:00:21 -07:00
Berthold Stoeger
b1f8b6b950 profile: avoid double-free when reusing plot_info
free_plot_info_data() freed the pressure-data, but didn't set the
value to NULL. Thus, when the plot_info was reused, a double-free()
could ensue.

Crash condition: export the profiles of multiple dives with pressure
data.

Reported-by: Willem Ferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-04-18 11:17:32 +02:00
Berthold Stoeger
48b4dc9c84 cleanup: remove commented-out evn_foreach() function
Apparently this was used to hide events in pre-Qt times. However,
that has already been reimplemented in different ways. Let's remove
that commented-out code.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-04-07 00:13:35 +02:00
Robert C. Helling
285fa8acbc Grammar: replaces 'indexes' by 'indices'
Grammar-nazi ran

git grep -l 'indexes' | xargs sed -i '' -e 's/indexes/indices/g'

to prevent future wincing when reading the source code.

Unfortunatly, Qt itself is infected as in
QModelIndexList QItemSelection::indexes() const

Signed-off-by: Robert C. Helling <helling@atdotde.de>
2020-03-11 08:26:30 -07:00
Robert C. Helling
33e49637ec Add current GF to infobox
As per request from users on scubaforum.com, this adds
the current gradient factor to the deco information of
the infobox. Up to now, this information was only
graphically represented in the pressure bar graph
and the heatmap. This gives a numerical value.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
2019-11-28 12:23:04 -08:00
Robert C. Helling
28db9ede41 Don't access uninitialized deco_structure
Coverty found that in the export functions, we initialize
the planner deco state with NULL and then possibly later
access its content. This makes sure, we don't do that.

Let's see if this makes Coverty happy or I missed somehting
else.

Fixes CID 350736
Fixes CID 350735

Signed-off-by: Robert C. Helling <helling@atdotde.de>
2019-11-16 12:34:30 -08:00
Berthold Stoeger
b850384100 Profile: fix pressure scale
The determination of minimum pressure in calculate_max_limits_new()
in profile.c was wrong for a long time. Since the loop went over all
cylinders (even unused ones), the minimum pressure was always zero.

Since we loop only over used cylinders, the minimum pressure was
initialized to the lowest starting pressure of any cylinder.

If there were no events with pressure change, the minimum pressure
stayed unchanged, resulting in a funky scaling.

Instead, let's initialize the minimum pressure to the lowest ending
pressure.

Reported-by: Willem Ferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-12 07:00:37 +01:00
Berthold Stoeger
794066b236 Cylinders: access cylinders with get_cylinder()
Instead of accessing the cylinder table directly, use the get_cylinder()
function. This gives less unwieldy expressions. But more importantly,
the function does bound checking. This is crucial for now as the code
hasn't be properly audited since the change to arbitrarily sized
cylinder tables. Accesses of invalid cylinder indexes may lead to
silent data-corruption that is sometimes not even noticed by
valgrind. Returning NULL instead of an invalid pointer will make
debugging much easier.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-09 19:19:04 +01:00
Berthold Stoeger
7c9f46acd2 Core: remove MAX_CYLINDERS restriction
Instead of using fixed size arrays, use a new cylinder_table structure.
The code copies the weightsystem code, but is significantly more complex
because cylinders are such an integral part of the core.

Two functions to access the cylinders were added:
get_cylinder() and get_or_create_cylinder()
The former does a simple array access and supposes that the cylinder
exists. The latter is used by the parser(s) and if a cylinder with
the given id does not exist, cylinders up to that id are generated.

One point will make C programmers cringe: the cylinder structure is
passed by value. This is due to the way the table-macros work. A
refactoring of the table macros is planned. It has to be noted that
the size of a cylinder_t is 64 bytes, i.e. 8 long words on a 64-bit
architecture, so passing on the stack is probably not even significantly
slower than passing as reference.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-09 19:19:04 +01:00
Berthold Stoeger
05a5a06fd3 Profile: dynamically allocate gases array
To calculate sac rates, an array of used gases for every point on the
profile was used. This was implemented using unsigned int bitfields.

While nobody sane will ever use 32 or even 64 cylinders, for consistency
with the rest of the code, also change this to use dynamically
allocated arrays.

But allocate only once per shown profile, not once per sample.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-09 19:19:04 +01:00
Berthold Stoeger
00289cd222 Profile: dynamically allocate plot pressure data
All accesses to the pressure data were converted to use functions.
Therefore it is now rather trivial to dynamically allocate the
pressure array and just change the functions.

The only thing to take care of is the idiosyncratic memory
management. Make sure to free and copy the buffer in the
appropriate places.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-09 19:19:04 +01:00
Berthold Stoeger
7e1425796d Profile: turn INSERT_ENTRY macro into helper function
The only apparent reason that this was a macro is that it automatically
increased the "index" and "entry" counts. But incrementing these explicitly
seems reasonable.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-09 19:19:04 +01:00