def main(year, month, day): """Manual Testing of Scrubbing""" start = datetime.datetime(year, month, day) client = authorize.get_authorized_client(username) act_manager = ActivityManager(client) athlete = client.get_athlete() metric_in_meters = 100000 acts = act_manager.get_activities(after=start, distance_min=metric_in_meters); count =1; print("Century (>100mi) Stats since: " + str(start)) acts.reverse() for act in acts: distance= unithelper.miles(act.distance).get_num() if distance >= 100: print(str(count) +": distance: " + '{:6.2f}'.format(distance) + " miles on Event: " + act.name + " " + str(act.start_date_local)) count = count +1 count = 1 print("*********************************************************************") print("Metric Centuries (>=62mi and <100mi) Stats since: " + str(start)) for act in acts: distance = unithelper.miles(act.distance).get_num() if distance < 100: print(str(count) + ": distance: " + '{:6.2f}'.format(distance) + " miles on Event: " + act.name + " " + str( act.start_date_local)) count = count + 1 print("Script Source: https://github.com/JHa13y/Strava")
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 __init__(self, athStats, athId): self.athId=athId self.RecentCount=athStats.recent_run_totals.count self.RecentDistance= float(unithelper.miles(athStats.recent_run_totals.distance))#distance in miles self.RecentTime= float(unithelper.seconds(athStats.recent_run_totals.moving_time))#time in seconds self.YTDCount=athStats.ytd_run_totals.count self.YTDDistance= float(unithelper.miles(athStats.ytd_run_totals.distance))#distance in miles self.YTDTime= float(unithelper.seconds(athStats.ytd_run_totals.moving_time))#time in seconds self.AllCount=athStats.all_run_totals.count self.AllDistance= float(unithelper.miles(athStats.all_run_totals.distance))#distance in miles self.AllTime= float(unithelper.seconds(athStats.all_run_totals.moving_time))#time in seconds
def filter_segment_efforts(seg_efforts, unithelper, min_miles=1, min_grade=0, ids_only=False, unique_ids=True): """Filters segment effort segments based on specific kwargs """ filtered = [] ids, ids_filt = set(), set() for seg_effort in seg_efforts: seg = seg_effort.segment if (unique_ids) and (seg.id in ids or seg.id in ids_filt): continue if seg.average_grade < min_grade: ids_filt.add( seg.id ) continue elif float(unithelper.miles( seg.distance )) < min_miles: ids_filt.add( seg.id ) continue elif ids_only: ids.add( seg.id ) filtered.append( seg.id ) else: ids.add( seg.id ) filtered.append( seg ) return filtered
def update_ride_basic(self, strava_activity: Activity, ride: Ride): """ Set basic ride properties from the Strava Activity object. :param strava_activity: The Strava Activity :param ride: The ride model object. """ # Should apply to both new and preexisting rides ... # If there are multiple instagram photos, then request syncing of non-primary photos too. if strava_activity.photo_count > 1 and ride.photos_fetched is None: self.logger.debug( "Scheduling non-primary photos sync for {!r}".format(ride)) ride.photos_fetched = False ride.private = bool(strava_activity.private) ride.name = strava_activity.name ride.start_date = strava_activity.start_date_local # We need to round so that "1.0" miles in data is "1.0" miles when we convert back from meters. ride.distance = round( float(unithelper.miles(strava_activity.distance)), 3) ride.average_speed = float( unithelper.mph(strava_activity.average_speed)) ride.maximum_speed = float(unithelper.mph(strava_activity.max_speed)) ride.elapsed_time = timedelta_to_seconds(strava_activity.elapsed_time) ride.moving_time = timedelta_to_seconds(strava_activity.moving_time) location_parts = [] if strava_activity.location_city: location_parts.append(strava_activity.location_city) if strava_activity.location_state: location_parts.append(strava_activity.location_state) location_str = ', '.join(location_parts) ride.location = location_str ride.commute = strava_activity.commute ride.trainer = strava_activity.trainer ride.manual = strava_activity.manual ride.elevation_gain = float( unithelper.feet(strava_activity.total_elevation_gain)) ride.timezone = str(strava_activity.timezone) # # Short-circuit things that might result in more obscure db errors later. if ride.elapsed_time is None: raise DataEntryError("Activities cannot have null elapsed time.") if ride.moving_time is None: raise DataEntryError("Activities cannot have null moving time.") if ride.distance is None: raise DataEntryError("Activities cannot have null distance.") self.logger.debug( "Writing ride for {athlete!r}: \"{ride!r}\" on {date}".format( athlete=ride.athlete.name, ride=ride.name, date=ride.start_date.strftime('%m/%d/%y')))
def summary(ctx): """Summary of everything you've done on Strava.""" client = ctx.obj['client'] bikes = ctx.obj['bikes'] by_bike = defaultdict(lambda: defaultdict(int)) activities = client.get_activities() for a in activities: if a.type != 'Ride': continue by_bike[a.gear_id]['distance'] += unithelper.miles(a.distance).num by_bike[a.gear_id]['rides'] += 1 output = cStringIO.StringIO() csv_out = UnicodeWriter(output) columns = ['bike', 'rides', 'distance'] csv_out.writerow(columns) for (bike, datap) in by_bike.items(): bike_name = bikes.get(bike) if not bike_name: bike_name = 'Retired bike ({})'.format(bike) else: bike_name = bike_name.name csv_out.writerow( [bike_name, datap['rides'], '{0:0.2f}'.format(datap['distance'])]) print(output.getvalue().strip())
def get_runs(request, n): """ Get most recent n runs associated with an account. """ # Our admin object admin = _get_admin(request) # Be sure it exists if not admin.exists_document('strava_access_token'): request.response.status_int = 403 return # Get the access token access_token = admin.get_document('strava_access_token') running_docs = { a:admin.get_document(a) for a in admin.list_documents() if a.startswith('run_') } strava_client = StravaClient(access_token=access_token['strava_access_token']) runs = [] for a in strava_client.get_activities(): if 'run_' + str(a.id) in running_docs: run = running_docs['run_' + str(a.id)] else: run = { 'id': a.id, 'timestamp': a.start_date_local.isoformat(), 'duration': a.elapsed_time.total_seconds(), 'distance': unithelper.miles(a.distance).num, 'name': a.name, 'description': a.description } if a.map.summary_polyline is not None: run['map_polyline'] = a.map.summary_polyline if a.start_latlng is not None and a.start_date is not None and 'darksky' in request.registry.settings['secrets']: fio = ForecastIO.ForecastIO( request.registry.settings['secrets']['darksky']['darksky_secret'], units=ForecastIO.ForecastIO.UNITS_US, latitude=float(a.start_latlng[0]), longitude=float(a.start_latlng[1]), time=str(int(time.mktime(a.start_date.timetuple()))) ) if fio.has_currently(): currently = FIOCurrently.FIOCurrently(fio) run['temperature'] = currently.temperature run['weather_icon'] = currently.icon admin.create_document(run, doc_id='run_' + str(a.id)) runs.append(run) if n is not None and len(runs) == n: break # Return appropriately request.response.status_int = 200 return { 'runs': runs }
def query_strava(): print('Querying Strava...') table = db[ACTIVITIES_TABLE] activity_summaries = [a for a in client.get_activities()] num_added = 0 for a_summary in activity_summaries: if table.find_one(strava_id=a_summary.id): break a = client.get_activity(a_summary.id) activity_data = { 'strava_id': a.id, 'name': a.name, 'type': a.type, 'start_date': a.start_date.isoformat(), 'distance_mi': float(unithelper.miles(a.distance)), 'elapsed_sec': a.elapsed_time.total_seconds(), 'pace_mins_per_mi': avg_speed_to_mins(a.average_speed), 'polyline': a.map.summary_polyline } print('Added %s: %s' % (a.type, a.name)) num_added += 1 table.insert(activity_data) print('Done! %s activities added.' % num_added)
def test_update_activity(self): """ Test Client.update_activity simple case. """ now = datetime.now().replace(microsecond=0) a = self.client.create_activity("test_update_activity#create", activity_type=model.Activity.RIDE, start_date_local=now, elapsed_time=timedelta(hours=3, minutes=4, seconds=5), distance=uh.miles(15.2)) self.assertIsInstance(a, model.Activity) self.assertEqual("test_update_activity#create", a.name) update1 = self.client.update_activity( a.id, name="test_update_activivty#update") self.assertEqual("test_update_activivty#update", update1.name) self.assertFalse(update1.private) self.assertFalse(update1.trainer) self.assertFalse(update1.commute) update2 = self.client.update_activity(a.id, private=True) self.assertTrue(update2.private) update3 = self.client.update_activity(a.id, trainer=True) self.assertTrue(update3.private) self.assertTrue(update3.trainer)
def get_runs(request, n): """ Get most recent n runs associated with an account. """ # Our admin object admin = _get_admin(request) # Be sure it exists if not admin.exists_document('strava_access_token'): request.response.status_int = 403 return # Get the access token access_token = admin.get_document('strava_access_token') running_docs = { a: admin.get_document(a) for a in admin.list_documents() if a.startswith('run_') } strava_client = StravaClient( access_token=access_token['strava_access_token']) runs = [] for a in strava_client.get_activities(): if 'run_' + str(a.id) in running_docs: run = running_docs['run_' + str(a.id)] else: run = { 'id': a.id, 'timestamp': a.start_date_local.isoformat(), 'duration': a.elapsed_time.total_seconds(), 'distance': unithelper.miles(a.distance).num, 'name': a.name, 'description': a.description } if a.map.summary_polyline is not None: run['map_polyline'] = a.map.summary_polyline if a.start_latlng is not None and a.start_date is not None and 'darksky' in request.registry.settings[ 'secrets']: fio = ForecastIO.ForecastIO( request.registry.settings['secrets']['darksky'] ['darksky_secret'], units=ForecastIO.ForecastIO.UNITS_US, latitude=float(a.start_latlng[0]), longitude=float(a.start_latlng[1]), time=str(int(time.mktime(a.start_date.timetuple())))) if fio.has_currently(): currently = FIOCurrently.FIOCurrently(fio) run['temperature'] = currently.temperature run['weather_icon'] = currently.icon admin.create_document(run, doc_id='run_' + str(a.id)) runs.append(run) if n is not None and len(runs) == n: break # Return appropriately request.response.status_int = 200 return {'runs': runs}
def on_tweet(self): # First, pull in the stats from Strava. current = datetime.datetime.now() last_week = current + datetime.timedelta(weeks=-1) after = datetime.datetime(last_week.year, last_week.month, last_week.day) activities = self.client.get_activities(after=after) # Second, filter by activity type and time frame. lf = [a for a in activities if a.start_date_local.day != current.day] num_activities = len(lf) l = [a.id for a in lf if a.type == 'Run'] # Third, tabulate up the stats for mileage and calories. mileage = 0.0 calories = 0.0 for activity_id in l: activity = self.client.get_activity(activity_id) distance = unithelper.miles(activity.distance) mileage += round(distance.num, 2) # Rounds to 2 sig figs. calories += activity.calories calories = int(calories) # Finally, use the stats to craft a tweet. This can be any format # you want, but I'll use the example one from the start of the post. tweet = "My training last week: {:d} workouts for {:.2f} miles and {:d} calories burned.".format( num_activities, mileage, calories) self.update_status(tweet)
def test_update_activity(self): """ Test Client.update_activity simple case. """ now = datetime.now().replace(microsecond=0) a = self.client.create_activity("test_update_activity#create", activity_type=model.Activity.RIDE, start_date_local=now, elapsed_time=timedelta(hours=3, minutes=4, seconds=5), distance=uh.miles(15.2)) self.assertIsInstance(a, model.Activity) self.assertEquals("test_update_activity#create", a.name) update1 = self.client.update_activity(a.id, name="test_update_activivty#update") self.assertEquals("test_update_activivty#update", update1.name) self.assertFalse(update1.private) self.assertFalse(update1.trainer) self.assertFalse(update1.commute) update2 = self.client.update_activity(a.id, private=True) self.assertTrue(update2.private) update3 = self.client.update_activity(a.id, trainer=True) self.assertTrue(update3.private) self.assertTrue(update3.trainer)
def on_tweet(self): # First, pull in the stats from Strava. current = datetime.datetime.now() last_week = current + datetime.timedelta(weeks = -1) after = datetime.datetime(last_week.year, last_week.month, last_week.day) activities = self.client.get_activities(after = after) # Second, filter by activity type and time frame. lf = [a for a in activities if a.start_date_local.day != current.day] num_activities = len(lf) l = [a.id for a in lf if a.type == 'Run'] # Third, tabulate up the stats for mileage and calories. mileage = 0.0 calories = 0.0 for activity_id in l: activity = self.client.get_activity(activity_id) distance = unithelper.miles(activity.distance) mileage += round(distance.num, 2) # Rounds to 2 sig figs. calories += activity.calories calories = int(calories) # Finally, use the stats to craft a tweet. This can be any format # you want, but I'll use the example one from the start of the post. tweet = "My training last week: {:d} workouts for {:.2f} miles and {:d} calories burned.".format(num_activities, mileage, calories) self.update_status(tweet)
def test_create_activity(self): """ Test Client.create_activity simple case. """ now = datetime.now().replace(microsecond=0) a = self.client.create_activity("test_create_activity#simple", activity_type=model.Activity.RIDE, start_date_local=now, elapsed_time=timedelta(hours=3, minutes=4, seconds=5), distance=uh.miles(15.2)) print(a) self.assertIsInstance(a, model.Activity) self.assertEqual("test_create_activity#simple", a.name) self.assertEqual(now, a.start_date_local) self.assertEqual(round(float(uh.miles(15.2)), 2), round(float(uh.miles(a.distance)), 2)) self.assertEqual(timedelta(hours=3, minutes=4, seconds=5), a.elapsed_time)
def test_create_activity(self): """ Test Client.create_activity simple case. """ now = datetime.now().replace(microsecond=0) a = self.client.create_activity("test_create_activity#simple", activity_type=model.Activity.RIDE, start_date_local=now, elapsed_time=timedelta(hours=3, minutes=4, seconds=5), distance=uh.miles(15.2)) print a self.assertIsInstance(a, model.Activity) self.assertEquals("test_create_activity#simple", a.name) self.assertEquals(now, a.start_date_local) self.assertEquals(round(float(uh.miles(15.2)), 2), round(float(uh.miles(a.distance)), 2)) self.assertEquals(timedelta(hours=3, minutes=4, seconds=5), a.elapsed_time)
def update_ride_from_activity(strava_activity, ride): """ Refactoring to just set ride properties from the Strava Activity object. :param strava_activity: The Strava Activyt :type strava_activity: stravalib.model.Activity :param ride: The ride model object. :type ride: Ride """ # Should apply to both new and preexisting rides ... # If there are multiple instagram photos, then request syncing of non-primary photos too. if strava_activity.photo_count > 1 and ride.photos_fetched is None: log.debug("Scheduling non-primary photos sync for {!r}".format(ride)) ride.photos_fetched = False ride.private = bool(strava_activity.private) ride.name = strava_activity.name ride.start_date = strava_activity.start_date_local # We need to round so that "1.0" miles in strava is "1.0" miles when we convert back from meters. ride.distance = round(float(unithelper.miles(strava_activity.distance)), 3) ride.average_speed = float(unithelper.mph(strava_activity.average_speed)) ride.maximum_speed = float(unithelper.mph(strava_activity.max_speed)) ride.elapsed_time = timedelta_to_seconds(strava_activity.elapsed_time) ride.moving_time = timedelta_to_seconds(strava_activity.moving_time) location_parts = [] if strava_activity.location_city: location_parts.append(strava_activity.location_city) if strava_activity.location_state: location_parts.append(strava_activity.location_state) location_str = ', '.join(location_parts) ride.location = location_str ride.commute = strava_activity.commute ride.trainer = strava_activity.trainer ride.manual = strava_activity.manual ride.elevation_gain = float(unithelper.feet(strava_activity.total_elevation_gain)) ride.timezone = str(strava_activity.timezone) # # Short-circuit things that might result in more obscure db errors later. if ride.elapsed_time is None: raise DataEntryError("Activities cannot have null elapsed time.") if ride.moving_time is None: raise DataEntryError("Activities cannot have null moving time.") if ride.distance is None: raise DataEntryError("Activities cannot have null distance.") log.debug("Writing ride for {athlete!r}: \"{ride!r}\" on {date}".format(athlete=ride.athlete.name, ride=ride.name, date=ride.start_date.strftime('%m/%d/%y')))
def get_activity_summary(activity): """Pulls activity metrics and returns a dict with name, id, distance, elevation, type, and date. """ vals = { "id": activity.id, "name": activity.name, "type": activity.type, "distance": unithelper.miles(activity.distance), "elevation": unithelper.feet(activity.total_elevation_gain), "date": activity.start_date.replace(tzinfo=TZ_LOCAL).strftime("%m/%d") } return vals
def get_total_miles(start, end, token): dotenv.load() client = Client(dotenv.get("STRAVA_TOKEN")) total_miles = 0 for activity in client.get_activities(after=start, before=end): total_miles += unithelper.miles(activity.distance).num return int(total_miles)
def runsToTable(runList): items = list() for act in runList: items.append( dict(dist=unithelper.miles(act.distance), time=act.moving_time.seconds, date=act.start_date, pace=minPerMile(act.average_speed), maxPace=minPerMile(act.max_speed), el=act.total_elevation_gain, name=act.name)) return tableCls(items)
def build_df_summary(self): self.df_summary = pd.DataFrame() self.df_summary['activity_id'] = [self.id] if self.start_latlng is not None: self.df_summary['start_lat'] = [self.start_latlng[0]] self.df_summary['start_lon'] = [self.start_latlng[1]] else: self.df_summary['start_lat'] = None self.df_summary['start_lon'] = None if self.end_latlng is not None: self.df_summary['end_lat'] = [self.end_latlng[0]] self.df_summary['end_lon'] = [self.end_latlng[1]] else: self.df_summary['end_lat'] = None self.df_summary['end_lon'] = None self.df_summary['achievement_count'] = [self.achievement_count] self.df_summary['activity_id'] = [self.id] self.df_summary['average_heartrate'] = [self.average_heartrate] self.df_summary['average_speed'] = [ unithelper.mph(self.average_speed).num ] self.df_summary['average_watts'] = [self.average_watts] self.df_summary['calories'] = [self.calories] self.df_summary['commute'] = [self.commute] self.df_summary['description'] = [self.description] self.df_summary['device_name'] = [self.device_name] self.df_summary['distance'] = [unithelper.miles(self.distance).num] self.df_summary['elapsed_time'] = [self.elapsed_time.seconds] self.df_summary['gear_id'] = [self.gear_id] self.df_summary['kilojoules'] = [self.kilojoules] self.df_summary['location_city'] = [self.location_city] self.df_summary['location_country'] = [self.location_country] self.df_summary['location_state'] = [self.location_state] self.df_summary['max_heartrate'] = [self.max_heartrate] self.df_summary['max_speed'] = [unithelper.mph(self.max_speed).num] self.df_summary['max_watts'] = [self.max_watts] self.df_summary['moving_time'] = [self.moving_time.seconds] self.df_summary['name'] = [self.name] self.df_summary['pr_count'] = [self.pr_count] self.df_summary['start_date_local'] = [self.start_date_local] self.df_summary['start_date_utc'] = [self.start_date] self.df_summary['start_day_local'] = [self.start_date_local.date()] self.df_summary['timezone'] = [str(self.timezone)] self.df_summary['total_elevation_gain'] = [ unithelper.feet(self.total_elevation_gain).num ] self.df_summary['trainer'] = [self.trainer] self.df_summary['type'] = [self.type] self.df_summary.set_index(['start_date_utc'], inplace=True)
def cycle(): try: if init_error: return jsonify(error=init_error), 500 access_token = get_access_token() client = Client(access_token) stats = client.get_athlete_stats() print(stats) ride_total = float(unithelper.miles(stats.ytd_ride_totals.distance)) return jsonify(ytd=ride_total, goal=year_goal) except Exception as e: return jsonify(error=str(e)), 500
def __init__(self, act): self.actId=act.id self.athId=act.athlete.id self.dist=float(unithelper.miles(act.distance)) self.time=act.moving_time.seconds self.date=act.start_date print "start_date type",type(act.start_date) try: self.pace=ru.minPerMile(act.average_speed) self.maxPace=ru.minPerMile(act.max_speed) except: self.pace=0. self.maxPace=0. self.el=unithelper.feet(act.total_elevation_gain) self.name=act.name
def insert_into_db(self, activities, activity_type): added = 0 skipped = 0 for activity in activities: obj, created = ActivityCache.objects.get_or_create( activity_type=activity_type, distance=unithelper.miles(activity.distance).num, name=activity.name, athlete=activity.athlete) if created: added = added + 1 else: skipped = skipped + 1 self.stdout.write("Added " + str(added) + " activities, and skipped " + str(skipped))
def add_activity(conn, athlete_id, Activity): """Adds an metrics from a DETAILED Activity object activity to the database """ table = TABLES["activities"] distance = float( unithelper.miles(Activity.distance) ) elevation = float( unithelper.feet(Activity.total_elevation_gain) ) date_time = Activity.start_date.strftime('%Y-%m-%d %H:%M:%S') statement = "INSERT INTO %s VALUES (%i, %i, '%s', '%s', %.2f, %.2f, '%s');" % \ (table, athlete_id, Activity.id, Activity.type, Activity.name, \ distance, elevation, Activity.start_date) try: cur = conn.cursor() cur.execute(statement) logger.info("Activity %i added for athlete %i" % (Activity.id, athlete_id)) except Exception, e: logger.critical("Error with activity %i for %i, error:\n%s" % (Activity.id, athlete_id, e))
r = open('data.json', 'r') data = json.load(r) activities = list(d["id"] for d in data) r.close() stravaActivities = client.get_activities() for activity in stravaActivities: if (activity.id in activities): print("Already have this activity!") continue a = client.get_activity(activity.id) if (a.type != "Run"): print("Activity was a run") continue print("Found a new activity!", activity.id) act = {} act["date"] = a.start_date_local.strftime("%y-%m-%d") act["id"] = a.id act["distance"] = unithelper.miles(a.distance).num act["duration"] = a.moving_time.seconds act["speed"] = a.average_speed.num * meterToMile * 3600 act["pace"] = float(1 / (meterToMile*a.average_speed)) act["name"] = a.name act["splits"] = list({"time":split.elapsed_time.total_seconds() , "distance": unithelper.miles(split.distance).num } for split in a.splits_standard) data.append(act) f = open('data.json', 'w') print(json.dumps(data, indent=4), file=f);
def add_ride(user, activity): return add_activity(user, RIDE_GOAL_SLUG, activity, unithelper.miles(activity.distance))
# per activity, get segment efforts for activity in activities: segment_efforts = client.get_activity(activity.id).segment_efforts # 4 # per segment effort for segment in segment_efforts: mysegments[segment.segment.id] = segment.segment # save to db # check if segment leaderboard contains any friends for key, segment in mysegments.iteritems(): leaderboard = client.get_segment_leaderboard(key, following=True).entries # 12 # get friend with time < athlete time for person in leaderboard: if person.athlete_id == 1869056: me = person index = leaderboard.index(me) if index > 0: other = leaderboard[index - 1] data = {} data['segment_name'] = segment.name data['person_ahead'] = other.athlete_name data['distance'] = str(unithelper.miles(segment.distance)) data['my_elapsed_time'] = str(me.elapsed_time) # data['my_moving_time'] = str(me.moving_time) data['their_elapsed_time'] = str(other.elapsed_time) # data['their_moving_time'] = str(other.moving_time) data['time_difference'] = str(me.elapsed_time - other.elapsed_time) print('') pprint(data)
def ride_distance(self): return '{0:0.3f}'.format(unithelper.miles(self.activity.distance).num)
def get_club_activities(client,cid): ids = [] names = [] distances = [] moving_times = [] total_elevation_gains = [] start_dates = [] start_latlngs = [] start_latitudes = [] start_longitudes = [] end_latlngs = [] maps = [] average_speeds = [] achievement_counts = [] athlete_counts = [] kudos_counts = [] workout_types = [] athletes = [] firstnames = [] lastnames = [] for a in client.get_club_activities(cid, limit=200): ids.append(a.id) names.append(a.name) distances.append(a.distance) moving_times.append(a.moving_time) total_elevation_gains.append(a.total_elevation_gain) start_dates.append(a.start_date_local) start_latlngs.append(a.start_latlng) start_latitudes.append(a.start_latitude) start_longitudes.append(a.start_longitude) end_latlngs.append(a.end_latlng) maps.append(a.map) average_speeds.append(a.average_speed) achievement_counts.append(a.achievement_count) athlete_counts.append(a.athlete_count) kudos_counts.append(a.kudos_count) workout_types.append(a.workout_type) firstnames.append(a.athlete.firstname) lastnames.append(a.athlete.lastname) for i in range(len(start_latitudes)): if start_latitudes[i] == None: start_latitudes[i] = np.nan for i in range(len(start_longitudes)): if start_longitudes[i] == None: start_longitudes[i] = np.nan #convert distances to miles, pull out just the number too distances_miles = [] for d in distances: d = unithelper.miles(d).num distances_miles.append(d) club_dict = {'ids':ids, 'names':names, 'distances':distances_miles, 'moving_times':moving_times,\ 'total_elevation_gains':total_elevation_gains,'start_dates':start_dates, \ 'start_latlngs':start_latlngs, 'start_latitudes':start_latitudes,\ 'start_longitudes':start_longitudes, 'end_latlngs':end_latlngs, 'maps':maps,\ 'average_speeds':average_speeds, 'achievement_counts':achievement_counts, \ 'athlete_counts':athlete_counts, 'kudos_counts':kudos_counts, 'workout_types':workout_types,\ 'firstname':firstnames, 'lastname':lastnames} club = pd.DataFrame(data = club_dict) return club
import os import sys sys.path.insert(0,os.path.join('..','Resources','AccessInformation')) from accessinformation import access_token from flask import Flask, render_template,jsonify from stravalib import Client , unithelper import json client = Client(access_token ) print(client.get_athlete()) print([float(unithelper.miles(i.distance)) for i in client.get_activities()]) print([i.segment_efforts for i in client.get_activities()]) with open('../Data/JSONData/MainDataset.json') as f: data = json.load(f) app = Flask(__name__) @app.route("/") def homepage(): return(render_template('index.html')) @app.route("/data") def dataset(): return(jsonify(data)) if __name__ == '__main__': app.run()
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, ))
def write_ride(activity): """ Takes the specified activity and writes it to the database. :param activity: The Strava :class:`stravalib.orm.Activity` object. :type activity: stravalib.orm.Activity :return: A tuple including the written Ride model object, whether to resync segment efforts, and whether to resync photos. :rtype: bafs.orm.Ride """ if activity.start_latlng: start_geo = WKTSpatialElement('POINT({lon} {lat})'.format( lat=activity.start_latlng.lat, lon=activity.start_latlng.lon)) else: start_geo = None if activity.end_latlng: end_geo = WKTSpatialElement('POINT({lon} {lat})'.format( lat=activity.end_latlng.lat, lon=activity.end_latlng.lon)) else: end_geo = None athlete_id = activity.athlete.id # Fail fast for invalid data (this can happen with manual-entry rides) assert activity.elapsed_time is not None assert activity.moving_time is not None assert activity.distance is not None # Find the model object for that athlete (or create if doesn't exist) athlete = meta.scoped_session().query(Athlete).get(athlete_id) if not athlete: # The athlete has to exist since otherwise we wouldn't be able to query their rides raise ValueError( "Somehow you are attempting to write rides for an athlete not found in the database." ) if start_geo is not None or end_geo is not None: ride_geo = RideGeo() ride_geo.start_geo = start_geo ride_geo.end_geo = end_geo ride_geo.ride_id = activity.id meta.scoped_session().merge(ride_geo) ride = meta.scoped_session().query(Ride).get(activity.id) new_ride = (ride is None) if ride is None: ride = Ride(activity.id) # Check to see if we need to pull down efforts for this ride if new_ride: ride.detail_fetched = False # Just to be explicit if not activity.manual: ride.track_fetched = False # photo_count refers to instagram photos if activity.photo_count > 1: ride.photos_fetched = False else: ride.photos_fetched = None else: if round(ride.distance, 2) != round( float(unithelper.miles(activity.distance)), 2): log.info( "Queing resync of details for activity {0!r}: distance mismatch ({1} != {2})" .format(activity, ride.distance, unithelper.miles(activity.distance))) ride.detail_fetched = False ride.track_fetched = False ride.athlete = athlete update_ride_from_activity(strava_activity=activity, ride=ride) meta.scoped_session().add(ride) return ride
def write_ride(self, activity: Activity) -> Ride: """ Takes the specified activity and writes it to the database. :param activity: The Strava :class:`stravalib.orm.Activity` object. :return: A tuple including the written Ride model object, whether to resync segment efforts, and whether to resync photos. :rtype: bafs.orm.Ride """ session = meta.scoped_session() if activity.start_latlng: start_geo = WKTSpatialElement("POINT({lon} {lat})".format( lat=activity.start_latlng.lat, lon=activity.start_latlng.lon)) else: start_geo = None if activity.end_latlng: end_geo = WKTSpatialElement("POINT({lon} {lat})".format( lat=activity.end_latlng.lat, lon=activity.end_latlng.lon)) else: end_geo = None athlete_id = activity.athlete.id # Fail fast for invalid data (this can happen with manual-entry rides) assert activity.elapsed_time is not None assert activity.moving_time is not None assert activity.distance is not None # Find the model object for that athlete (or create if doesn't exist) athlete = session.query(Athlete).get(athlete_id) if not athlete: # The athlete has to exist since otherwise we wouldn't be able to query their rides raise ValueError( "Somehow you are attempting to write rides for an athlete not found in the database." ) if start_geo is not None or end_geo is not None: ride_geo = RideGeo() ride_geo.start_geo = start_geo ride_geo.end_geo = end_geo ride_geo.ride_id = activity.id session.merge(ride_geo) ride = session.query(Ride).get(activity.id) new_ride = ride is None if ride is None: ride = Ride(activity.id) if new_ride: # Set the "workflow flags". These all default to False in the database. The value of NULL means # that the workflow flag does not apply (e.g. do not bother fetching this) ride.detail_fetched = False # Just to be explicit if not activity.manual: ride.track_fetched = False # photo_count refers to instagram photos if activity.photo_count > 1: ride.photos_fetched = False else: ride.photos_fetched = None else: # If ride has been cropped, we re-fetch it. if round(ride.distance, 2) != round( float(unithelper.miles(activity.distance)), 2): self.logger.info( "Queing resync of details for activity {0!r}: " "distance mismatch ({1} != {2})".format( activity, ride.distance, unithelper.miles(activity.distance))) ride.detail_fetched = False ride.track_fetched = False ride.athlete = athlete self.update_ride_basic(strava_activity=activity, ride=ride) if new_ride: statsd.histogram("strava.activity.distance", ride.distance) session.add(ride) return ride
from stravalib import unithelper client = Client() # authorize_url = client.authorization_url(client_id=os.environ['CLIENT_ID'], # redirect_uri='http://localhost:8282/authorized') client.access_token = os.environ['ACCESS_TOKEN'] # ali = client.get_athlete() #print(ali) acts = client.get_activities(before=None, after=None, limit=10) for act in acts: print(act.id, act.name, unithelper.miles(act.distance), act.description) #testing #ryan = client.get_athlete(6777976) #print ryan.city # Activities can have many streams, you can request n desired stream types types = [ 'time', 'latlng', 'altitude', 'heartrate', 'temp', ]
def meters_to_miles(value): return unithelper.miles(unit('m')(value))
activities = strava.get_activities( limit = 10 ) #for activity in activities: # print activity.type # Iterate through all valid activity types #for activity_id in MMF_BIKE_ACTIVITY_TYPES: # workouts = workouts + mmf.workout.search( user=MMF_USER_ID, activity_type=activity_id, started_after=started_after ) for activity in activities: start_datetime = activity.start_date_local start_date = start_datetime.strftime( '%Y-%m-%d' ) start_time = start_datetime.strftime( '%H:%M' ) duration_milliseconds = int( 1000 * activity.moving_time.total_seconds() ) distance = unithelper.miles( activity.distance ).num dupe = False activity_information = { 'startTime' : start_time, 'durationMillis': duration_milliseconds, 'date' : start_date, 'distance' : distance } # If it's a ride in strava we have a direct mapping to FitBit, otherwise we need to use a custom activity type if activity.type == 'Ride': activity_information['activityId'] = FITBIT_BIKE_ACTIVITY_ID elif activity.type == 'Hike': activity_information['activityId'] = FITBIT_HIKE_ACTIVITY_ID
# Authenticate with Strava. # token_response = client.exchange_code_for_token(client_id=client_id, client_secret=client_secret, code=client_code) client.access_token = token_response['access_token'] client.refresh_token = token_response['refresh_token'] client.expires_at = token_response['expires_at'] athlete = client.get_athlete() print("Retrieving records of the past {days} days for {id}: {firstname} {lastname}".format( days=numdays, id=athlete.id, firstname=athlete.firstname, lastname=athlete.lastname)) activities = list(client.get_activities(after=then, before=now)) activities.reverse() for activity in activities: if (activity.gear_id is None): gear_name = "N/A" else: if ((gear is None) or gear.id != activity.gear_id): gear = client.get_gear(activity.gear_id) gear_name = gear.name distance=unithelper.miles(activity.distance).get_num() speed=unithelper.miles_per_hour(activity.average_speed).get_num() print("{dt}, , {bike}, {distance:.2f}, {speed:.1f}, {time}, \"{name}\", {pr} PRs".format( dt=activity.start_date.strftime("%m/%d/%y %H:%M"), bike=gear_name, distance=distance, speed=speed, time=activity.moving_time, name=activity.name, pr=activity.pr_count))
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 runsToTable(runList): items=list() for act in runList: items.append(dict(dist=unithelper.miles(act.distance), time=act.moving_time.seconds, date=act.start_date, pace=minPerMile(act.average_speed), maxPace=minPerMile(act.max_speed), el=act.total_elevation_gain, name=act.name)) return tableCls(items)
hikedis = [] hikeelev = [] snowshoe = [] snowdis = [] snowelev = [] for a in activities: atype.append(a.type) types = set(atype) print types for a in activities: if a.type == 'Run': run.append(a) rundis.append(float(unithelper.miles(a.distance))) runelev.append(float(unithelper.feet(a.total_elevation_gain))) elif a.type == 'Walk': walk.append(a) walkdis.append(float(unithelper.miles(a.distance))) walkelev.append(float(unithelper.feet(a.total_elevation_gain))) elif a.type == 'Ride': ride.append(a) ridedis.append(float(unithelper.miles(a.distance))) rideelev.append(float(unithelper.feet(a.total_elevation_gain))) elif a.type == 'Hike': hike.append(a) hikedis.append(float(unithelper.miles(a.distance))) hikeelev.append(float(unithelper.feet(a.total_elevation_gain))) elif a.type == 'Snowshoe': snowshoe.append(a)
sdf = pd.DataFrame(dict((stype, stream.data) for (stype, stream) in streams.iteritems())) if "latlng" in stream_filter: sdf["lat"] = [a[0] for a in sdf.latlng] sdf["lng"] = [a[1] for a in sdf.latlng] del sdf["latlng"] detail_fname = join(output_detail_dir, "{0}.json".format(act.id)) sdf.to_json(detail_fname) # with open(join(output_detail_dir, "{0}.p".format(act.id)), "wb") as f: # pickle.dump(sdf, f, 2) print "{0} on {1:%d %b %Y} [kudos {2}]".format(act.name, act.start_date, act.kudos_count) print "\tHR: {0}".format(act.average_heartrate) print "\tDistance: {0}".format(unithelper.miles(act.distance)) print "\tSpeed: {0}".format(unithelper.mph(act.average_speed)) item = dict((k, func(getattr(act, k, None))) for k, func in save_fields.iteritems()) data.append(item) start_dates.append(act.start_date) df = pd.DataFrame(data=data, index=start_dates) summary_fname = join(output_dir, "summary.json") df.to_json(summary_fname) # with open(join(output_dir, "summary.p"), "wb") as f: # pickle.dump(df, f, 2) df.to_csv(join(output_dir, "summary.csv"))
def massive_test(access_token, athlete_id): client = Client(access_token=access_token) mysegments = {} # all segments a user has ridden # get athlete activities athlete_from_db = Athlete.objects.get(strava_id=athlete_id) activities = client.get_activities(limit=5, before=athlete_from_db.oldest_activity_date) # API call # per activity, get segment efforts for activity in activities: if activity.type not in ['Ride', 'ride']: continue try: # if activity already exists in db, skip it Activity.objects.get(strava_id=activity.id) continue except Activity.DoesNotExist: new_activity = Activity() new_activity.strava_id = activity.id new_activity.start_lat = activity.start_latitude new_activity.start_long = activity.start_longitude new_activity.start_date = activity.start_date new_activity.save() # update newest / oldest activity dates if athlete_from_db.newest_activity_date is None: athlete_from_db.newest_activity_date = activity.start_date athlete_from_db.oldest_activity_date = activity.start_date else: if activity.start_date > athlete_from_db.newest_activity_date: athlete_from_db.newest_activity_date = activity.start_date elif activity.start_date < athlete_from_db.oldest_activity_date: athlete_from_db.oldest_activity_date = activity.start_date athlete_from_db.save() segment_efforts = client.get_activity(activity.id).segment_efforts # API call # per segment effort for segment in segment_efforts: mysegments[segment.segment.id] = segment.segment # save to db # check if segment leaderboard contains any friends for key, segment in mysegments.iteritems(): leaderboard = client.get_segment_leaderboard(key, following=True).entries # API call (possibly lots, depends on number of segments) # get friend with time < athlete time for i, entry in enumerate(leaderboard): if entry.athlete_id == athlete_id: me = entry if i == 0: # I'm already the winner! break j = 1 while j <= i and leaderboard[i - j].elapsed_time == me.elapsed_time: # check for ties, compare each entry from i to zero (possibly) j += 1 if leaderboard[i - j].elapsed_time == me.elapsed_time: # if they're still tied at the end of the loop, I don't want to see it break other = leaderboard[i - j] try: new_segment = ChallengedSegment.objects.get(my_id=athlete_id, segment_id=segment.id) except ChallengedSegment.DoesNotExist: new_segment = ChallengedSegment() new_segment.my_id = athlete_id new_segment.their_id = other.athlete_id new_segment.their_name = other.athlete_name new_segment.my_pr = me.activity_id new_segment.their_pr = other.activity_id new_segment.my_time = str(me.elapsed_time) new_segment.their_time = str(other.elapsed_time) new_segment.difference = str(me.elapsed_time - other.elapsed_time) new_segment.segment_id = segment.id new_segment.segment_name = segment.name new_segment.segment_distance = str(unithelper.miles(segment.distance)) new_segment.save() break # we already found my entry, why keep looking through the list?
def getChallengeRuns(challengeName="strava-races-10k-2015-10"): # taking athletes from http://www.strava.com/challenges/turn-up-the-heat-run # there are 17311 athletes registered for that challenge detailsUrl="https://www.strava.com/challenges/"+challengeName+"/details" athPerPage=1 r = requests.get(detailsUrl) data = json.loads(r.text) nAthletes=int(data["totals"]["participants"]) nActivities=int(data["totals"]["num_activities"]) total_pages = nAthletes/athPerPage challenges=[] for page in range(1, total_pages + 2): pageUrl = detailsUrl+('?paging_type=' 'overall&per_page=%s&overall_page=%s&overall_male_page=1' '&overall_female_page=1' %(athPerPage, page)) r = requests.get(pageUrl) data = json.loads(r.text) for r in data['data'].values(): challenges.append(models.Challenge(time=float(unithelper.seconds(r['moving_time'])), distance=float(unithelper.miles(r['distance'])), athId=r['id'])) break print len(challenges) time.sleep(TIME_BT_REQUESTS) return challenges
def to_miles(dist): return float(unithelper.miles(dist))
def distance(self): return '{0:0.3f}'.format(unithelper.miles(self._segment.distance).num)
activities_packaged = [] record = 1 for i in activities: print('Processing activity {0}'.format(record)) try: already_processed[i.id] # If this succeeds it's already processed except: activity = data_proxy.getActivity(i.id) types = ['time', 'latlng', 'altitude', 'heartrate', 'temp'] streams = data_proxy.getActivityStreams(i.id, types) to_add = { 'id': i.id, 'name': i.name, 'distance': float(unithelper.miles(activity.distance)), 'date': str(i.start_date) } for i in streams: try: to_add[i] = streams[i].data except: print('No {0} data for this activity'.format(i)) to_save['activities'] += [to_add] to_save['count'] = len(to_save['activities']) save(to_save) record += 1 print('Saving...') print(to_save) save(to_save)
def main(): assert len(args.athlete_ids) == len(args.access_tokens) logger.info("app id: %i, fetching activities for ids %s" % \ (args.id_strava_app, str(args.athlete_ids))) for i in range( len(args.access_tokens) ): # for each athlete client = Client() client.access_token = args.access_tokens[i] athlete_id = args.athlete_ids[i] # get summary activities first (filterd before detailed activity call) time.sleep(TIME_PAUSE) activity_ids = get_user_activities(client) # now fetch detailed versions, add to db detailed_activites = [] activity_to_segments = {} # { act_id: # { seg_id : # { "distance" : x, "grade" : y }, }, } segment_ranks = {} # { seg_id : { "auth_athlete_rank" : auth_rank, # "other_athletes" : { other_id : other_rank, } } } for act_id in activity_ids: try: activity_to_segments[act_id] = {} time.sleep(TIME_PAUSE) detailed_activity = client.get_activity( act_id ) detailed_activites.append( detailed_activity ) for seg_effort in detailed_activity.segment_efforts: segment = seg_effort.segment seg_id = int(segment.id) seg_dist = float( unithelper.miles(segment.distance) ) seg_grade = segment.average_grade seg_dct = { "distance" : seg_dist, "grade" : seg_grade } activity_to_segments[act_id][seg_id] = seg_dct if segment_ranks.has_key(seg_id): # already have ranks continue # might be overlap between activities else: try: # some = hazardous = error time.sleep(TIME_PAUSE) # now get ranks for this segment leaderboard_entries = \ client.get_segment_leaderboard(seg_id, top_results_limit=1).entries segment_ranks[seg_id] = { "auth_athlete_rank" : -1, "other_athletes" : {} } for entry in leaderboard_entries: if entry.athlete_id == athlete_id: segment_ranks[seg_id]["auth_athlete_rank"] = entry.rank continue other_id = entry.athlete_id other_rank = entry.rank segment_ranks[seg_id]["other_athletes"][other_id] = other_rank except Exception, e: logger.warning("Error with segment_id %i, removing from activity,"\ " trace:\n %s" % (seg_id, traceback.print_exc())) activity_to_segments[act_id].pop(seg_id) continue if len(activity_to_segments[act_id]) > 0: add_activity(conn, athlete_id, detailed_activity) # if made it here, okay else: logger.info("No segments for activity %i, skipping" % act_id) except Exception, e: # occurs with wrong privaleges, eg private activity logger.warning("Error with activity %i for athlete %i, popping. tracebac:\n%s" % \ (act_id, athlete_id, traceback.print_exc())) activity_to_segments.pop(act_id)
def write_ride(activity): """ Takes the specified activity and writes it to the database. :param activity: The Strava :class:`stravalib.model.Activity` object. :type activity: stravalib.model.Activity :return: A tuple including the written Ride model object, whether to resync segment efforts, and whether to resync photos. :rtype: bafs.model.Ride """ if activity.start_latlng: start_geo = WKTSpatialElement('POINT({lon} {lat})'.format(lat=activity.start_latlng.lat, lon=activity.start_latlng.lon)) else: start_geo = None if activity.end_latlng: end_geo = WKTSpatialElement('POINT({lon} {lat})'.format(lat=activity.end_latlng.lat, lon=activity.end_latlng.lon)) else: end_geo = None athlete_id = activity.athlete.id # Fail fast for invalid data (this can happen with manual-entry rides) assert activity.elapsed_time is not None assert activity.moving_time is not None assert activity.distance is not None # Find the model object for that athlete (or create if doesn't exist) athlete = db.session.query(Athlete).get(athlete_id) if not athlete: # The athlete has to exist since otherwise we wouldn't be able to query their rides raise ValueError("Somehow you are attempting to write rides for an athlete not found in the database.") if start_geo is not None or end_geo is not None: ride_geo = RideGeo() ride_geo.start_geo = start_geo ride_geo.end_geo = end_geo ride_geo.ride_id = activity.id db.session.merge(ride_geo) ride = db.session.query(Ride).get(activity.id) new_ride = (ride is None) if ride is None: ride = Ride(activity.id) # Check to see if we need to pull down efforts for this ride if new_ride: ride.detail_fetched = False # Just to be explicit if not activity.manual: ride.track_fetched = False # photo_count refers to instagram photos if activity.photo_count > 1: ride.photos_fetched = False else: ride.photos_fetched = None else: if round(ride.distance, 2) != round(float(unithelper.miles(activity.distance)), 2): log.info("Queing resync of details for activity {0!r}: distance mismatch ({1} != {2})".format(activity, ride.distance, unithelper.miles(activity.distance))) ride.detail_fetched = False ride.track_fetched = False ride.athlete = athlete update_ride_from_activity(strava_activity=activity, ride=ride) db.session.add(ride) return ride
schema = '"ID","Name","Distance (mi)","Moving time (s)","Elapsed time (s)","Elevation gain (ft)","Avg speed (mph)","Max speed (mph)","Avg cadence","Avg temp (C)","Avg HR","Max HR","Calories","Shoes","Start timestamp (local)","Start Lat","Start Lng","End Lat","End Lng","City","State","Country","Achievements","Kudos","Workout type"\n' print 'Writing schema...' outputfile.write(schema) runs = 0 print 'Writing activities...' for x in range(total_activities-1,-1,-1): curr_activity = activity_list[x] if curr_activity.type == 'Run': print("Writing activity {i} (Run): {act_id}".format(i=x, act_id=curr_activity.id)) curr_activity_full = client.get_activity(curr_activity.id) record = '' record = record + '"' + xstr(curr_activity_full.id) + '",' record = record + '"' + xstr(curr_activity_full.name) + '",' record = record + '"' + xstr(unithelper.miles(curr_activity_full.distance).num) + '",' record = record + '"' + xstr(curr_activity_full.moving_time.seconds) + '",' record = record + '"' + xstr(curr_activity_full.elapsed_time.seconds) + '",' record = record + '"' + xstr(unithelper.feet(curr_activity_full.total_elevation_gain).num) + '",' record = record + '"' + xstr(unithelper.miles_per_hour(curr_activity_full.average_speed).num) + '",' record = record + '"' + xstr(unithelper.miles_per_hour(curr_activity_full.max_speed).num) + '",' record = record + '"' + xstr(curr_activity_full.average_cadence) + '",' record = record + '"' + xstr(curr_activity_full.average_temp) + '",' record = record + '"' + xstr(curr_activity_full.average_heartrate) + '",' record = record + '"' + xstr(curr_activity_full.max_heartrate) + '",' record = record + '"' + xstr(curr_activity_full.calories) + '",' record = record + '"' + xstr(curr_activity_full.gear.name) + '",' record = record + '"' + xstr(createTimestamp(curr_activity_full.start_date_local)) + '",' start_lat = ''