[locations] Refactor has moved to not use multiple points

This commit is contained in:
2024-03-12 16:57:56 -04:00
parent 0fff2ec388
commit df1bfd4177
3 changed files with 28 additions and 59 deletions

View File

@ -1,4 +1,4 @@
from decimal import Decimal from decimal import Decimal, getcontext
import logging import logging
from typing import Dict from typing import Dict
from uuid import uuid4 from uuid import uuid4
@ -91,47 +91,37 @@ class GeoLocation(ScrobblableMixin):
abs(Decimal(old_lat_lon[1]) - Decimal(self.lon)), abs(Decimal(old_lat_lon[1]) - Decimal(self.lon)),
) )
def has_moved(self, past_points: list["GeoLocation"]) -> bool: def has_moved_for_user(self, user_id: int) -> bool:
"""GPS jumps from time to time. This function tries to smooth out
when we appear to have flagging our location as having not moved if one of our last
3"""
has_moved = False has_moved = False
has_moved_locs = [] user = User.objects.filter(id=user_id).first()
for point in past_points: if not user:
loc_diff = self.loc_diff((point.lat, point.lon)) return False
loc_has_moved = False
if (
loc_diff[0] > GEOLOC_PROXIMITY
or loc_diff[1] > GEOLOC_PROXIMITY
):
loc_has_moved = True
logger.info(
f"[locations] checked whether location has moved against proximity setting",
extra={
"location": self,
"loc_diff": loc_diff,
"loc_has_moved": loc_has_moved,
"point": point,
"geoloc_proximity": GEOLOC_PROXIMITY,
},
)
has_moved_locs.append(loc_has_moved)
# Sum up all True values, if they're more than half of our locations, we've moved last_point = (
if sum(has_moved_locs) > int(len(past_points) / 2): user.scrobble_set.filter(media_type="GeoLocation")
.order_by("-timestamp")
.first()
).media_obj
if not last_point:
return True
loc_diff = self.loc_diff((last_point.lat, last_point.lon))
if loc_diff[0] > GEOLOC_PROXIMITY or loc_diff[1] > GEOLOC_PROXIMITY:
has_moved = True has_moved = True
logger.info( logger.debug(
f"[locations] finished checking for movement", f"[locations] checked whether location has moved against proximity setting",
extra={ extra={
"location": self,
"loc_diff": loc_diff,
"has_moved": has_moved, "has_moved": has_moved,
"has_moved_locs": has_moved_locs, "point": last_point,
"past_points": past_points, "geoloc_proximity": GEOLOC_PROXIMITY,
}, },
) )
return has_moved return has_moved
def in_proximity(self, named=True) -> models.QuerySet: def in_proximity(self, named=False) -> models.QuerySet:
lat_min = Decimal(self.lat) - GEOLOC_PROXIMITY lat_min = Decimal(self.lat) - GEOLOC_PROXIMITY
lat_max = Decimal(self.lat) + GEOLOC_PROXIMITY lat_max = Decimal(self.lat) + GEOLOC_PROXIMITY
lon_min = Decimal(self.lon) - GEOLOC_PROXIMITY lon_min = Decimal(self.lon) - GEOLOC_PROXIMITY
@ -143,12 +133,5 @@ class GeoLocation(ScrobblableMixin):
lat__gte=lat_min, lat__gte=lat_min,
lon__lte=lon_max, lon__lte=lon_max,
lon__gte=lon_min, lon__gte=lon_min,
) ).exclude(id=self.id)
logger.info(
f"[locations] finished looking for proximate locations",
extra={
"close_locations": close_locations,
"is_title_null": is_title_null,
},
)
return close_locations return close_locations

View File

@ -50,8 +50,8 @@ def test_found_in_proximity_location():
close = GeoLocation.objects.create( close = GeoLocation.objects.create(
lat=lat + 0.0001, lon=lon - 0.0001, altitude=60 lat=lat + 0.0001, lon=lon - 0.0001, altitude=60
) )
assert close not in loc.in_proximity() assert close not in loc.in_proximity(named=True)
assert close in loc.in_proximity(named=False) assert close in loc.in_proximity()
@pytest.mark.django_db @pytest.mark.django_db
@ -63,7 +63,7 @@ def test_not_found_in_proximity_location():
far = GeoLocation.objects.create( far = GeoLocation.objects.create(
lat=lat + 0.0002, lon=lon - 0.0001, altitude=60 lat=lat + 0.0002, lon=lon - 0.0001, altitude=60
) )
assert far not in loc.in_proximity(named=False) assert far not in loc.in_proximity()
@pytest.mark.django_db @pytest.mark.django_db

View File

@ -932,10 +932,7 @@ class Scrobble(TimeStampedModel):
) )
return scrobble return scrobble
jitter_correction_locations = cls.past_scrobbled_locations( has_moved = location.has_moved(scrobble.user.id)
user_id, POINTS_FOR_MOVEMENT_HISTORY
)
has_moved = location.has_moved(jitter_correction_locations)
logger.info( logger.info(
f"[scrobbling] checking - has last location has moved?", f"[scrobbling] checking - has last location has moved?",
extra={ extra={
@ -944,7 +941,6 @@ class Scrobble(TimeStampedModel):
"media_type": cls.MediaType.GEO_LOCATION, "media_type": cls.MediaType.GEO_LOCATION,
"media_id": location.id, "media_id": location.id,
"has_moved": has_moved, "has_moved": has_moved,
"past_locations_used": jitter_correction_locations,
}, },
) )
if not has_moved: if not has_moved:
@ -986,16 +982,6 @@ class Scrobble(TimeStampedModel):
) )
return scrobble return scrobble
@classmethod
def past_scrobbled_locations(
cls, user_id: int, num: int
) -> list["Location"]:
past_scrobbles = cls.objects.filter(
media_type="GeoLocation",
user_id=user_id,
).order_by("-timestamp")[1:num]
return [s.geo_location for s in past_scrobbles]
def update(self, scrobble_data: dict) -> "Scrobble": def update(self, scrobble_data: dict) -> "Scrobble":
# Status is a field we get from Mopidy, which refuses to poll us # Status is a field we get from Mopidy, which refuses to poll us
scrobble_status = scrobble_data.pop("mopidy_status", None) scrobble_status = scrobble_data.pop("mopidy_status", None)