[locations] Refactor has moved to not use multiple points
This commit is contained in:
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user