diff options
| -rw-r--r-- | fietsboek/views/profile.py | 86 | 
1 files changed, 59 insertions, 27 deletions
| diff --git a/fietsboek/views/profile.py b/fietsboek/views/profile.py index 6aef499..2a4203e 100644 --- a/fietsboek/views/profile.py +++ b/fietsboek/views/profile.py @@ -1,6 +1,7 @@  """Endpoints for the user profile pages."""  import datetime  import sqlite3 +from dataclasses import dataclass  from pyramid.httpexceptions import HTTPNotFound  from pyramid.request import Request @@ -14,6 +15,54 @@ from ..data import UserDataDir  from ..models.track import TrackType, TrackWithMetadata +@dataclass +class CumulativeStats: +    """Cumulative user stats. + +    The values start out with default values, and tracks can be merged in via +    :meth:`add`. +    """ + +    count: int = 0 +    """Number of tracks added.""" + +    length: float = 0.0 +    """Total length, in meters.""" + +    uphill: float = 0.0 +    """Total uphill, in meters.""" + +    downhill: float = 0.0 +    """Total downhill, in meters.""" + +    moving_time: datetime.timedelta = datetime.timedelta(0) +    """Total time spent moving.""" + +    stopped_time: datetime.timedelta = datetime.timedelta(0) +    """Total time standing still.""" + +    max_speed: float = 0.0 +    """Overall maximum speed, in m/s.""" + +    def add(self, track: TrackWithMetadata): +        """Adds a track to this stats collection. + +        :param track: The track to add, with accompanying metadata. +        """ +        self.count += 1 +        self.length += track.length +        self.uphill += track.uphill +        self.downhill += track.downhill +        self.moving_time += track.moving_time +        self.stopped_time += track.stopped_time +        self.max_speed = max(self.max_speed, track.max_speed) + +    @property +    def avg_speed(self) -> float: +        """Average speed, in m/s.""" +        return self.length / self.moving_time.total_seconds() + +  def round_to_seconds(value: datetime.timedelta) -> datetime.timedelta:      """Round a timedelta to full seconds. @@ -34,31 +83,14 @@ def profile(request: Request) -> dict:      :param request: The pyramid request.      :return: The template parameters.      """ -    total_length = 0.0 -    total_uphill = 0.0 -    total_downhill = 0.0 -    total_moving_time = datetime.timedelta(0) -    total_stopped_time = datetime.timedelta(0) -    max_speed = 0.0 -    number_of_tracks = 0 +    total = CumulativeStats()      query = request.context.all_tracks_query()      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) - -        total_length += meta.length -        total_uphill += meta.uphill -        total_downhill += meta.downhill -        total_moving_time += meta.moving_time -        total_stopped_time += meta.stopped_time -        max_speed = max(max_speed, meta.max_speed) -        number_of_tracks += 1 - -    avg_speed = total_length / total_moving_time.total_seconds() -    total_moving_time = round_to_seconds(total_moving_time) -    total_stopped_time = round_to_seconds(total_stopped_time) +        total.add(meta)      heatmap_url = None      tilehunt_url = None @@ -94,15 +126,15 @@ def profile(request: Request) -> dict:      return {          "user": request.context, -        "total_length": total_length, -        "total_uphill": total_uphill, -        "total_downhill": total_downhill, -        "total_moving_time": total_moving_time, -        "total_stopped_time": total_stopped_time, -        "max_speed": max_speed, -        "avg_speed": avg_speed, +        "total_length": total.length, +        "total_uphill": total.uphill, +        "total_downhill": total.downhill, +        "total_moving_time": round_to_seconds(total.moving_time), +        "total_stopped_time": round_to_seconds(total.stopped_time), +        "max_speed": total.max_speed, +        "avg_speed": total.avg_speed,          "mps_to_kph": util.mps_to_kph, -        "number_of_tracks": number_of_tracks, +        "number_of_tracks": total.count,          "heatmap_url": heatmap_url,          "tilehunt_url": tilehunt_url,      } | 
