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);
|
} 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 *merge_dives(struct dive *a, struct dive *b, int offset, gboolean prefer_downloaded)
|
||||||
{
|
{
|
||||||
struct dive *res = alloc_dive();
|
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
|
* we free it - so make sure the source
|
||||||
* dive computer data is cleared out.
|
* dive computer data is cleared out.
|
||||||
*/
|
*/
|
||||||
memset(&dl->dc, 0, sizeof(dl->dc));
|
clear_dc(&dl->dc);
|
||||||
} else if (offset) {
|
} else if (offset)
|
||||||
struct divecomputer *a_dc = &a->dc;
|
interleave_dive_computers(&res->dc, &a->dc, &b->dc, offset);
|
||||||
struct divecomputer *b_dc = &b->dc;
|
else
|
||||||
struct divecomputer *res_dc = &res->dc;
|
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);
|
fixup_dive(res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue