core: improve merging of cylinders pressures

When merging cylinders pressures derived from samples were taken
as maximum of the start and minimum of the end pressure, which
makes sense, since we believe that this is the same cylinder.

However, for manually entered pressures, this was not done.

Moreover, when one dive had manual pressures and the other only
pressure from samples, the manual pressure was taken. However,
that could have been the wrong one, for example if the end
pressure was manually set for the cylinder of the first part of
the dive, but not the last.

Therefore, improve merging of manuall set pressures in two ways:
1) use maximum/minimum for start/end pressure
2) if the pressure of one cylinder was manually set, but not for
   the other, complete with the sample pressure (if that exists).

Fixes #2884.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2020-10-03 17:03:28 +02:00 committed by Dirk Hohndel
parent 6f8837eca3
commit 6729428b6a
2 changed files with 40 additions and 4 deletions

View file

@ -1,4 +1,5 @@
- desktop: allow adding dives to arbitrary trips
- core: improve merging of cylinder pressures [#2884]
- desktop: respect page-up, page-down, home and end keys for selection change [#2957]
- Use pO2 from prefernces for MOD display in equipment tab
- filter: more flexible filtering system based on individual constraints

View file

@ -2227,6 +2227,39 @@ static int match_cylinder(const cylinder_t *cyl, const struct dive *dive, const
return -1;
}
/*
* Function used to merge manually set start or end pressures. This
* is used to merge cylinders when merging dives. We store up to two
* values for start _and_ end pressures: one derived from samples and
* one entered manually, whereby the latter takes precedence. It may
* happen that the user merges two dives where one has a manual,
* the other only a sample-derived pressure. In such a case we want to
* supplement the non-existing manual value by a sample derived one.
* Otherwise, the merged dive would end up with incomplete pressure
* information.
* The last argument to the function specifies whether the larger
* or smaller value of the two dives should be returned. Obviously,
* for the starting pressure we want the larger and for the ending
* pressure the smaller value.
*/
static pressure_t merge_pressures(pressure_t a, pressure_t sample_a, pressure_t b, pressure_t sample_b, bool take_min)
{
if (!a.mbar && !b.mbar)
return a;
if (!a.mbar)
a = sample_a;
if (!b.mbar)
b = sample_b;
if (!a.mbar)
a = b;
if (!b.mbar)
b = a;
if (take_min && a.mbar < b.mbar)
return a;
else
return b;
}
/*
* We matched things up so that they have the same gasmix and
* use, but we might want to fill in any missing cylinder details
@ -2240,10 +2273,12 @@ static void merge_one_cylinder(cylinder_t *a, const cylinder_t *b)
a->type.workingpressure.mbar = b->type.workingpressure.mbar;
if (empty_string(a->type.description))
a->type.description = copy_string(b->type.description);
if (!a->start.mbar)
a->start.mbar = b->start.mbar;
if (!a->end.mbar)
a->end.mbar = b->end.mbar;
/* If either cylinder has manually entered pressures, try to merge them.
* Use pressures from divecomputer samples if only one cylinder has such a value.
* Yes, this is an actual use case we encountered. */
a->start = merge_pressures(a->start, a->sample_start, b->start, b->sample_start, false);
a->end = merge_pressures(a->end, a->sample_end, b->end, b->sample_end, true);
if (a->sample_start.mbar && b->sample_start.mbar)
a->sample_start.mbar = a->sample_start.mbar > b->sample_start.mbar ? a->sample_start.mbar : b->sample_start.mbar;