aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Schadt <kingdread@gmx.de>2025-10-21 21:24:53 +0200
committerDaniel Schadt <kingdread@gmx.de>2025-10-28 21:06:37 +0100
commitd29b5ba644773f94a12244cb47a85dc5aa7623a8 (patch)
tree4fe885465ee2231ad8c9a5f5ec589dec0eeef650
parent9be283944a72019ee0d151011c049fc21ca7e718 (diff)
downloadfietsboek-d29b5ba644773f94a12244cb47a85dc5aa7623a8.tar.gz
fietsboek-d29b5ba644773f94a12244cb47a85dc5aa7623a8.tar.bz2
fietsboek-d29b5ba644773f94a12244cb47a85dc5aa7623a8.zip
take metadata from geo module
-rw-r--r--fietsboek/actions.py2
-rw-r--r--fietsboek/models/track.py53
-rw-r--r--fietsboek/util.py37
-rw-r--r--fietsboek/views/browse.py2
-rw-r--r--fietsboek/views/default.py2
-rw-r--r--fietsboek/views/detail.py2
-rw-r--r--fietsboek/views/profile.py4
7 files changed, 29 insertions, 73 deletions
diff --git a/fietsboek/actions.py b/fietsboek/actions.py
index 0e2284b..f49283d 100644
--- a/fietsboek/actions.py
+++ b/fietsboek/actions.py
@@ -105,7 +105,7 @@ def add_track(
# Best time to build the cache is right after the upload, but *after* the
# transformers have been applied!
- track.ensure_cache(gpx)
+ track.ensure_cache()
dbsession.add(track.cache)
LOGGER.debug("Building preview image for %s", track.id)
diff --git a/fietsboek/models/track.py b/fietsboek/models/track.py
index e9c09d6..7a7aff0 100644
--- a/fietsboek/models/track.py
+++ b/fietsboek/models/track.py
@@ -445,24 +445,21 @@ class Track(Base):
result = ACLHelper().permits(self, principals, "track.view")
return isinstance(result, ACLAllowed)
- def ensure_cache(self, gpx_data: Union[str, bytes, gpxpy.gpx.GPX]):
- """Ensure that a cached version of this track's metadata exists.
-
- :param gpx_data: GPX data (uncompressed) from which to build the cache.
- """
+ def ensure_cache(self):
+ """Ensure that a cached version of this track's metadata exists."""
if self.cache is not None:
return
self.cache = TrackCache(track=self)
- meta = util.tour_metadata(gpx_data)
- self.cache.length = meta["length"]
- self.cache.uphill = meta["uphill"]
- self.cache.downhill = meta["downhill"]
- self.cache.moving_time = meta["moving_time"]
- self.cache.stopped_time = meta["stopped_time"]
- self.cache.max_speed = meta["max_speed"]
- self.cache.avg_speed = meta["avg_speed"]
- self.cache.start_time = meta["start_time"]
- self.cache.end_time = meta["end_time"]
+ meta = self.path().movement_data()
+ self.cache.length = meta.length
+ self.cache.uphill = meta.uphill
+ self.cache.downhill = meta.downhill
+ self.cache.moving_time = meta.moving_duration
+ self.cache.stopped_time = meta.stopped_duration
+ self.cache.max_speed = meta.maximum_speed
+ self.cache.avg_speed = meta.average_speed
+ self.cache.start_time = self.date
+ self.cache.end_time = self.date + datetime.timedelta(seconds=meta.duration)
def text_tags(self):
"""Returns a set of textual tags.
@@ -542,7 +539,7 @@ class Track(Base):
class TrackWithMetadata:
"""A class to add metadata to a :class:`Track`.
- This basically caches the result of :func:`fietsboek.util.tour_metadata`,
+ This basically caches the result of :func:`fietsboek.geo.Path.movement_data`,
or uses the track's cache if possible.
Loading of the metadata is lazy on first access. The track is accessible as
@@ -551,10 +548,9 @@ class TrackWithMetadata:
# pylint: disable=too-many-public-methods
- def __init__(self, track: Track, data_manager):
+ def __init__(self, track: Track):
self.track = track
self.cache = track.cache
- self.data_manager = data_manager
self._cached_meta: Optional[dict] = None
def _meta(self):
@@ -562,8 +558,7 @@ class TrackWithMetadata:
if self._cached_meta:
return self._cached_meta
- data = self.data_manager.open(self.track.id).decompress_gpx()
- self._cached_meta = util.tour_metadata(data)
+ self._cached_meta = self.track.path().movement_data()
return self._cached_meta
@property
@@ -573,7 +568,7 @@ class TrackWithMetadata:
:return: Length of the track in meters.
"""
if self.cache is None or self.cache.length is None:
- return self._meta()["length"]
+ return self._meta().length
return float(self.cache.length)
@property
@@ -583,7 +578,7 @@ class TrackWithMetadata:
:return: Downhill in meters.
"""
if self.cache is None or self.cache.downhill is None:
- return self._meta()["downhill"]
+ return self._meta().downhill
return float(self.cache.downhill)
@property
@@ -593,7 +588,7 @@ class TrackWithMetadata:
:return: Uphill in meters.
"""
if self.cache is None or self.cache.uphill is None:
- return self._meta()["uphill"]
+ return self._meta().uphill
return float(self.cache.uphill)
@property
@@ -615,7 +610,7 @@ class TrackWithMetadata:
:return: Stopped time in seconds.
"""
if self.cache is None or self.cache.stopped_time is None:
- value = self._meta()["stopped_time"]
+ value = self._meta().moving_duration
else:
value = self.cache.stopped_time
return datetime.timedelta(seconds=value)
@@ -627,7 +622,7 @@ class TrackWithMetadata:
:return: Maximum speed in meters/second.
"""
if self.cache is None or self.cache.max_speed is None:
- return self._meta()["max_speed"]
+ return self._meta().maximum_speed
return float(self.cache.max_speed)
@property
@@ -637,7 +632,7 @@ class TrackWithMetadata:
:return: Average speed in meters/second.
"""
if self.cache is None or self.cache.avg_speed is None:
- return self._meta()["avg_speed"]
+ return self._meta().average_speed
return float(self.cache.avg_speed)
@property
@@ -648,9 +643,7 @@ class TrackWithMetadata:
:return: Start time.
"""
- if self.cache is None or self.cache.start_time is None:
- return self._meta()["start_time"]
- return self.cache.start_time
+ return self.track.date
@property
def end_time(self) -> datetime.datetime:
@@ -661,7 +654,7 @@ class TrackWithMetadata:
:return: End time.
"""
if self.cache is None or self.cache.end_time is None:
- return self._meta()["end_time"]
+ return self.track.date + datetime.timedelta(seconds=self._meta().duration)
return self.cache.end_time
@property
diff --git a/fietsboek/util.py b/fietsboek/util.py
index 5611c51..27c333d 100644
--- a/fietsboek/util.py
+++ b/fietsboek/util.py
@@ -173,43 +173,6 @@ def guess_gpx_timezone(gpx: gpxpy.gpx.GPX) -> datetime.tzinfo:
return datetime.timezone.utc
-def tour_metadata(gpx_data: Union[str, bytes, gpxpy.gpx.GPX]) -> dict:
- """Calculate the metadata of the tour.
-
- Returns a dict with ``length``, ``uphill``, ``downhill``, ``moving_time``,
- ``stopped_time``, ``max_speed``, ``avg_speed``, ``start_time`` and
- ``end_time``.
-
- :param gpx_data: The GPX data of the tour. Can be pre-parsed to save time.
- :return: A dictionary with the computed values.
- """
- if isinstance(gpx_data, bytes):
- gpx_data = gpx_data.decode("utf-8")
- if isinstance(gpx_data, gpxpy.gpx.GPX):
- gpx = gpx_data
- else:
- gpx = gpxpy.parse(gpx_data)
- timezone = guess_gpx_timezone(gpx)
- uphill, downhill = gpx.get_uphill_downhill()
- moving_data = gpx.get_moving_data()
- time_bounds = gpx.get_time_bounds()
- try:
- avg_speed = moving_data.moving_distance / moving_data.moving_time
- except ZeroDivisionError:
- avg_speed = 0.0
- return {
- "length": gpx.length_3d(),
- "uphill": uphill,
- "downhill": downhill,
- "moving_time": moving_data.moving_time,
- "stopped_time": moving_data.stopped_time,
- "max_speed": moving_data.max_speed,
- "avg_speed": avg_speed,
- "start_time": (time_bounds.start_time or DEFAULT_START_TIME).astimezone(timezone),
- "end_time": (time_bounds.end_time or DEFAULT_END_TIME).astimezone(timezone),
- }
-
-
def mps_to_kph(mps: float) -> float:
"""Converts meters/second to kilometers/hour.
diff --git a/fietsboek/views/browse.py b/fietsboek/views/browse.py
index e8e3edf..a9e9d2e 100644
--- a/fietsboek/views/browse.py
+++ b/fietsboek/views/browse.py
@@ -463,7 +463,7 @@ def paginate(
break
for track in tracks:
- track = TrackWithMetadata(track, data_manager)
+ track = TrackWithMetadata(track)
if filters.apply(track):
num_retrieved += 1
yield track
diff --git a/fietsboek/views/default.py b/fietsboek/views/default.py
index 8a9718d..320d02d 100644
--- a/fietsboek/views/default.py
+++ b/fietsboek/views/default.py
@@ -61,7 +61,7 @@ def home(request: Request) -> Response:
gpx_data = request.data_manager.open(track.id).decompress_gpx()
track.ensure_cache(gpx_data)
request.dbsession.add(track.cache)
- summary.add(TrackWithMetadata(track, request.data_manager))
+ summary.add(TrackWithMetadata(track))
unfinished_uploads = request.identity.uploads
diff --git a/fietsboek/views/detail.py b/fietsboek/views/detail.py
index 2f2d887..5fa3beb 100644
--- a/fietsboek/views/detail.py
+++ b/fietsboek/views/detail.py
@@ -107,7 +107,7 @@ def details(request):
# Strip off the sort key again
images = [(image[1], image[2]) for image in images]
- with_meta = TrackWithMetadata(track, request.data_manager)
+ with_meta = TrackWithMetadata(track)
return {
"track": with_meta,
"show_organic": track.show_organic_data(),
diff --git a/fietsboek/views/profile.py b/fietsboek/views/profile.py
index 15bc46c..2e18c19 100644
--- a/fietsboek/views/profile.py
+++ b/fietsboek/views/profile.py
@@ -54,7 +54,7 @@ def profile_data(request: Request) -> dict:
query = select(aliased(models.Track, query)).where(query.c.type == TrackType.ORGANIC)
track: models.Track
for track in request.dbsession.execute(query).scalars():
- meta = TrackWithMetadata(track, request.data_manager)
+ meta = TrackWithMetadata(track)
total.add(meta)
total.moving_time = util.round_to_seconds(total.moving_time)
@@ -340,7 +340,7 @@ def json_summary(request: Request) -> Response:
if track.cache is None:
LOGGER.debug("Skipping track %d as it has no cached metadata", track.id)
continue
- summary.add(TrackWithMetadata(track, request.data_manager))
+ summary.add(TrackWithMetadata(track))
return {y.year: {m.month: m.total_length for m in y} for y in summary}