|
17 | 17 | import pytz
|
18 | 18 | import kombu
|
19 | 19 | import json
|
| 20 | +import bisect |
20 | 21 |
|
21 |
| -# Set this up seperate from the logger used in this scope, so services logging messages are caught and logged into user's files. |
| 22 | +# Set this up separate from the logger used in this scope, so services logging messages are caught and logged into user's files. |
22 | 23 | _global_logger = logging.getLogger("tapiriik")
|
23 | 24 |
|
24 | 25 | _global_logger.setLevel(logging.DEBUG)
|
@@ -439,8 +440,13 @@ def _accumulateActivities(self, conn, svcActivities, no_add=False):
|
439 | 440 | if act.TZ and not hasattr(act.TZ, "localize"):
|
440 | 441 | raise ValueError("Got activity with TZ type " + str(type(act.TZ)) + " instead of a pytz timezone")
|
441 | 442 | # Used to ensureTZ() right here - doubt it's needed any more?
|
442 |
| - existElsewhere = [ |
443 |
| - x for x in self._activities if |
| 443 | + # Binsearch to find which activities actually need individual attention. |
| 444 | + # Otherwise it's O(mn^2). |
| 445 | + # self._activities is sorted most recent first |
| 446 | + relevantActivitiesStart = bisect.bisect_left(self._activities, act.StartTime + timezoneErrorPeriod) |
| 447 | + relevantActivitiesEnd = bisect.bisect_right(self._activities, act.StartTime - timezoneErrorPeriod, lo=relevantActivitiesStart) |
| 448 | + extantActIter = ( |
| 449 | + x for x in (self._activities[idx] for idx in range(relevantActivitiesStart, relevantActivitiesEnd)) if |
444 | 450 | (
|
445 | 451 | # Identical
|
446 | 452 | x.UID == act.UID
|
@@ -481,9 +487,14 @@ def _accumulateActivities(self, conn, svcActivities, no_add=False):
|
481 | 487 | and
|
482 | 488 | # Prevents closely-spaced activities of known different type from being lumped together - esp. important for manually-enetered ones
|
483 | 489 | (x.Type == ActivityType.Other or act.Type == ActivityType.Other or x.Type == act.Type or ActivityType.AreVariants([act.Type, x.Type]))
|
484 |
| - ] |
485 |
| - if len(existElsewhere) > 0: |
486 |
| - existingActivity = existElsewhere[0] |
| 490 | + ) |
| 491 | + |
| 492 | + try: |
| 493 | + existingActivity = next(extantActIter) |
| 494 | + except StopIteration: |
| 495 | + existingActivity = None |
| 496 | + |
| 497 | + if existingActivity: |
487 | 498 | # we don't merge the exclude values here, since at this stage the services have the option of just not returning those activities
|
488 | 499 | if act.TZ is not None and existingActivity.TZ is None:
|
489 | 500 | existingActivity.TZ = act.TZ
|
@@ -522,7 +533,7 @@ def _accumulateActivities(self, conn, svcActivities, no_add=False):
|
522 | 533 | act.UIDs = existingActivity.UIDs # stop the circular inclusion, not that it matters
|
523 | 534 | continue
|
524 | 535 | if not no_add:
|
525 |
| - self._activities.append(act) |
| 536 | + bisect.insort_left(self._activities, act) |
526 | 537 |
|
527 | 538 | def _determineEligibleRecipientServices(self, activity, recipientServices):
|
528 | 539 | from tapiriik.auth import User
|
|
0 commit comments