Changeset bed4f06 in OpenWorkouts-current


Ignore:
Timestamp:
Jan 29, 2019, 12:16:50 PM (5 years ago)
Author:
borja <borja@…>
Branches:
current, feature/docs, master
Children:
6dc1846
Parents:
4bab6c1
Message:

(#7) Added method to gather monthly stats + view to export them

Location:
ow
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • ow/models/user.py

    r4bab6c1 rbed4f06  
    234234                        timedelta())
    235235        }
     236
     237    @property
     238    def yearly_stats(self):
     239        """
     240        Return per-month stats for the last 12 months
     241        """
     242        # set the boundaries for looking for workouts afterwards,
     243        # we need the current date as the "end date" and one year
     244        # ago from that date. Then we set the start at the first
     245        # day of that month.
     246        end = datetime.now(timezone.utc)
     247        start = (end - timedelta(days=365)).replace(day=1)
     248
     249        # build the stats, populating first the dict with empty values
     250        # for each month.
     251        stats = {}
     252        for days in range((end - start).days):
     253            day = (start + timedelta(days=days)).date()
     254            if (day.year, day.month) not in stats.keys():
     255                stats[(day.year, day.month)] = {
     256                    'workouts': 0,
     257                    'time': timedelta(0),
     258                    'distance': Decimal(0),
     259                    'elevation': Decimal(0),
     260                    'sports': {}
     261                }
     262
     263        # now loop over workouts, filtering and then adding stats to the
     264        # proper place
     265        for workout in self.workouts():
     266            if start.date() <= workout.start.date() <= end.date():
     267                # less typing, avoid long lines
     268                month = stats[
     269                    (workout.start.date().year, workout.start.date().month)]
     270                month['workouts'] += 1
     271                month['time'] += workout.duration or timedelta(seconds=0)
     272                month['distance'] += workout.distance or Decimal(0)
     273                month['elevation'] += workout.uphill or Decimal(0)
     274                if workout.sport not in month['sports']:
     275                    month['sports'][workout.sport] = {
     276                        'workouts': 0,
     277                        'time': timedelta(seconds=0),
     278                        'distance': Decimal(0),
     279                        'elevation': Decimal(0),
     280                    }
     281                month['sports'][workout.sport]['workouts'] += 1
     282                month['sports'][workout.sport]['time'] += (
     283                    workout.duration or timedelta(0))
     284                month['sports'][workout.sport]['distance'] += (
     285                    workout.distance or Decimal(0))
     286                month['sports'][workout.sport]['elevation'] += (
     287                    workout.uphill or Decimal(0))
     288
     289        return stats
  • ow/tests/views/test_user.py

    r4bab6c1 rbed4f06  
    268268        request = dummy_request
    269269        response = user_views.profile(john, request)
    270         assert response == {}
     270        assert len(response.keys()) == 1
     271        current_month = datetime.now(timezone.utc).strftime('%Y-%m')
     272        assert response['current_month'] == current_month
    271273
    272274    def test_login_get(self, dummy_request):
  • ow/views/user.py

    r4bab6c1 rbed4f06  
    11import json
    22from calendar import month_name
    3 from datetime import datetime
     3from datetime import datetime, timezone
    44
    55from pyramid.httpexceptions import HTTPFound
     
    165165    basic info, stats, etc
    166166    """
    167     return {}
     167    now = datetime.now(timezone.utc)
     168    return {
     169        'current_month': now.strftime('%Y-%m')
     170    }
    168171
    169172
     
    250253                    charset='utf-8',
    251254                    body=json.dumps(json_stats))
     255
     256
     257@view_config(
     258    context=User,
     259    permission='view',
     260    name='yearly')
     261def last_months_stats(context, request):
     262    """
     263    Return a json-encoded stream with statistics for the last 12 months
     264    """
     265    stats = context.yearly_stats
     266    # this sets which month is 2 times in the stats, once this year, once
     267    # the previous year. We will show it a bit different in the UI (showing
     268    # the year too to prevent confusion)
     269    repeated_month = datetime.now(timezone.utc).date().month
     270    json_stats = []
     271    for month in stats:
     272        hms = timedelta_to_hms(stats[month]['time'])
     273        name = month_name[month[1]][:3]
     274        if month[1] == repeated_month:
     275            name += ' ' + str(month[0])
     276        month_stats = {
     277            'id': str(month[0]) + '-' + str(month[1]).zfill(2),
     278            'name': name,
     279            'time': str(hms[0]).zfill(2),
     280            'distance': int(round(stats[month]['distance'])),
     281            'elevation': int(stats[month]['elevation']),
     282            'workouts': stats[month]['workouts']
     283        }
     284        json_stats.append(month_stats)
     285    return Response(content_type='application/json',
     286                    charset='utf-8',
     287                    body=json.dumps(json_stats))
Note: See TracChangeset for help on using the changeset viewer.