mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
Be much saner about merging dive computer data
Now that we have dive computer device ID fields etc, we can do a much better job of merging the dive computer data. The rule is - if we actually merge two disjoint dives (ie extended surface interval causing the dive computer to think the dive ended and turning two of those dives into one), find the *matching* dive computer from the other dive to combine with. - if we are merging dives at the same time, discard old-style data with no dive computer info (ie act like a re-download) - if we have new-style dive computers with identifiers, take them all. which seems to work fairly well. There's more tweaking to be done, but I think this is getting to the point where it largely works. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
parent
7bfc8de55e
commit
42240a83ff
1 changed files with 109 additions and 34 deletions
143
dive.c
143
dive.c
|
@ -1147,6 +1147,110 @@ static void remove_redundant_dc(struct divecomputer *dc)
|
|||
} while (dc);
|
||||
}
|
||||
|
||||
static void clear_dc(struct divecomputer *dc)
|
||||
{
|
||||
memset(dc, 0, sizeof(*dc));
|
||||
}
|
||||
|
||||
static struct divecomputer *find_matching_computer(struct divecomputer *match, struct divecomputer *list)
|
||||
{
|
||||
struct divecomputer *p;
|
||||
|
||||
while ((p = list) != NULL) {
|
||||
list = list->next;
|
||||
|
||||
/* No dive computer model? That matches anything */
|
||||
if (!match->model || !p->model)
|
||||
break;
|
||||
|
||||
/* Otherwise at least the model names have to match */
|
||||
if (strcasecmp(match->model, p->model))
|
||||
continue;
|
||||
|
||||
/* No device ID? Match */
|
||||
if (!match->deviceid || !p->deviceid)
|
||||
break;
|
||||
|
||||
if (match->deviceid == p->deviceid)
|
||||
break;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* Join dive computers with a specific time offset between
|
||||
* them.
|
||||
*
|
||||
* Use the dive computer ID's (or names, if ID's are missing)
|
||||
* to match them up. If we find a matching dive computer, we
|
||||
* merge them. If not, we just take the data from 'a'.
|
||||
*/
|
||||
static void interleave_dive_computers(struct divecomputer *res,
|
||||
struct divecomputer *a, struct divecomputer *b, int offset)
|
||||
{
|
||||
do {
|
||||
struct divecomputer *match;
|
||||
|
||||
res->model = strdup(a->model);
|
||||
res->deviceid = a->deviceid;
|
||||
res->diveid = a->diveid;
|
||||
res->next = NULL;
|
||||
|
||||
match = find_matching_computer(a, b);
|
||||
if (match) {
|
||||
merge_events(res, a, match, offset);
|
||||
merge_samples(res, a, match, offset);
|
||||
} else {
|
||||
res->sample = a->sample;
|
||||
res->samples = a->samples;
|
||||
res->events = a->events;
|
||||
a->sample = NULL;
|
||||
a->samples = 0;
|
||||
a->events = NULL;
|
||||
}
|
||||
a = a->next;
|
||||
if (!a)
|
||||
break;
|
||||
res->next = calloc(1, sizeof(struct divecomputer));
|
||||
res = res->next;
|
||||
} while (res);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Join dive computer information.
|
||||
*
|
||||
* If we have old-style dive computer information (no model
|
||||
* name etc), we will prefer a new-style one and just throw
|
||||
* away the old. We're assuming it's a re-download.
|
||||
*
|
||||
* Otherwise, we'll just try to keep all the information.
|
||||
*/
|
||||
static void join_dive_computers(struct divecomputer *res, struct divecomputer *a, struct divecomputer *b)
|
||||
{
|
||||
if (a->model && !b->model) {
|
||||
*res = *a;
|
||||
clear_dc(a);
|
||||
return;
|
||||
}
|
||||
if (b->model && !a->model) {
|
||||
*res = *b;
|
||||
clear_dc(b);
|
||||
return;
|
||||
}
|
||||
|
||||
*res = *a;
|
||||
clear_dc(a);
|
||||
while (res->next)
|
||||
res = res->next;
|
||||
|
||||
res->next = calloc(1, sizeof(*res));
|
||||
*res->next = *b;
|
||||
clear_dc(b);
|
||||
|
||||
remove_redundant_dc(res);
|
||||
}
|
||||
|
||||
struct dive *merge_dives(struct dive *a, struct dive *b, int offset, gboolean prefer_downloaded)
|
||||
{
|
||||
struct dive *res = alloc_dive();
|
||||
|
@ -1188,41 +1292,12 @@ struct dive *merge_dives(struct dive *a, struct dive *b, int offset, gboolean pr
|
|||
* we free it - so make sure the source
|
||||
* dive computer data is cleared out.
|
||||
*/
|
||||
memset(&dl->dc, 0, sizeof(dl->dc));
|
||||
} else if (offset) {
|
||||
struct divecomputer *a_dc = &a->dc;
|
||||
struct divecomputer *b_dc = &b->dc;
|
||||
struct divecomputer *res_dc = &res->dc;
|
||||
clear_dc(&dl->dc);
|
||||
} else if (offset)
|
||||
interleave_dive_computers(&res->dc, &a->dc, &b->dc, offset);
|
||||
else
|
||||
join_dive_computers(&res->dc, &a->dc, &b->dc);
|
||||
|
||||
/*
|
||||
* FIXME! We should try to match these things up some way,
|
||||
* now we just depend on the merged dives having the same
|
||||
* dive computers in the same order!
|
||||
*/
|
||||
for (;;) {
|
||||
merge_events(res_dc, a_dc, b_dc, offset);
|
||||
merge_samples(res_dc, a_dc, b_dc, offset);
|
||||
a_dc = a_dc->next;
|
||||
b_dc = b_dc->next;
|
||||
if (!a_dc || !b_dc)
|
||||
break;
|
||||
res_dc->next = calloc(1, sizeof(*res_dc));
|
||||
res_dc = res_dc->next;
|
||||
if (!res_dc)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
struct divecomputer *dc;
|
||||
res->dc = a->dc;
|
||||
memset(&a->dc, 0, sizeof(a->dc));
|
||||
dc = &res->dc;
|
||||
while (dc->next)
|
||||
dc = dc->next;
|
||||
dc->next = calloc(1, sizeof(*dc));
|
||||
*dc->next = b->dc;
|
||||
memset(&b->dc, 0,sizeof(b->dc));
|
||||
remove_redundant_dc(&res->dc);
|
||||
}
|
||||
fixup_dive(res);
|
||||
return res;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue