mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
core: move merge_dives() functios to struct dive_table
These functions have to access other dives in the list to calculate CNS, etc, so let's call them from there. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
8ec1f008ab
commit
4d7291d4a1
6 changed files with 178 additions and 163 deletions
|
|
@ -1149,3 +1149,124 @@ std::array<std::unique_ptr<dive>, 2> dive_table::split_dive_at_time(const struct
|
|||
return {};
|
||||
return split_dive_at(dive, static_cast<int>(idx), static_cast<int>(idx - 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Pick a trip for a dive
|
||||
*/
|
||||
static struct dive_trip *get_preferred_trip(const struct dive *a, const struct dive *b)
|
||||
{
|
||||
dive_trip *atrip, *btrip;
|
||||
|
||||
/* If only one dive has a trip, choose that */
|
||||
atrip = a->divetrip;
|
||||
btrip = b->divetrip;
|
||||
if (!atrip)
|
||||
return btrip;
|
||||
if (!btrip)
|
||||
return atrip;
|
||||
|
||||
/* Both dives have a trip - prefer the non-autogenerated one */
|
||||
if (atrip->autogen && !btrip->autogen)
|
||||
return btrip;
|
||||
if (!atrip->autogen && btrip->autogen)
|
||||
return atrip;
|
||||
|
||||
/* Otherwise, look at the trip data and pick the "better" one */
|
||||
if (atrip->location.empty())
|
||||
return btrip;
|
||||
if (btrip->location.empty())
|
||||
return atrip;
|
||||
if (atrip->notes.empty())
|
||||
return btrip;
|
||||
if (btrip->notes.empty())
|
||||
return atrip;
|
||||
|
||||
/*
|
||||
* Ok, so both have location and notes.
|
||||
* Pick the earlier one.
|
||||
*/
|
||||
if (a->when < b->when)
|
||||
return atrip;
|
||||
return btrip;
|
||||
}
|
||||
|
||||
/*
|
||||
* Merging two dives can be subtle, because there's two different ways
|
||||
* of merging:
|
||||
*
|
||||
* (a) two distinctly _different_ dives that have the same dive computer
|
||||
* are merged into one longer dive, because the user asked for it
|
||||
* in the divelist.
|
||||
*
|
||||
* Because this case is with the same dive computer, we *know* the
|
||||
* two must have a different start time, and "offset" is the relative
|
||||
* time difference between the two.
|
||||
*
|
||||
* (b) two different dive computers that we might want to merge into
|
||||
* one single dive with multiple dive computers.
|
||||
*
|
||||
* This is the "try_to_merge()" case, which will have offset == 0,
|
||||
* even if the dive times might be different.
|
||||
*
|
||||
* If new dives are merged into the dive table, dive a is supposed to
|
||||
* be the old dive and dive b is supposed to be the newly imported
|
||||
* dive. If the flag "prefer_downloaded" is set, data of the latter
|
||||
* will take priority over the former.
|
||||
*
|
||||
* The trip the new dive should be associated with (if any) is returned
|
||||
* in the "trip" output parameter.
|
||||
*
|
||||
* The dive site the new dive should be added to (if any) is returned
|
||||
* in the "dive_site" output parameter.
|
||||
*/
|
||||
merge_result dive_table::merge_dives(const struct dive &a_in, const struct dive &b_in, int offset, bool prefer_downloaded) const
|
||||
{
|
||||
merge_result res = { };
|
||||
|
||||
const dive *a = &a_in;
|
||||
const dive *b = &b_in;
|
||||
if (is_dc_planner(&a->dcs[0]))
|
||||
std::swap(a, b);
|
||||
|
||||
res.dive = dive::create_merged_dive(*a, *b, offset, prefer_downloaded);
|
||||
|
||||
/* The CNS values will be recalculated from the sample in fixup_dive() */
|
||||
res.dive->cns = res.dive->maxcns = 0;
|
||||
|
||||
res.trip = get_preferred_trip(a, b);
|
||||
|
||||
/* we take the first dive site, unless it's empty */
|
||||
res.site = a->dive_site && !a->dive_site->is_empty() ? a->dive_site : b->dive_site;
|
||||
if (!dive_site_has_gps_location(res.site) && dive_site_has_gps_location(b->dive_site)) {
|
||||
/* we picked the first dive site and that didn't have GPS data, but the new dive has
|
||||
* GPS data (that could be a download from a GPS enabled dive computer).
|
||||
* Keep the dive site, but add the GPS data */
|
||||
res.site->location = b->dive_site->location;
|
||||
}
|
||||
fixup_dive(*res.dive);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* This could do a lot more merging. Right now it really only
|
||||
* merges almost exact duplicates - something that happens easily
|
||||
* with overlapping dive downloads.
|
||||
*
|
||||
* If new dives are merged into the dive table, dive a is supposed to
|
||||
* be the old dive and dive b is supposed to be the newly imported
|
||||
* dive. If the flag "prefer_downloaded" is set, data of the latter
|
||||
* will take priority over the former.
|
||||
*
|
||||
* Attn: The dive_site parameter of the dive will be set, but the caller
|
||||
* still has to register the dive in the dive site!
|
||||
*/
|
||||
struct std::unique_ptr<dive> dive_table::try_to_merge(const struct dive &a, const struct dive &b, bool prefer_downloaded) const
|
||||
{
|
||||
if (!a.likely_same(b))
|
||||
return {};
|
||||
|
||||
auto [res, trip, site] = merge_dives(a, b, 0, prefer_downloaded);
|
||||
res->dive_site = site; /* Caller has to call site->add_dive()! */
|
||||
return std::move(res);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue