def index(request): primary_bike_id = '' bikes = request.user.gear_set.all() for bike in bikes: if bike.primary: primary_bike_id = bike.strava_id gear_id = request.POST.get('gear_id', primary_bike_id) before = request.POST.get('before') after = request.POST.get('after') if before and after: before = datetime.datetime.strptime(before, '%Y-%m-%d') + timedelta(hours=23, minutes=59, seconds=59) after = datetime.datetime.strptime(after, '%Y-%m-%d') + timedelta(hours=23, minutes=59, seconds=59) else: before = datetime.datetime.today().replace(hour=23, minute=59, second=59, microsecond=0) after = before - timedelta(days=7) stra = strava() filters = [ {'field': 'athlete.id', 'query': request.user.strava_id}, {'field': 'start_date', 'query': {'$lt': before, '$gte': after}}, {'field': 'gear_id', 'query': gear_id}, ] activities = stra.aggregate_activities_mongo(filters, { '_id': None, 'distance': {'$sum': '$distance'}, 'elapsed_time': {'$sum': '$moving_time'}, 'elevation': {'$sum': '$total_elevation_gain'}, 'average_speed': {'$avg': '$average_speed'}, 'kilojoules': {'$sum': '$kilojoules'}, }) template_fields = { 'bikes': bikes, 'gear_id':gear_id, 'before':before.strftime('%Y-%m-%d'), 'after':after.strftime('%Y-%m-%d'), 'distance': unithelper.miles(unit('m')(0)), 'time': unithelper.hours(unit('s')(0)), 'elevation': unithelper.meters(unit('m')(0)), 'avg_speed': unithelper.mph(unit('m')(0)/unit('s')(1)), 'kjs': 0, } activity = None for agg in activities: if not activity: activity = agg if activity: merge_dict = template_fields.copy() merge_dict.update({ 'distance': unithelper.miles(unit('m')(activity['distance'])), 'time': unithelper.hours(unit('s')(activity['elapsed_time'])), 'elevation': unithelper.meters(unit('m')(activity['elevation'])), 'avg_speed': unithelper.mph(unit('m')(activity['average_speed'])/unit('s')(1)), 'kjs': activity['kilojoules'], }) template_fields = merge_dict return render_to_response('strava/templates/strava_index.html', template_fields, context_instance=RequestContext(request))
def test_basic_get_from_client(self): stats = self.client.get_athlete_stats() self.assertIsInstance(stats, model.AthleteStats) self.assertIsInstance(stats.recent_ride_totals, model.ActivityTotals) # Check biggest_climb_elevation_gain has been set self.assertTrue( uh.meters(stats.biggest_climb_elevation_gain) >= uh.meters(0))
def get_route_details(self, cookies=None): """ retrieve route details including streams from strava. the source_id of the model instance must be set. """ # Retrieve route details from Strava API strava_route = self.strava_client.get_route(self.source_id) # set route name and description self.name = strava_route.name self.description = strava_route.description if strava_route.description else "" # use Strava route distance and elevation_gain until we calculate them from data self.total_elevation_gain = unithelper.meters(strava_route.elevation_gain).num self.total_distance = unithelper.meters(strava_route.distance).num # Strava only knows two activity types for routes: '1' for ride, '2' for run if strava_route.type == "1": self.activity_type = ActivityType.objects.get(name=ActivityType.RIDE) if strava_route.type == "2": self.activity_type = ActivityType.objects.get(name=ActivityType.RUN) # create route data and geo from Strava API streams self.geom, self.data = self.get_route_data()
def test_basic_get_from_client(self): stats = self.client.get_athlete_stats() self.assertIsInstance(stats, model.AthleteStats) self.assertIsInstance(stats.recent_ride_totals, model.ActivityTotals) print("Biggest climb: {!r}".format(stats.biggest_climb_elevation_gain)) # Check biggest_climb_elevation_gain has been set self.assertTrue(uh.meters(stats.biggest_climb_elevation_gain) >= uh.meters(0))
def update_with_strava_data(self, strava_activity, commit=True): """ update an activity based on information received from Strava. :param strava_activity: the activity object returned by the Strava API client. :param commit: save Strava activity to the database """ # fields from the Strava API object mapped to the Activity Model fields_map = { "name": strava_activity.name, "activity_type": strava_activity.type, "start_date": strava_activity.start_date, "elapsed_time": strava_activity.elapsed_time, "moving_time": strava_activity.moving_time, "description": strava_activity.description, "workout_type": strava_activity.workout_type, "distance": unithelper.meters(strava_activity.distance), "total_elevation_gain": unithelper.meters( strava_activity.total_elevation_gain ), "gear": strava_activity.gear_id, "commute": strava_activity.commute, } # find or create the activity type fields_map["activity_type"], created = ActivityType.objects.get_or_create( name=strava_activity.type ) if strava_activity.gear_id: # resolve foreign key relationship for gear and get gear info if new fields_map["gear"], created = Gear.objects.get_or_create( strava_id=strava_activity.gear_id, athlete=self.athlete ) if created: fields_map["gear"].update_from_strava() # transform description text to empty if None if strava_activity.description is None: fields_map["description"] = "" # update activity information for key, value in fields_map.items(): setattr(self, key, value) if commit: self.save()
def collect_ride_data(self, challenge): """ Pull the latest ride data from Strava via the API """ client = Client() client.access_token = self.strava_config['access-token'] #activities = client.get_club_activities(165009) activities = client.get_club_activities(challenge.get_group_id()) act_list = [] for activity in activities: if not activity.type == 'Ride' and not activity.type == 'VirtualRide': print 'Non-ride activity: %s, type: %s' % (activity.name, activity.type) continue act = Activity(activity.id) act.set_athlete(activity.athlete.id) act.set_name(activity.name) act.set_gmt_date(activity.start_date) # GMT Start date act.set_elapsed_time(activity.elapsed_time) act.set_distance(round(unithelper.kilometers(activity.distance).num, 2)) act.set_elevation(unithelper.meters(activity.total_elevation_gain).num) act.set_ride_type(activity.type) act.set_trainer_ride(activity.trainer) act_list.append(act) db_store = GTDataStore(challenge.get_db_path(), self.verbose) db_store.store_if_new(act_list)
def get_xtraining(self, after='2017-11-01', before='2018-09-05'): """ """ activities = self.client.get_activities(after=after, before=before) self.x_training = pd.DataFrame([{ 'name': activity.name, 'id': activity.id, 'activity': activity.type, 'elapsed_time': unithelper.timedelta_to_seconds(activity.elapsed_time), 'start_date': activity.start_date, 'distance': float(unithelper.meters(activity.distance)) * self.M_TO_YD } for activity in activities if activity.type != 'Swim']) self.x_training = self.x_training.set_index('start_date') self.x_training.index = pd.DatetimeIndex(self.x_training.index) self.x_training.index = self.x_training.index.tz_convert('US/Pacific') self.x_training['month'] = self.x_training.index.month self.x_training['month_name'] = self.x_training['month'].apply( lambda x: calendar.month_abbr[x]) self.x_training['ds_week_ending'] = self.x_training.index.to_period( 'W').end_time.floor('d') self.x_training['ds_month_ending'] = self.x_training.index.to_period( 'M').end_time.floor('d') self.x_training['hours'] = self.x_training.elapsed_time / 3600
def load_strava_data(user_id): user = User.objects.get(id=user_id) token = user.social_auth.get(provider='strava').tokens c = StravaClient(token) # fetch 200 activities activities = c.get_activities(limit=200) for track in activities: activity, created = Activity.objects.get_or_create( guID=track.id, user=user ) print track.id activity.provider = Activity.STRAVA_PROVIDER activity.location_city = track.location_city activity.location_country = track.location_country full_activity = c.get_activity(track.id) activity.polyline = full_activity.map.polyline activity.moving_time = full_activity.moving_time activity.start_date = full_activity.start_date activity.distance = float( unithelper.meters( track.distance ) ) activity.total_elevation_gain = float( unithelper.meters( track.total_elevation_gain ) ) activity.resource_state = track.resource_state activity.description = track.description if hasattr(track, 'start_latlng') and track.start_latlng is not None: activity.start_point = Point( track.start_latlng.lon, track.start_latlng.lat ) activity.save() if activity.polyline: activity.route = LineString(polyline_decode(activity.polyline)) activity.save()
def handle(self, *args, **options): # "start_date_local": "2017-10-08T23:59:59Z" # "moving_time": 1800 # "kilojoules": 1000 # "distance": 16093.44 # 10 miles # "total_elevation_gain": 500 logger = logging.getLogger(__name__) athlete_count = input("Enter Desired Number of Athletes:") gear_count = input("Enter Desired Number of Bikes per Athlete:") activity_count = input("Enter Desired Activity Count per Bike per Athlete:") distance = input("Enter Distance Per Activity (Miles):") elapsed_time = input("Enter Time Per Activity (Seconds):") elevation = input("Enter Elevation Gain Per Activity (Meters):") kjs = input("Enter kilojoules Per Activity:") start_date = datetime.datetime.strptime('2017-10-18T23:59:59Z', '%Y-%m-%dT%H:%M:%SZ') - timedelta(days=int(activity_count)) f = open("mycyclediary_dot_com/fixtures/mongo/{}.json".format(start_date.isoformat()), "w") activity_id = 0 for athlete_id in range(int(athlete_count)): for gear_id in range(int(gear_count)): for i in range(int(activity_count)): distance_unit = unithelper.meters(unit('mi')(int(distance))) activity_date = start_date + timedelta(days=i) dict_activity = { "_id": activity_id, "start_date_local":activity_date.strftime("%Y-%m-%dT%H:%M:%SZ"), "id":activity_id, "gear_id":str(gear_id), "elapsed_time":int(elapsed_time), "type":"Ride", "start_date":{ "$date":activity_date.strftime("%Y-%m-%dT%H:%M:%S.000Z"), }, "moving_time":int(elapsed_time), "strava_api_version":3, "distance":distance_unit.num, "name":"Generated activity {}".format(activity_id), "total_elevation_gain":int(elevation), "athlete":{ "resource_state":1, "id":athlete_id }, "average_speed": distance_unit.num/int(elapsed_time), "kilojoules": int(kjs) } json_str = json.dumps(dict_activity, sort_keys=True, indent=4, separators=(',', ': ')) f.write(json.dumps(dict_activity)+",\n") print(json_str) activity_id = activity_id+1 f.close()
def get_remote_routes_list(athlete, cookies=None): """ fetches the athlete's routes list from Strava and returns them as a list of StravaRoute stubs. """ # retrieve routes list from Strava strava_routes = athlete.strava_client.get_routes(athlete_id=athlete.strava_id) # create model instances with Strava routes data return [ StravaRoute( source_id=strava_route.id, name=strava_route.name, total_elevation_gain=unithelper.meters(strava_route.elevation_gain).num, total_distance=unithelper.meters(strava_route.distance).num, athlete=athlete, ) for strava_route in strava_routes ]
def get_swims(self, after='2017-11-01', before='2018-09-05'): """ """ activities = self.client.get_activities(after=after, before=before) self.swims = pd.DataFrame([{ 'name': activity.name, 'id': activity.id, 'stroke_count': 2 * activity.average_cadence if activity.average_cadence is not None else None, 'average_speed': float(unithelper.meters_per_second(activity.average_speed)), 'elapsed_time': unithelper.timedelta_to_seconds(activity.elapsed_time), 'start_date': activity.start_date, 'distance': float(unithelper.meters(activity.distance)) * self.M_TO_YD } for activity in activities if activity.type == 'Swim']) self.swims = self.swims.set_index('start_date') self.swims.index = pd.DatetimeIndex(self.swims.index) self.swims.index = self.swims.index.tz_convert('US/Pacific') self.swims['month'] = self.swims.index.month self.swims['month_name'] = self.swims['month'].apply( lambda x: calendar.month_abbr[x]) self.swims['ds_week_ending'] = self.swims.index.to_period( 'W').end_time.floor('d') self.swims['ds_month_ending'] = self.swims.index.to_period( 'M').end_time.floor('d') self.swims['is_pool'] = [ 'pool' if "[POOL]" in name else 'open water' for name in self.swims.name ] self.swims['hours'] = self.swims.elapsed_time / 3600 self.total_yards = int(self.swims.distance.sum()) self.in_out = self.swims.groupby(['is_pool' ])['distance'].agg({'total': 'sum'}) self.in_out['percentage'] = 100 * self.in_out['total'] / self.in_out[ 'total'].sum() # TODO: wrap in utility # TODO: sort by ds_month_ending self.monthly_yardage = self.swims.groupby( self.swims.index.month)['distance', 'hours'].sum() self.monthly_yardage[ "weekly distance"] = self.monthly_yardage.distance / 4.0 self.monthly_yardage.index = self.monthly_yardage.index.map( lambda x: datetime.date(1900, x, 1).strftime('%B'))
def load_strava_data(user_id): user = User.objects.get(id=user_id) token = user.social_auth.get(provider='strava').tokens c = StravaClient(token) # fetch 200 activities activities = c.get_activities(limit=200) for track in activities: activity, created = Activity.objects.get_or_create(guID=track.id, user=user) print track.id activity.provider = Activity.STRAVA_PROVIDER activity.location_city = track.location_city activity.location_country = track.location_country full_activity = c.get_activity(track.id) activity.polyline = full_activity.map.polyline activity.moving_time = full_activity.moving_time activity.start_date = full_activity.start_date activity.distance = float(unithelper.meters(track.distance)) activity.total_elevation_gain = float( unithelper.meters(track.total_elevation_gain)) activity.resource_state = track.resource_state activity.description = track.description if hasattr(track, 'start_latlng') and track.start_latlng is not None: activity.start_point = Point(track.start_latlng.lon, track.start_latlng.lat) activity.save() if activity.polyline: activity.route = LineString(polyline_decode(activity.polyline)) activity.save()
def create_activity(self, name, activity_type, start_date_local, elapsed_time, description=None, distance=None): """ Create a new manual activity. If you would like to create an activity from an uploaded GPS file, see the :meth:`stravalib.client.Client.upload_activity` method instead. :param name: The name of the activity. :param activity_type: The activity type (case-insensitive). Possible values: ride, run, swim, workout, hike, walk, nordicski, alpineski, backcountryski, iceskate, inlineskate, kitesurf, rollerski, windsurf, workout, snowboard, snowshoe :param start_date: Local date/time of activity start. (TZ info will be ignored) :type start_date: :class:`datetime.datetime` or string in ISO8601 format. :param elapsed_time: The time in seconds or a :class:`datetime.timedelta` object. :type elapsed_time: :class:`datetime.timedelta` or int (seconds) :param description: The description for the activity. :type description: str :param distance: The distance in meters (float) or a :class:`units.quantity.Quantity` instance. :type distance: :class:`units.quantity.Quantity` or float (meters) """ if isinstance(elapsed_time, timedelta): elapsed_time = unithelper.timedelta_to_seconds(elapsed_time) if isinstance(distance, Quantity): distance = float(unithelper.meters(distance)) if isinstance(start_date_local, datetime): start_date_local = start_date_local.strftime("%Y-%m-%dT%H:%M:%SZ") if not activity_type.lower() in [t.lower() for t in model.Activity.TYPES]: raise ValueError("Invalid activity type: {0}. Possible values: {1!r}".format(activity_type, model.Activity.TYPES)) params = dict(name=name, type=activity_type, start_date_local=start_date_local, elapsed_time=elapsed_time) if description is not None: params['description'] = description if distance is not None: params['distance'] = distance raw_activity = self.protocol.post('/activities', **params) return model.Activity.deserialize(raw_activity, bind_client=self)
def post_activity(self, activity): payload = {} if (activity.athlete.firstname is None): activity.athlete = self.client.get_athlete(activity.athlete.id) first_name = activity.athlete.firstname last_name = activity.athlete.lastname distance = kilometers(activity.distance) activity_duration = activity.moving_time speed = kilometers_per_hour(activity.average_speed) climbing = meters(activity.total_elevation_gain) activity_id = activity.id description = activity.name if (len(description) > 100): description = description[:97] + "..." payload = {'username': '******', 'icon_url': 'https://raw.githubusercontent.com/patoupatou/pymatterstrava/master/icon-strava.png', 'text': u':bicyclist: *{} {} : distance: {}, moving time duration: {}, speed: {}, climbing: {}* [{}](http://strava.com/activities/{}) :bicyclist:'.format(first_name, last_name, distance, activity_duration, speed, climbing, description, activity_id)} r = self.http.request('POST', self.mattermostUrl, headers={'Content-Type': 'application/json'}, body=json.dumps(payload)) print(time.ctime() + ': New activity posted') print('payload: ' + str(payload) + '\n')
print athlete.firstname activities= client.get_activities() activity_list = [] for activity in activities: activity = client.get_activity(activity.id) if activity.photos.primary: primary_pic = activity.photos.primary.urls['600'] else: primary_pic = [] data = { "Name" : activity.name, "Created At" : activity.start_date.isoformat(), "Distance Meters" : float(unithelper.meters(activity.distance)), "Elapsed Time in Seconds" : activity.elapsed_time.seconds, "Link to Activity" : "https://www.strava.com/activities/" + str(activity.id), "Notes" : activity.description, "Photos" : [{'url':primary_pic}] if primary_pic else [], "Strava Activity ID" : activity.id, } print data response = at.create(str("Runs"), data) print response print len(list(activities))
explores=client.explore_segments(bounds) time.sleep(3) count+=1 if len(explores)==10: pol.style.polystyle.color=simplekml.Color.red pol.style.polystyle.fill=1 file=open('segments.slider.01.csv', 'ab') wr=csv.writer(file,dialect='excel') for s in explores: segmentname=s.name.encode('utf-8') results=[s.id, segmentname, s.climb_category, s.climb_category_desc, s.avg_grade, \ s.start_latlng.lat, s.start_latlng.lon, s.end_latlng.lat, s.end_latlng.lon, \ float(unithelper.meters(s.elev_difference)), float(unithelper.meters(s.distance))\ ,s.segment.state,s.segment.city, s.segment.starred, s.segment.created_at, \ s.segment.updated_at, s.segment.effort_count, s.segment.athlete_count, \ s.segment.hazardous, s.segment.star_count,\ s.points] wr.writerow(results) file.close() lon +=increment lat+=increment lon=-87.49 lat=46.23 latsize-=increment lonsize-=increment kml.save("polys.kml")
def test_get_route(self): route = self.client.get_route(3445913) self.assertEquals('Baveno - Mottarone', route.name) self.assertAlmostEquals(1265.20, float(uh.meters(route.elevation_gain)), 2)
def activity_dict(athlete, a): elapsed_time = unithelper.seconds(a.elapsed_time.total_seconds()) if athlete.measurement_preference == 'feet': distance = str(unithelper.miles(a.distance)) gain = str(unithelper.feet(a.total_elevation_gain)) if a.type == 'Ride': speed = str(unithelper.mph(a.average_speed)) elapsed_speed = str(unithelper.mph(a.distance / elapsed_time)) else: try: speed = "{0:.2f} /mi".format( 60 / (unithelper.mph(a.average_speed).num)) elapsed_speed = "{0:.2f} /mi".format( 60 / unithelper.mph(a.distance / elapsed_time).num) except ZeroDivisionError: speed = 'NaN' elapsed_speed = 'NaN' else: distance = str(unithelper.kilometers(a.distance)) gain = str(unithelper.meters(a.total_elevation_gain)) if a.type == 'Ride': speed = str(unithelper.kph(a.average_speed)) elapsed_speed = str(unithelper.kph(a.distance / elapsed_time)) else: try: speed = "{0:.2f} /km".format( 60 / (unithelper.kph(a.average_speed).num)) elapsed_speed = "{0:.2f} /km".format( 60 / unithelper.kph(a.distance / elapsed_time).num) except ZeroDivisionError: speed = 'NaN' elapsed_speed = 'NaN' date = a.start_date_local.strftime(athlete.date_preference or "%a, %d %b %Y") weekday = calendar.day_name[a.start_date_local.weekday()] workout_type = '' if a.type == 'Run': workout_type = ['', 'Race', 'Long Run', 'Workout'][int(a.workout_type or 0)] garmin_link = '' if a.external_id: if a.external_id.startswith('garmin_push_'): garmin_id = a.external_id.split('_')[2] garmin_link = 'https://connect.garmin.com/modern/activity/{}'.format( garmin_id) return { 'id': a.id, 'link': url_for('query.show_activity', id=a.id), 'strava_link': 'https://www.strava.com/activities/{}'.format(a.id), 'garmin_link': garmin_link, 'name': a.name, 'type': a.type, 'workout_type': workout_type, 'date': date, 'weekday': weekday, 'distance': distance, 'gain': gain, 'elapsed_time': str(a.elapsed_time), 'moving_time': str(a.moving_time), 'speed': speed, 'elapsed_speed': elapsed_speed, 'start_latlng': [a.start_latitude, a.start_longitude], 'polyline': a.map.polyline or a.map.summary_polyline }
def create_club_workbook(filename: str, athlete_map: dict): workbook = Workbook(filename, {'default_date_format':'dd/mm/yy'}) worksheet = workbook.add_worksheet() bold = workbook.add_format({'bold': True}) row = 0 col = 0 worksheet.write(row, col, 'Name', bold) worksheet.write(row, col+1, 'Distance (km)', bold) worksheet.write(row, col+2, 'Moving Time (s)', bold) worksheet.write(row, col+3, 'Elapsed Time (s)', bold) worksheet.write(row, col+4, 'Total Elevation Gain (m)', bold) worksheet.write(row, col+5, 'Activity Type', bold) worksheet.set_column('A:A', 14) worksheet.set_column('B:B', 20) worksheet.set_column('C:C', 20) worksheet.set_column('D:D', 20) worksheet.set_column('E:E', 28) worksheet.set_column('F:F', 18) row += 1 total_distance_kilometers = float(0) for key in athlete_map: athlete_distance_kilometers = 0 athlete_moving_time_seconds = 0 athlete_elapsed_time_seconds = 0 athlete_total_elevation_gain_meters = 0 for idx, activity in enumerate(athlete_map[key]): distance_kilometers = unithelper.kilometers(activity['distance']) athlete_distance_kilometers += float(distance_kilometers) moving_time = activity['moving_time'] athlete_moving_time_seconds += moving_time.seconds elapsed_time = activity['elapsed_time'] athlete_elapsed_time_seconds += elapsed_time.seconds total_elevation_gain_meters = unithelper.meters(activity['total_elevation_gain']) athlete_total_elevation_gain_meters += float(total_elevation_gain_meters) worksheet.write(row, col, key) worksheet.write(row, col+1, round(float(distance_kilometers), util.DEFAULT_DECIMAL_PLACES)) worksheet.write(row, col+2, moving_time.seconds) worksheet.write(row, col+3, elapsed_time.seconds) worksheet.write(row, col+4, float(total_elevation_gain_meters)) worksheet.write(row, col+5, activity['type']) row += 1 col = 0 total_distance_kilometers += athlete_distance_kilometers print( '=> Total distance is {total_distance_kilometers} km'.format( total_distance_kilometers=round(total_distance_kilometers, util.DEFAULT_DECIMAL_PLACES), ) ) workbook.close() print( '\n=> Wrote "{filename}"\n'.format( filename=filename, ) )
def create_activity_workbook(filename: str): print('\nPreparing {filename} ... '.format(filename=filename, )) spinner = util.spinning_cursor() # read all access tokens tokens = [] tokens = _read_access_tokens('tokens') print('\n=> Read {token_count} access tokens\n'.format( token_count=len(tokens), )) row = 0 col = 0 workbook = Workbook(filename, {'default_date_format': 'dd/mm/yy'}) bold = workbook.add_format({'bold': True}) workbook.add_format({'num_format': 'dd/mm/yy'}) worksheet = workbook.add_worksheet() worksheet.write(row, col, 'ID', bold) worksheet.write(row, col + 1, 'Athlete', bold) worksheet.write(row, col + 2, 'Activity Name', bold) worksheet.write(row, col + 3, 'Achievement Count', bold) worksheet.write(row, col + 4, 'Date', bold) worksheet.write(row, col + 5, 'Type', bold) worksheet.write(row, col + 6, 'Distance (m)', bold) worksheet.write(row, col + 7, 'Distance (miles)', bold) worksheet.write(row, col + 8, 'Moving Time (s)', bold) worksheet.write(row, col + 9, 'Average Speed (m/s)', bold) worksheet.write(row, col + 10, 'Max Speed (m/s)', bold) worksheet.write(row, col + 11, 'Total Elevation Gain (m)', bold) worksheet.write(row, col + 12, 'Suffer Score', bold) worksheet.write(row, col + 13, 'Average Watts', bold) worksheet.write(row, col + 14, 'Max Watts', bold) worksheet.write(row, col + 15, 'Average Cadence', bold) worksheet.write(row, col + 16, 'Kudos', bold) worksheet.write(row, col + 17, 'Location City', bold) worksheet.write(row, col + 18, 'Calories', bold) worksheet.write(row, col + 19, 'PR Count', bold) worksheet.set_column('A:A', 12) worksheet.set_column('B:B', 20) worksheet.set_column('C:C', 20) worksheet.set_column('D:D', 20) worksheet.set_column('E:E', 10) worksheet.set_column('F:F', 14) worksheet.set_column('G:G', 16) worksheet.set_column('H:H', 16) worksheet.set_column('I:I', 18) worksheet.set_column('J:J', 24) worksheet.set_column('K:K', 20) worksheet.set_column('L:L', 24) worksheet.set_column('M:M', 18) worksheet.set_column('N:N', 18) worksheet.set_column("O:O", 18) worksheet.set_column('P:P', 18) worksheet.set_column('Q:Q', 18) worksheet.set_column('R:R', 18) worksheet.set_column('S:S', 18) worksheet.set_column('T:T', 18) row += 1 cursor.hide() # get activities for all athletes total_distance_miles = float(0) for idx, access_token in enumerate(tokens): client = Client(access_token=access_token) athlete = client.get_athlete() print('Processing athlete: "{lastname}, {firstname}" ...'.format( lastname=athlete.lastname, firstname=athlete.firstname, )) athlete_total_distance_miles = float(0) athlete_total_distance_meters = float(0) for idx, activity in enumerate(client.get_activities()): if idx % 20 == 0: sys.stdout.write('{}\r'.format(next(spinner))) sys.stdout.flush() time.sleep(0.1) worksheet.write(row, col, activity.id) worksheet.write( row, col + 1, util.athlete_fullname(athlete.firstname, athlete.lastname)) worksheet.write(row, col + 2, activity.name) worksheet.write(row, col + 3, activity.achievement_count) worksheet.write(row, col + 4, activity.start_date.replace(tzinfo=None)) worksheet.write(row, col + 5, activity.type) distance_meters = float(unithelper.meters(activity.distance)) worksheet.write( row, col + 6, round(distance_meters, util.DEFAULT_DECIMAL_PLACES)) distance_miles = float(unithelper.miles(activity.distance)) worksheet.write(row, col + 7, round(distance_miles, util.DEFAULT_DECIMAL_PLACES)) worksheet.write(row, col + 8, activity.moving_time.seconds) average_speed_meters_per_second = float( unithelper.meters_per_second(activity.average_speed)) worksheet.write( row, col + 9, round(average_speed_meters_per_second, util.DEFAULT_DECIMAL_PLACES)) max_speed_meters_per_second = float( unithelper.meters_per_second(activity.max_speed)) worksheet.write( row, col + 10, round(max_speed_meters_per_second, util.DEFAULT_DECIMAL_PLACES)) total_elevation_gain_meters = float( unithelper.meters(activity.total_elevation_gain)) worksheet.write( row, col + 11, round(total_elevation_gain_meters, util.DEFAULT_DECIMAL_PLACES)) worksheet.write( row, col + 12, activity.suffer_score ) #: a measure of heartrate intensity, available on premium users' activities only worksheet.write(row, col + 13, activity.average_watts ) #: (undocumented) Average power during activity worksheet.write( row, col + 14, activity.max_watts) #: rides with power meter data only worksheet.write( row, col + 15, activity.average_cadence ) #: (undocumented) Average cadence during activity worksheet.write( row, col + 16, activity.kudos_count) #: How many kudos received for activity worksheet.write( row, col + 17, activity.location_city) #: The activity location city worksheet.write( row, col + 18, activity.calories ) #: Calculation of how many calories burned on activity worksheet.write( row, col + 19, activity.pr_count ) #: How many new personal records earned for the activity row += 1 col = 0 # reset athlete_total_distance_miles += distance_miles print( '=> Athlete total distance is {athlete_total_distance_miles} miles' .format(athlete_total_distance_miles=round( athlete_total_distance_miles, util.DEFAULT_DECIMAL_PLACES), )) total_distance_miles += athlete_total_distance_miles print('\n=> Total distance is {total_distance_miles} miles'.format( total_distance_miles=round(total_distance_miles, util.DEFAULT_DECIMAL_PLACES), )) cursor.show() workbook.close() print('\n=> Wrote "{filename}"\n'.format(filename=filename, ))