From b58ba932fd27bb2683e1545eb91a10d7b2ef58f7 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Fri, 21 May 2021 09:36:38 +0200 Subject: [PATCH 01/12] removed UnderArmour / MapMyFitness --- rowers/admin.py | 2 - rowers/c2stuff.py | 78 +-- rowers/models.py | 7 - rowers/tasks.py | 36 +- rowers/templates/export.html | 209 ------- rowers/templates/imports.html | 137 ----- rowers/templates/menu_other.html | 1 - rowers/templates/menu_workout.html | 15 - rowers/templates/menu_workouts.html | 1 - rowers/templates/rower_exportsettings.html | 6 +- rowers/templates/underarmour_list_import.html | 41 -- rowers/tests/test_imports.py | 103 ---- rowers/traverselinktest.py | 1 - rowers/underarmourstuff.py | 544 ------------------ rowers/uploads.py | 13 +- rowers/urls.py | 5 - rowers/utils.py | 9 + rowers/views/importviews.py | 350 +---------- rowers/views/statements.py | 6 +- rowers/views/userviews.py | 1 - rowers/views/workoutviews.py | 15 - rowsandall_app/urls.py | 1 - 22 files changed, 54 insertions(+), 1527 deletions(-) delete mode 100644 rowers/templates/export.html delete mode 100644 rowers/templates/imports.html delete mode 100644 rowers/templates/underarmour_list_import.html delete mode 100644 rowers/underarmourstuff.py diff --git a/rowers/admin.py b/rowers/admin.py index 9b6be6ab..5c179e88 100644 --- a/rowers/admin.py +++ b/rowers/admin.py @@ -46,8 +46,6 @@ class RowerInline(admin.StackedInline): 'sporttrackstoken','sporttrackstokenexpirydate', 'sporttracksrefreshtoken', 'sporttracks_auto_export', - 'underarmourtoken','underarmourtokenexpirydate', - 'underarmourrefreshtoken', 'mapmyfitness_auto_export', 'tptoken','tptokenexpirydate','tprefreshtoken', 'trainingpeaks_auto_export', diff --git a/rowers/c2stuff.py b/rowers/c2stuff.py index 3f3346ac..e533a713 100644 --- a/rowers/c2stuff.py +++ b/rowers/c2stuff.py @@ -22,15 +22,7 @@ from scipy import optimize from json.decoder import JSONDecodeError from pytz.exceptions import UnknownTimeZoneError - -def dologging(s): - tstamp = time.localtime() - timestamp = time.strftime('%b-%d-%Y %H:%M:%S', tstamp) - with open('debuglog.log','a') as f: - f.write('\n') - f.write(timestamp) - f.write(' ') - f.write(s) +from rowers.utils import dologging from rowsandall_app.settings import ( C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET, @@ -39,6 +31,7 @@ from rowsandall_app.settings import ( from rowers.tasks import ( handle_c2_import_stroke_data, handle_c2_sync, handle_c2_async_workout, + handle_c2_getworkout ) import django_rq queue = django_rq.get_queue('default') @@ -840,64 +833,15 @@ def get_workout(user,c2id,do_async=False): elif (timezone.now()>r.tokenexpirydate): s = "Token expired. Needs to refresh." return custom_exception_handler(401,s),0 - else: - # ready to fetch. Hurray - authorizationstring = str('Bearer ' + r.c2token) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - url = "https://log.concept2.com/api/users/me/results/"+str(c2id) - s = requests.get(url,headers=headers) - if s.status_code != 200: # pragma: no cover - if s.status_code == 404: - raise PermissionDenied("You have no access to this resource") - else: - s = "Something went wrong with the import" - return custom_exception_handler(401,s), 0 + job = myqueue(queuehigh, + handle_c2_getworkout, + user.id, + r.c2token, + c2id, + r.defaulttimezone) - data = s.json()['data'] - alldata = {c2id:data} - splitdata = None - #with open('c2temp.json','w') as f: - # f.write(json.dumps(s.json())) - # print(s.json()) - - if do_async: - print('aap',alldata) - job = myqueue(queuehigh, - handle_c2_async_workout, - alldata, - r.user.id, - r.c2token, - c2id, - 0, - r.defaulttimezone) - - return data, pd.DataFrame() - - - if 'workout' in data: - if 'splits' in data['workout']: # pragma: no cover - splitdata = data['workout']['splits'] - elif 'intervals' in data['workout']: # pragma: no cover - splitdata = data['workout']['intervals'] - else: # pragma: no cover - splitdata = None - - # Check if workout has stroke data, and get the stroke data - - if data['stroke_data']: - res2 = get_c2_workout_strokes(user,c2id) - if res2.status_code == 200: - strokedata = pd.DataFrame.from_dict(res2.json()['data']) - else: # pragma: no cover - strokedata = pd.DataFrame() - else: # pragma: no cover - strokedata = pd.DataFrame() - - - return data,strokedata + return 1 # Get stroke data belonging to C2 ID def get_c2_workout_strokes(user,c2id): @@ -1027,9 +971,9 @@ def workout_c2_upload(user,w,asynchron=False): if not c2userid: # pragma: no cover raise NoTokenError("User has no token") - dologging('Upload to C2 user {userid}'.format(userid=user.id)) + dologging('debuglog.log','Upload to C2 user {userid}'.format(userid=user.id)) data = createc2workoutdata(w) - dologging(json.dumps(data)) + dologging('debuglog.log',json.dumps(data)) if data == 0: # pragma: no cover return "Error: No data file. Contact info@rowsandall.com if the problem persists",0 diff --git a/rowers/models.py b/rowers/models.py index d5449391..7b72f243 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -988,10 +988,6 @@ class Rower(models.Model): sporttracksrefreshtoken = models.CharField(default='',max_length=200, blank=True,null=True) sporttracks_auto_export = models.BooleanField(default=False) - underarmourtoken = models.CharField(default='',max_length=200,blank=True,null=True) - underarmourtokenexpirydate = models.DateTimeField(blank=True,null=True) - underarmourrefreshtoken = models.CharField(default='',max_length=200, - blank=True,null=True) mapmyfitness_auto_export = models.BooleanField(default=False) tptoken = models.CharField(default='',max_length=1000,blank=True,null=True) tptokenexpirydate = models.DateTimeField(blank=True,null=True) @@ -3201,7 +3197,6 @@ class Workout(models.Model): maxhr = models.BigIntegerField(blank=True,null=True) uploadedtostrava = models.BigIntegerField(default=0) uploadedtosporttracks = models.BigIntegerField(default=0) - uploadedtounderarmour = models.BigIntegerField(default=0) uploadedtotp = models.BigIntegerField(default=0) uploadedtorunkeeper = models.BigIntegerField(default=0) uploadedtogarmin = models.BigIntegerField(default=0) @@ -3283,7 +3278,6 @@ class TombStone(models.Model): uploadedtoc2 = models.IntegerField(default=0) uploadedtostrava = models.BigIntegerField(default=0) uploadedtosporttracks = models.BigIntegerField(default=0) - uploadedtounderarmour = models.BigIntegerField(default=0) uploadedtotp = models.BigIntegerField(default=0) uploadedtorunkeeper = models.BigIntegerField(default=0) uploadedtonk = models.BigIntegerField(default=0) @@ -3294,7 +3288,6 @@ def create_tombstone_on_delete(sender, instance, **kwargs): user=instance.user, uploadedtoc2 = instance.uploadedtoc2, uploadedtostrava = instance.uploadedtostrava, - uploadedtounderarmour = instance.uploadedtounderarmour, uploadedtotp = instance.uploadedtotp, uploadedtorunkeeper = instance.uploadedtorunkeeper, uploadedtonk = instance.uploadedtonk diff --git a/rowers/tasks.py b/rowers/tasks.py index 72a9528a..df1a1c5d 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -25,6 +25,8 @@ from rowingdata import rowingdata as rdata from datetime import timedelta from sqlalchemy import create_engine +from rowers.imports import splituadata + #from celery import app from rowers.celery import app from celery import shared_task @@ -64,7 +66,7 @@ from django_rq import job from django.utils import timezone from django.utils.html import strip_tags -from rowers.utils import deserialize_list,ewmovingaverage,wavg +from rowers.utils import deserialize_list,ewmovingaverage,wavg,dologging from rowers.emails import htmlstrip from rowers import mytypes @@ -125,15 +127,6 @@ from rowers.courseutils import ( InvalidTrajectoryError ) -def dologging(s): - tstamp = time.localtime() - timestamp = time.strftime('%b-%d-%Y %H:%M:%S', tstamp) - with open('debuglog.log','a') as f: - f.write('\n') - f.write(timestamp) - f.write(' ') - f.write(s) - # Concept2 logbook sends over split data for each interval # We use it here to generate a custom summary # Some users complained about small differences @@ -2985,7 +2978,23 @@ def handle_nk_async_workout(alldata,userid,nktoken,nkid,delaysec,defaulttimezone # return return workoutid +@app.task +def handle_c2_getworkout(userid,c2token,c2id,defaulttimezone,debug=False,**kwargs): + authorizationstring = str('Bearer ' + c2token) + headers = {'Authorization': authorizationstring, + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} + url = "https://log.concept2.com/api/users/me/results/"+str(c2id) + s = requests.get(url,headers=headers) + if s.status_code != 200: # pragma: no cover + return 0 + + data = s.json()['data'] + alldata = {c2id:data} + splitdata = None + + return handle_c2_async_workout(alldata,userid,c2token,c2id,0,defaulttimezone) @app.task def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone,debug=False,**kwargs): @@ -3007,8 +3016,8 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone weightclass = data['weight_class'] s = 'User {userid}, C2 ID {c2id}'.format(userid=userid,c2id=c2id) - dologging(s) - dologging(json.dumps(data)) + dologging('debuglog.log',s) + dologging('debuglog.log',json.dumps(data)) try: title = data['name'] @@ -3041,7 +3050,7 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone s = 'Time zone {timezone}, stardatetime {startdatetime}, duration {duration}'.format( timezone=timezone,startdatetime=startdatetime, duration=duration) - dologging(s) + dologging('debuglog.log',s) @@ -3246,6 +3255,7 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone return workoutid + @app.task def fetch_strava_workout(stravatoken,oauth_data,stravaid,csvfilename,userid,debug=False,**kwargs): fetchresolution = 'high' diff --git a/rowers/templates/export.html b/rowers/templates/export.html deleted file mode 100644 index e28275c0..00000000 --- a/rowers/templates/export.html +++ /dev/null @@ -1,209 +0,0 @@ -{% extends "base.html" %} -{% load static %} -{% load rowerfilters %} - -{% block title %}Export {% endblock %} - -{% block content %} -
- - -

Export Workout

- -
-

- Edit Workout -

-
-
-

- Workflow View -

-
-
-

- Advanced Edit -

- -
- -
-

- Click on the icon to upload this workout to your site of choice. A checkmark indicates that the workout has already been uploaded. If the button is grayed out, click it to authorize the connection to that site. Use TCX or CSV export to email a TCX or CSV file of your workout to yourself. -

- -
- - {% if workout.uploadedtoc2 == 0 %} - {% if user.rower.c2token == None or user.rower.c2token == '' %} -
- - C2 icon -
- {% else %} -
- Concept2 icon -
- {% endif %} - {% else %} -
- - Concept2 icon -
- {% endif %} - - {% if workout.uploadedtostrava == 0 %} - {% if user.rower.stravatoken == None or user.rower.stravatoken == '' %} -
- - Strava icon -
- {% else %} -
- Strava icon -
- {% endif %} - {% else %} -
- - Concept2 icon -
- {% endif %} - {% if workout.uploadedtosporttracks == 0 %} - {% if user.rower.sporttrackstoken == None or user.rower.sporttrackstoken == '' %} -
- - SportTracks icon -
- {% else %} -
- - SportTracks icon -
- {% endif %} - {% else %} -
- - Concept2 icon -
- {% endif %} -
- - TCX Export -
- -
- - CSV Export -
- -
- {% if workout.uploadedtorunkeeper == 0 %} - {% if user.rower.runkeepertoken == None or user.rower.runkeepertoken == '' %} -
- - Runkeeper icon -
- {% else %} -
- Runkeeper icon -
- {% endif %} - {% else %} -
- - Runkeeper icon -
- {% endif %} - - {% if workout.uploadedtounderarmour == 0 %} - {% if user.rower.underarmourtoken == None or user.rower.underarmourtoken == '' %} -
- - Underarmour icon -
- {% else %} -
- Underarmour icon -
- {% endif %} - {% else %} -
- - Underarmour icon -
- {% endif %} - - {% if workout.uploadedtotp == 0 %} - {% if user.rower.tptoken == None or user.rower.tptoken == '' %} -
- - TrainingPeaks icon -
- {% else %} -
- Tp icon -
- {% endif %} - {% else %} -
- - TrainingPeaks icon -
- {% endif %} - -
- - GPX Export -
-
- -
- -
-

Connect

- -
-

Click one of the below logos to connect to the service of your choice. - You only need to do this once. After that, the site will have access until you - revoke the authorization for the "rowingdata" app.

- -
-

connect with strava

- -
-
-

connect with Concept2

-
- - -
-

connect with SportTracks

-
- -
-
-
-

connect with Runkeeper

-
-
-

connect with Under Armour

-
-
-

connect with TrainingPeaks

-
-
-
-

-

Export Settings

- -

-
- -
- - - -{% endblock %} diff --git a/rowers/templates/imports.html b/rowers/templates/imports.html deleted file mode 100644 index f2bd719a..00000000 --- a/rowers/templates/imports.html +++ /dev/null @@ -1,137 +0,0 @@ - {% extends "base.html" %} - {% block title %}Import Workouts{% endblock title %} - {% block content %} - -
-

Import Workouts

- -
-
-

- strava logo -

-
-
-

Import workouts from Strava

-
-
-
-
-

- Concept2 logo -

-
-
-

Import workouts from the Concept2 logbook

-
-
-

- SportTracks logo -

-
-
-

Import workouts from SportTracks

-
-
-
-
-

- Runkeeper logo -

-
-
-

Import workouts from RunKeeper

-
-
-
-
-

- Under Armour logo -

-
-
-

Import workouts from MapMyFitness/UnderArmour

-
-
-
-
-

- Polar logo -

-
-
-

Import workouts from Polar Flow.

Note: No workout selection possible. Automatically imports all new workouts

-
-
-
- -
-

Connect

- -
-

Click one of the below logos to connect to the service of your choice. - You only need to do this once. After that, the site will have - access until you - revoke the authorization for the "rowingdata" app.

- -
-

connect with strava

- -
-
-

connect with Concept2

-
- - -
-

connect with SportTracks

-
- -
-
-
-

connect with RunKeeper

-
-
-

connect with Under Armour

-
-
-

connect with Polar

-
-
- -

Auto Import/Export Settings

- - -

Use the form below to set your auto import/export settings. - As we implement auto import/export for various partner sites, this form will be expanded.

- -

Auto Import = rowsandall.com will regularly poll the partner site for new - workouts and automatically import new workouts -

- -

Auto Export = New workouts uploaded to rowsandall.com will be automatically synchronized - to the partner site

- -

These settings only have effect if you are a user on one - of the paid plans

- -
-
- - {{ form.as_table }} -
- {% csrf_token %} -
- -
-
-
- - -
- - - {% endblock content %} - diff --git a/rowers/templates/menu_other.html b/rowers/templates/menu_other.html index b565018e..71789d84 100644 --- a/rowers/templates/menu_other.html +++ b/rowers/templates/menu_other.html @@ -39,7 +39,6 @@
  • Strava
  • RunKeeper
  • SportTracks
  • -
  • MapMyFitness
  • Polar
  • diff --git a/rowers/templates/menu_workout.html b/rowers/templates/menu_workout.html index 96313d6d..2b77156f 100644 --- a/rowers/templates/menu_workout.html +++ b/rowers/templates/menu_workout.html @@ -207,21 +207,6 @@ {% endif %} -
  • - {% if workout.uploadedtounderarmour %} - - MapMyFitness - - {% elif user.rower.underarmourtoken == None or user.rower.underarmourtoken == '' %} - - Connect to MapMyFitness - - {% else %} - - MapMyFitness - - {% endif %} -
  • {% if workout.uploadedtotp %} diff --git a/rowers/templates/menu_workouts.html b/rowers/templates/menu_workouts.html index 12931af6..82045548 100644 --- a/rowers/templates/menu_workouts.html +++ b/rowers/templates/menu_workouts.html @@ -42,7 +42,6 @@
  • Strava
  • RunKeeper
  • SportTracks
  • -
  • MapMyFitness
  • Polar
  • RP3
  • diff --git a/rowers/templates/rower_exportsettings.html b/rowers/templates/rower_exportsettings.html index e631af88..d6aabe5d 100644 --- a/rowers/templates/rower_exportsettings.html +++ b/rowers/templates/rower_exportsettings.html @@ -17,9 +17,6 @@ {% if rower.sporttrackstoken is not None and rower.sporttrackstoken != '' %} SportTracks, {% endif %} - {% if rower.underarmourtoken is not None and rower.underarmourtoken != '' %} - Under Armour (MapMyFitness), - {% endif %} {% if rower.tptoken is not None and rower.tptoken != '' %} TrainingPeaks, {% endif %} @@ -66,7 +63,7 @@ automatically auto-sync workouts from Garmin to Rowsandall (but not in the other direction). If you want to export our structured workout sessions to your Garmin device, you have to set the "Garmin Activity" to a activity type that is supported by your watch. Not all watches support "Custom" activities, so - you may have to set your activity to Run or Ride while rowing. + you may have to set your activity to Run or Ride while rowing.

    Strava Auto Import also imports activity changes on Strava to Rowsandall, except when you delete @@ -80,7 +77,6 @@

    connect with NK Logbook

    connect with SportTracks

    connect with RunKeeper

    -

    connect with Under Armour

    connect with Polar

    Available on MapMyFitness (UnderArmour) -{% if workouts %} - - - - - - - - - - - - {% for workout in workouts %} - - - - - - - - - {% endfor %} - -
    Import Date/Time Duration Total Distance Type
    - Import{{ workout|ualookup:'starttime' }}{{ workout|ualookup:'duration' }} {{ workout|ualookup:'distance' }} m{{ workout|ualookup:'type' }}
    -{% else %} -

    No workouts found. We only list workouts with time data series.

    -{% endif %} -{% endblock %} - -{% block sidebar %} -{% include 'menu_workouts.html' %} -{% endblock %} diff --git a/rowers/tests/test_imports.py b/rowers/tests/test_imports.py index 7da2bcdf..d49285a0 100644 --- a/rowers/tests/test_imports.py +++ b/rowers/tests/test_imports.py @@ -1149,109 +1149,6 @@ class RunKeeperObjects(DjangoTestCase): -@pytest.mark.django_db -@override_settings(TESTING=True) -class UAObjects(DjangoTestCase): - def setUp(self): - self.c = Client() - self.u = User.objects.create_user('john', - 'sander@ds.ds', - 'koeinsloot') - - self.u.first_name = 'John' - self.u.last_name = 'Sander' - self.u.save() - self.r = Rower.objects.create(user=self.u,gdproptin=True,surveydone=True, - gdproptindate=timezone.now() - ) - - - self.r.underarmourtoken = '12' - self.r.underarmourrefreshtoken = '12' - self.r.underarmourtokenexpirydate = arrow.get(datetime.datetime.now()+datetime.timedelta(days=1)).datetime - self.r.save() - - self.c.login(username='john',password='koeinsloot') - - self.nu = datetime.datetime.now() - - filename = 'rowers/tests/testdata/testdata.csv' - - rr = rrower(hrmax=self.r.max,hrut2=self.r.ut2, - hrut1=self.r.ut1,hrat=self.r.at, - hrtr=self.r.tr,hran=self.r.an,ftp=self.r.ftp) - row = rdata(csvfile=filename,rower=rr) - totaldist = row.df['cum_dist'].max() - totaltime = row.df['TimeStamp (sec)'].max()-row.df['TimeStamp (sec)'].min() - totaltime = totaltime+row.df.loc[:,' ElapsedTime (sec)'].iloc[0] - - - hours = int(totaltime/3600.) - minutes = int((totaltime - 3600.*hours)/60.) - seconds = int(totaltime - 3600.*hours - 60.*minutes) - tenths = int(10*(totaltime - 3600.*hours - 60.*minutes - seconds)) - - duration = "%s:%s:%s.%s" % (hours,minutes,seconds,tenths) - - - workoutdate = row.rowdatetime.strftime('%Y-%m-%d') - workoutstarttime = row.rowdatetime.strftime('%H:%M:%S') - - self.w = Workout.objects.create( - name='testworkout',workouttype='water', - user=self.r,date=self.nu.strftime('%Y-%m-%d'), - starttime=workoutstarttime, - startdatetime=row.rowdatetime, - duration=duration,distance=totaldist, - csvfilename=filename - ) - - @patch('rowers.imports.requests.post', side_effect=mocked_requests) - def test_underarmour_callback(self, mock_post): - response = self.c.get('/underarmour_callback?code=dsdoij232s',follow=True) - - - self.assertEqual(response.status_code, 200) - - - @patch('rowers.underarmourstuff.requests.post', side_effect=mocked_requests) - def test_underarmour_token_refresh(self, mock_post): - response = self.c.get('/rowers/me/underarmourrefresh/',follow=True) - - self.assertEqual(response.status_code, 200) - - - @patch('rowers.underarmourstuff.requests.post', side_effect=mocked_requests) - @patch('rowers.underarmourstuff.requests.get', side_effect=mocked_requests) - def test_underarmour_upload(self, mock_get, mock_post): - response = self.c.get('/rowers/workout/'+encoded1+'/underarmouruploadw/') - - self.assertRedirects(response, - expected_url = '/rowers/workout/'+encoded1+'/edit/', - status_code=302,target_status_code=200) - - self.assertEqual(response.url, '/rowers/workout/'+encoded1+'/edit/') - self.assertEqual(response.status_code, 302) - - @patch('rowers.underarmourstuff.requests.get', side_effect=mocked_requests) - def test_underarmour_list(self, mock_get): - response = self.c.get('/rowers/workout/underarmourimport',follow=True) - - self.assertEqual(response.status_code,200) - - @patch('rowers.imports.requests.get', side_effect=mocked_requests) - @patch('rowers.dataprep.create_engine') - def test_underarmour_import(self, mock_get, mocked_sqlalchemy): - - response = self.c.get('/rowers/workout/underarmourimport/12/',follow=True) - - self.assertRedirects(response, - expected_url='/rowers/workout/'+encoded2+'/edit/', - status_code=302,target_status_code=200) - - self.assertEqual(response.status_code, 200) - - #@pytest.mark.django_db @override_settings(TESTING=True) class TPObjects(DjangoTestCase): diff --git a/rowers/traverselinktest.py b/rowers/traverselinktest.py index 3856fb44..0b07477f 100644 --- a/rowers/traverselinktest.py +++ b/rowers/traverselinktest.py @@ -99,7 +99,6 @@ class TraverseLinksTest(TestCase): '.*authorize.*', '.*youtu.*', '.*earth.*', - '.*underarmour.*', '.*runkeeper.*', '.*c2list.*', '.*stravaimport.*', diff --git a/rowers/underarmourstuff.py b/rowers/underarmourstuff.py deleted file mode 100644 index 33003a22..00000000 --- a/rowers/underarmourstuff.py +++ /dev/null @@ -1,544 +0,0 @@ -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals -from __future__ import unicode_literals, absolute_import -from rowers.imports import * - -import numpy - -import rowers.mytypes as mytypes -from rowers.mytypes import otwtypes -from rowers.rower_rules import is_workout_user - -from rowsandall_app.settings import ( - UNDERARMOUR_CLIENT_KEY, - UNDERARMOUR_CLIENT_SECRET, - UNDERARMOUR_REDIRECT_URI, - ) - -oauth_data = { - 'client_id': UNDERARMOUR_CLIENT_KEY, - 'client_secret': UNDERARMOUR_CLIENT_SECRET, - 'redirect_uri': UNDERARMOUR_REDIRECT_URI, - 'autorization_uri': "https://www.mapmyfitness.com/v7.1/oauth2/uacf/authorize/", - 'content_type': 'application/x-www-form-urlencoded', - 'tokenname': 'underarmourtoken', - 'refreshtokenname': 'underarmourrefreshtoken', - 'expirydatename': 'underarmourtokenexpirydate', - 'bearer_auth': True, - 'base_url': "https://api.ua.com/v7.1/oauth2/access_token/", - 'scope':'write', - } - -# Checks if user has UnderArmour token, renews them if they are expired -def underarmour_open(user): - return imports_open(user,oauth_data) - -# Refresh ST token using refresh token -def do_refresh_token(refreshtoken,access_token): - return imports_do_refresh_token( - refreshtoken,oauth_data,access_token=access_token - ) - -# Exchange access code for long-lived access token -def get_token(code): - return imports_get_token(code,oauth_data) - -# Make authorization URL including random string -def make_authorization_url(request): - return imports_make_authorization_url(oauth_data) # pragma: no cover - -# Get list of workouts available on Underarmour -def get_underarmour_workout_list(user): - r = Rower.objects.get(user=user) - if (r.underarmourtoken == '') or (r.underarmourtoken is None): - s = "Token doesn't exist. Need to authorize" - return custom_exception_handler(401,s) - else: - # ready to fetch. Hurray - authorizationstring = str('Bearer ' + r.underarmourtoken) - headers = {'Authorization': authorizationstring, - 'Api-Key': UNDERARMOUR_CLIENT_KEY, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - url = "https://api.ua.com/v7.1/workout/?user="+str(get_userid(r.underarmourtoken))+"&order_by=-start_datetime" - - s = requests.get(url,headers=headers) - - - return s - -# Get workout summary data by Underarmour ID -def get_workout(user,underarmourid,do_async=False): - r = Rower.objects.get(user=user) - if (r.underarmourtoken == '') or (r.underarmourtoken is None): # pragma: no cover - return custom_exception_handler(401,s) - s = "Token doesn't exist. Need to authorize" - else: - # ready to fetch. Hurray - authorizationstring = str('Bearer ' + r.underarmourtoken) - headers = {'Authorization': authorizationstring, - 'Api-Key': UNDERARMOUR_CLIENT_KEY, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - url = "https://api.ua.com/v7.1/workout/"+str(underarmourid)+"/?field_set=time_series" - s = requests.get(url,headers=headers) - - data = s.json() - - strokedata = pd.DataFrame.from_dict({ - key: pd.Series(value) for key, value in data.items() - }) - - return data,strokedata - - -# Create Workout Data for upload to Underarmour -def createunderarmourworkoutdata(w): - filename = w.csvfilename - try: - row = rowingdata(csvfile=filename) - except: # pragma: no cover - return 0 - - st = w.startdatetime.astimezone(pytz.timezone(w.timezone)) - start_time = st.isoformat() - - averagehr = int(row.df[' HRCur (bpm)'].mean()) - minhr = int(row.df[' HRCur (bpm)'].min()) - maxhr = int(row.df[' HRCur (bpm)'].max()) - averagespm = int(row.df[' Cadence (stokes/min)'].mean()/2.) - minspm = int(row.df[' Cadence (stokes/min)'].min()/2.) - maxspm = int(row.df[' Cadence (stokes/min)'].max()/2.) - maxhr = int(row.df[' HRCur (bpm)'].max()) - duration = w.duration.hour*3600 - duration += w.duration.minute*60 - duration += w.duration.second - duration += +1.0e-6*w.duration.microsecond - name = w.name - try: - notes = w.notes+'\n from '+w.workoutsource+' via rowsandall.com' - except TypeError: - notes = 'from '+w.workoutsource+' via rowsandall.com' - - # adding diff, trying to see if this is valid - #t = row.df.loc[:,'TimeStamp (sec)'].values-10*row.df.ix[0,'TimeStamp (sec)'] - t = row.df.loc[:,'TimeStamp (sec)'].values #-row.df.ix[0,'TimeStamp (sec)'] - - # t += arrow.get(st).timestamp() - - # t[0] = t[1] - - d = row.df.loc[:,'cum_dist'].values - d[0] = d[1] - t = t.astype(float).tolist() - - - - - d = d.astype(int).tolist() - spm = row.df[' Cadence (stokes/min)'].astype(int).tolist() - spm[0] = spm[1] - hr = row.df[' HRCur (bpm)'].astype(int).tolist() - speed = row.df[' AverageBoatSpeed (m/s)'] - speedmin = float(row.df[' AverageBoatSpeed (m/s)'].min()) - speedmax = float(row.df[' AverageBoatSpeed (m/s)'].max()) - speedmean = float(row.df[' AverageBoatSpeed (m/s)'].mean()) - speed = speed.replace(np.inf,0).tolist() - - - - haslatlon=1 - - try: # pragma: no cover - lat = row.df[' latitude'] - lon = row.df[' longitude'] - if not lat.std() and not lon.std(): - haslatlon = 0 - except KeyError: - haslatlon = 0 - - - # path data - if haslatlon: # pragma: no cover - locdata = [] - for e in zip(t,lat.values,lon.values): - point = { - 'lat':e[1], - 'lng':e[2], - 'elevation':0, - } - locdata.append([e[0],point]) - - hrdata = [] - for e in zip(t,hr): - point = [e[0], - e[1] - ] - hrdata.append(point) - - distancedata = [] - for e in zip(t,d): - point = [e[0], - e[1] - ] - distancedata.append(point) - - spmdata = [] - for e in zip(t,spm): - spmdata.append([e[0],e[1]]) - - - timeseries = { - "distance": distancedata, - "heartrate": hrdata, - "cadence": spmdata, - } - - - - aggregates = { - "elapsed_time_total": int(duration), - "active_time_total": int(duration), - "distance_total": int(max(d)), - "heartrate_avg": averagehr, - "heart_rate_min": minhr, - "heart_rate_max": maxhr, - "speed_min": speedmin, - "speed_max": speedmax, - "speed_avg": speedmean, - "cadence_min": minspm, - "cadence_max": maxspm, - "cadence_avg": averagespm, - } - - - if haslatlon: # pragma: no cover - timeseries["position"] = locdata - - data = { - "start_datetime": start_time, - "name": name, - "has_time_series": True, - "time_series": timeseries, - "aggregates": aggregates, - "start_locale_timezone": "Etc/UTC", - "activity_type": "/v7.1/activity_type/128/", - "notes": notes, - } - - return data - -# Obtain Underarmour Workout ID and activity type -def get_idfromuri(user,links): - id = links['self'][0]['id'] - typeid = links['activity_type'][0]['id'] - - typename = get_typefromid(typeid,user) - - return id,typename - -def getidfromresponse(response): - t = response.json() - - links = t["_links"] - - id = links["self"][0]["id"] - - return int(id) - -def refresh_ua_actlist(user): # pragma: no cover - r = Rower.objects.get(user=user) - authorizationstring = str('Bearer ' + r.underarmourtoken) - headers = {'Authorization': authorizationstring, - 'Api-Key': UNDERARMOUR_CLIENT_KEY, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - url = "https://api.ua.com/v7.1/activity_type/" - response = requests.get(url,headers=headers) - - me_json = response.json() - types = me_json["_embedded"]["activity_types"] - w = {int(t["_links"]["self"][0]["id"]):t["name"] for t in types} - wdf = pd.Series(w,name='Name') - wdf.to_csv('static/rigging/ua2.csv',index_label='id',header=True) - return w - -try: - activities = pd.read_csv('static/rigging/ua2.csv',index_col='id') - actdict = activities.to_dict()['Name'] -except: # pragma: no cover - actdict = {} - - -def get_typefromid(typeid,user): - r = Rower.objects.get(user=user) - try: - res = actdict[int(typeid)] - except KeyError: # pragma: no cover - authorizationstring = str('Bearer ' + r.underarmourtoken) - headers = {'Authorization': authorizationstring, - 'Api-Key': UNDERARMOUR_CLIENT_KEY, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - url = "https://api.ua.com/v7.1/activity_type/"+str(typeid) - response = requests.get(url,headers=headers) - - me_json = response.json() - - try: - res = me_json['name'] - except KeyError: - res = 0 - - return res - - - -# Get user id, having access token -# Handy for checking if the API access is working -def get_userid(access_token): - authorizationstring = str('Bearer ' + access_token) - headers = {'Authorization': authorizationstring, - 'Api-Key': UNDERARMOUR_CLIENT_KEY, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - - url = "https://api.ua.com/v7.1/user/self/" - response = requests.get(url,headers=headers) - - me_json = response.json() - - try: - res = me_json['id'] - except KeyError: # pragma: no cover - res = 0 - - return res - -def default(o): # pragma: no cover - if isinstance(o, numpy.int64): return int(o) - raise TypeError - - -def workout_ua_upload(user,w): # pragma: no cover - message = "Uploading to MapMyFitness" - uaid = 0 - - r = w.user - - thetoken = underarmour_open(r.user) - - # ready to upload. Hurray - - if (is_workout_user(user,w)): - data = createunderarmourworkoutdata(w) -# return HttpResponse(json.dumps(data)) - if not data: - message = "Data error" - uaid = 0 - return message, uaid - - authorizationstring = str('Bearer ' + thetoken) - headers = {'Authorization': authorizationstring, - 'Api-Key': UNDERARMOUR_CLIENT_KEY, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json', - } - - url = "https://api.ua.com/v7.1/workout/" - response = requests.post(url,headers=headers,data=json.dumps(data,default=default)) - - # check for duplicate error first - if (response.status_code == 409 ): - message = "Duplicate error" - w.uploadedtounderarmour = -1 - uaid = -1 - w.save() - elif (response.status_code == 201 or response.status_code==200): - uaid = getidfromresponse(response) - w.uploadedtounderarmour = uaid - w.save() - return 'Successfully synchronized with MapMyFitness',uaid - else: - s = response - message = "Something went wrong in workout_underarmour_upload_view: %s - %s" % (s.reason,s.text) - uaid = 0 - return message, uaid - - else: - message = "You are not authorized to upload this workout" - uaid = 0 - return message, uaid - - return message, uaid - -# Create workout from SportTracks Data, which are slightly different -# than Strava or Concept2 data -def add_workout_from_data(user,importid,data,strokedata, - source='mapmyfitness', - workoutsource='mapmyfitness'): - workouttype = 'water' - - try: - comments = data['notes'] - except: # pragma: no cover - comments = '' - - try: - thetimezone = tz(data['start_locale_timezone']) - except: - thetimezone = 'UTC' - - r = Rower.objects.get(user=user) - try: - rowdatetime = iso8601.parse_date(data['start_datetime']) - except iso8601.ParseError: # pragma: no cover - try: - rowdatetime = datetime.strptime(data['start_datetime'],"%Y-%m-%d %H:%M:%S") - rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) - except: - try: - rowdatetime = parser.parse(data['start_datetime']) - rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) - except: - rowdatetime = datetime.strptime(data['date'],"%Y-%m-%d %H:%M:%S") - rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) - starttimeunix = arrow.get(rowdatetime).timestamp() - - - try: - title = data['name'] - except: # pragma: no cover - title = "Imported data" - - timeseries = data['time_series'] - - # position, distance, speed, cadence, power, - - try: - res = splituadata(timeseries['distance']) - distance = res[1] - times_distance = res[0] - except KeyError: # pragma: no cover - message = "Error. No distance data" - return (0,message) - - - try: - l = timeseries['position'] - - res = splituadata(l) - times_location = res[0] - latlong = res[1] - latcoord = [] - loncoord = [] - - for coord in latlong: - lat = coord['lat'] - lon = coord['lng'] - latcoord.append(lat) - loncoord.append(lon) - except: # pragma: no cover - times_location = times_distance - latcoord = np.zeros(len(times_distance)) - loncoord = np.zeros(len(times_distance)) - if workouttype in otwtypes: - workouttype = 'rower' - - try: - res = splituadata(timeseries['cadence']) - times_spm = res[0] - spm = res[1] - except KeyError: # pragma: no cover - times_spm = times_distance - spm = 0*times_distance - - try: - res = splituadata(timeseries['heartrate']) - hr = res[1] - times_hr = res[0] - except KeyError: # pragma: no cover - times_hr = times_distance - hr = 0*times_distance - - - # create data series and remove duplicates - distseries = pd.Series(distance,index=times_distance) - distseries = distseries.groupby(distseries.index).first() - latseries = pd.Series(latcoord,index=times_location) - latseries = latseries.groupby(latseries.index).first() - lonseries = pd.Series(loncoord,index=times_location) - lonseries = lonseries.groupby(lonseries.index).first() - spmseries = pd.Series(spm,index=times_spm) - spmseries = spmseries.groupby(spmseries.index).first() - hrseries = pd.Series(hr,index=times_hr) - hrseries = hrseries.groupby(hrseries.index).first() - - - # Create dicts and big dataframe - d = { - ' Horizontal (meters)': distseries, - ' latitude': latseries, - ' longitude': lonseries, - ' Cadence (stokes/min)': spmseries, - ' HRCur (bpm)' : hrseries, - } - - - - df = pd.DataFrame(d) - - df = df.groupby(level=0).last() - - cum_time = df.index.values - df[' ElapsedTime (sec)'] = cum_time - - velo = df[' Horizontal (meters)'].diff()/df[' ElapsedTime (sec)'].diff() - - df[' Power (watts)'] = 0.0*velo - - nr_rows = len(velo.values) - - df[' DriveLength (meters)'] = np.zeros(nr_rows) - df[' StrokeDistance (meters)'] = np.zeros(nr_rows) - df[' DriveTime (ms)'] = np.zeros(nr_rows) - df[' StrokeRecoveryTime (ms)'] = np.zeros(nr_rows) - df[' AverageDriveForce (lbs)'] = np.zeros(nr_rows) - df[' PeakDriveForce (lbs)'] = np.zeros(nr_rows) - df[' lapIdx'] = np.zeros(nr_rows) - - - - unixtime = cum_time+starttimeunix - unixtime[0] = starttimeunix - - df['TimeStamp (sec)'] = unixtime - - - dt = np.diff(cum_time).mean() - wsize = round(5./dt) - - df = df.fillna(0) - - df.sort_values(by='TimeStamp (sec)',ascending=True) - - timestr = strftime("%Y%m%d-%H%M%S") - - csvfilename ='media/{code}_{importid}.csv'.format( - importid=importid, - code = uuid4().hex[:16] - ) - - res = df.to_csv(csvfilename+'.gz',index_label='index', - compression='gzip') - - id,message = dataprep.save_workout_database(csvfilename,r, - workouttype=workouttype, - workoutsource='mapmyfitness', - dosmooth=r.dosmooth, - title=title, - notes=comments) - - return (id,message) diff --git a/rowers/uploads.py b/rowers/uploads.py index dd2d7cb1..43706369 100644 --- a/rowers/uploads.py +++ b/rowers/uploads.py @@ -125,7 +125,6 @@ def matchsync(line): tester4 = tester+'(.*)(strava)' tester5 = tester+'(.*)((st)|(sporttracks))' tester6 = tester+'(.*)((rk)|(runkeeper))' - tester7 = tester+'(.*)((mapmyfitness)|(underarmour)|(ua))' tester = re.compile(tester) @@ -262,8 +261,6 @@ def getsyncoptions(uploadoptions,values): # pragma: no cover uploadoptions['upload_to_SportTracks'] = True if v in ['rk','runkeeper']: uploadoptions['upload_to_RunKeeper'] = True - if v in ['ua','underarmour','mapmyfitness']: - uploadoptions['upload_to_MapMyFitness'] = True except AttributeError: pass @@ -491,7 +488,7 @@ import rowers.c2stuff as c2stuff import rowers.stravastuff as stravastuff import rowers.sporttracksstuff as sporttracksstuff import rowers.runkeeperstuff as runkeeperstuff -import rowers.underarmourstuff as underarmourstuff + import rowers.tpstuff as tpstuff from rowers.rower_rules import is_promember @@ -653,14 +650,6 @@ def do_sync(w,options, quick=False): message = "Please connect to Runkeeper first" id = 0 - if ('upload_to_MapMyFitness' in options and options['upload_to_MapMyFitness']) or (w.user.mapmyfitness_auto_export): # pragma: no cover - try: - message,id = underarmourstuff.workout_ua_upload( - w.user.user,w - ) - except NoTokenError: - message = "Please connect to MapMyFitness first" - id = 0 if ('upload_to_TrainingPeaks' in options and options['upload_to_TrainingPeaks']) or (w.user.trainingpeaks_auto_export): # pragma: no cover diff --git a/rowers/urls.py b/rowers/urls.py index 7f002f21..8e91944d 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -510,14 +510,11 @@ urlpatterns = [ re_path(r'^workout/polarimport/user/(?P\d+)/',views.workout_polarimport_view,name='workout_polarimport_view'), re_path(r'^workout/runkeeperimport/$',views.workout_runkeeperimport_view,name='workout_runkeeperimport_view'), re_path(r'^workout/runkeeperimport/user/(?P\d+)/$',views.workout_runkeeperimport_view,name='workout_runkeeperimport_view'), - re_path(r'^workout/underarmourimport/user/(?P\d+)/$',views.workout_underarmourimport_view,name='workout_underarmourimport_view'), - re_path(r'^workout/underarmourimport/$',views.workout_underarmourimport_view,name='workout_underarmourimport_view'), re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/c2uploadw/$',views.workout_c2_upload_view,name='workout_c2_upload_view'), re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/stravauploadw/$',views.workout_strava_upload_view,name='workout_strava_upload_view'), re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/recalcsummary/$',views.workout_recalcsummary_view,name='workout_recalcsummary_view'), re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/sporttracksuploadw/$',views.workout_sporttracks_upload_view,name='workout_sporttracks_upload_view'), re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/runkeeperuploadw/$',views.workout_runkeeper_upload_view,name='workout_runkeeper_upload_view'), - re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/underarmouruploadw/$',views.workout_underarmour_upload_view,name='workout_underarmour_upload_view'), re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/tpuploadw/$',views.workout_tp_upload_view,name='workout_tp_upload_view'), re_path(r'^multi-compare/workout/(?P\b[0-9A-Fa-f]+\b)/user/(?P\d+)/$',views.multi_compare_view, name='multi_compare_view'), @@ -600,12 +597,10 @@ urlpatterns = [ re_path(r'^me/stravaauthorize/$',views.rower_strava_authorize,name='rower_strava_authorize'), re_path(r'^me/garminauthorize/$',views.rower_garmin_authorize,name='rower_garmin_authorize'), re_path(r'^me/sporttracksauthorize/$',views.rower_sporttracks_authorize,name='rower_sporttracks_authorize'), - re_path(r'^me/underarmourauthorize/$',views.rower_underarmour_authorize,name='rower_underarmour_authorize'), re_path(r'^me/tpauthorize/$',views.rower_tp_authorize,name='rower_tp_authorize'), re_path(r'^me/rp3authorize/$',views.rower_rp3_authorize,name='rower_rp3_authorize'), re_path(r'^me/runkeeperauthorize/$',views.rower_runkeeper_authorize,name='rower_runkeeper_authorize'), re_path(r'^me/sporttracksrefresh/$',views.rower_sporttracks_token_refresh,name='rower_sporttracks_token_refresh'), - re_path(r'^me/underarmourrefresh/$',views.rower_underarmour_token_refresh,name='rower_underarmoud_token_refresh'), re_path(r'^me/tprefresh/$',views.rower_tp_token_refresh,name='rower_tp_token_refresh'), re_path(r'^me/c2refresh/$',views.rower_c2_token_refresh,name='rower_c2_token_refresh'), re_path(r'^me/favoritecharts/$',views.rower_favoritecharts_view,name='rower_favoritecharts_view'), diff --git a/rowers/utils.py b/rowers/utils.py index 0c1a35d4..2722def7 100644 --- a/rowers/utils.py +++ b/rowers/utils.py @@ -105,6 +105,15 @@ info_calls = [ import random +def dologging(filename,s): + tstamp = time.localtime() + timestamp = time.strftime('%b-%d-%Y %H:%M:%S', tstamp) + with open('filename','a') as f: + f.write('\n') + f.write(timestamp) + f.write(' ') + f.write(s) + def to_pace(pace): minutes, seconds = divmod(pace,60) seconds, rest = divmod(seconds, 1) diff --git a/rowers/views/importviews.py b/rowers/views/importviews.py index eee66152..c1740e50 100644 --- a/rowers/views/importviews.py +++ b/rowers/views/importviews.py @@ -286,66 +286,6 @@ def workout_runkeeper_upload_view(request,id=0): return HttpResponseRedirect(url) # pragma: no cover -# Upload workout to Underarmour -@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True) -def workout_underarmour_upload_view(request,id=0): - message = "" - w = get_workout(id) - r = w.user - - try: - thetoken = underarmour_open(r.user) - except NoTokenError: # pragma: no cover - return HttpResponseRedirect("/rowers/me/underarmourauthorize/") - - # ready to upload. Hurray - - - data = underarmourstuff.createunderarmourworkoutdata(w) - if not data: # pragma: no cover - message = "Data error" - messages.error(request,message) - url = reverse(r.defaultlandingpage, - kwargs = { - 'id':encoder.encode_hex(w.id), - }) - return HttpResponseRedirect(url) - - authorizationstring = str('Bearer ' + thetoken) - headers = {'Authorization': authorizationstring, - 'Api-Key': UNDERARMOUR_CLIENT_KEY, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json', - } - - url = "https://api.ua.com/v7.1/workout/" - response = requests.post(url,headers=headers,data=json.dumps(data,default=default)) - - - # check for duplicate error first - if (response.status_code == 409 ): # pragma: no cover # pragma: no cover - message = "Duplicate error" - messages.error(request,message) - w.uploadedtounderarmour = -1 - w.save() - elif (response.status_code == 201 or response.status_code==200): - underarmourid = underarmourstuff.getidfromresponse(response) - w.uploadedtounderarmour = underarmourid - w.save() - url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)}) - - return HttpResponseRedirect(url) - else: # pragma: no cover - s = response - message = "Something went wrong in workout_underarmour_upload_view: %s " % s.reason - messages.error(request,message) - - url = reverse(r.defaultlandingpage, - kwargs = { - 'id':encoder.encode_hex(w.id), - }) # pragma: no cover - - return HttpResponseRedirect(url) # pragma: no cover # Upload workout to SportTracks @permission_required('workout.change_workout',fn=get_workout_by_opaqueid) @@ -525,24 +465,8 @@ def rower_sporttracks_authorize(request): # pragma: no cover return HttpResponseRedirect(url) -# Underarmour Authorization -@login_required() -def rower_underarmour_authorize(request): # pragma: no cover - # Generate a random string for the state parameter - # Save it for use later to prevent xsrf attacks - state = str(uuid4()) - - redirect_uri = UNDERARMOUR_REDIRECT_URI - - url = 'https://www.mapmyfitness.com/v7.1/oauth2/authorize/?' \ - 'client_id={0}&response_type=code&redirect_uri={1}'.format( - UNDERARMOUR_CLIENT_KEY, redirect_uri - ) - - return HttpResponseRedirect(url) - -# Underarmour Authorization +# RP3 Authorization @login_required() def rower_rp3_authorize(request): # pragma: no cover # Generate a random string for the state parameter @@ -557,7 +481,7 @@ def rower_rp3_authorize(request): # pragma: no cover return HttpResponseRedirect(url) -# Underarmour Authorization +# TrainingPeaks Authorization @login_required() def rower_tp_authorize(request): # pragma: no cover # Generate a random string for the state parameter @@ -603,33 +527,6 @@ def rower_c2_token_refresh(request): return HttpResponseRedirect(url) -# Underarmour token refresh. URL for manual refresh. Not visible to users -@login_required() -def rower_underarmour_token_refresh(request): - r = getrower(request.user) - res = underarmourstuff.do_refresh_token( - r.underarmourrefreshtoken, - r.underarmourtoken - ) - access_token = res[0] - expires_in = res[1] - refresh_token = res[2] - expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in) - - r = getrower(request.user) - r.underarmourtoken = access_token - r.underarmourtokenexpirydate = expirydatetime - r.underarmourrefreshtoken = refresh_token - - r.save() - - successmessage = "Tokens refreshed. Good to go" - messages.info(request,successmessage) - - url = reverse('workouts_view') - - return HttpResponseRedirect(url) - # TrainingPeaks token refresh. URL for manual refresh. Not visible to users @@ -1086,29 +983,6 @@ def rower_process_sporttrackscallback(request): -# Process Underarmour callback -@login_required() -def rower_process_underarmourcallback(request): - code = request.GET['code'] - res = underarmourstuff.get_token(code) - - - access_token = res[0] - expires_in = res[1] - refresh_token = res[2] - expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in) - - r = getrower(request.user) - r.underarmourtoken = access_token - r.underarmourtokenexpirydate = expirydatetime - r.underarmourrefreshtoken = refresh_token - - r.save() - - successmessage = "Tokens stored. Good to go. Please check your import/export settings" - messages.info(request,successmessage) - url = reverse('rower_exportsettings_view') - return HttpResponseRedirect(url) # Process RP3 callback @login_required() @@ -1680,56 +1554,6 @@ def workout_runkeeperimport_view(request,message="",userid=0): return HttpResponse(res) # pragma: no cover -# The page where you select which RunKeeper workout to import -@login_required() -@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True) -def workout_underarmourimport_view(request,message="",userid=0): - res = underarmourstuff.get_underarmour_workout_list(request.user) - if (res.status_code != 200): - return HttpResponseRedirect("/rowers/me/underarmourauthorize/") - - workouts = [] - items = res.json()['_embedded']['workouts'] - for item in items: - s = item['start_datetime'] - i,r = underarmourstuff.get_idfromuri(request.user,item['_links']) - n = item['name'] - try: - d = item['aggregates']['distance_total'] - except KeyError: # pragma: no cover - d = 0 - try: - ttot = item['aggregates']['active_time_total'] - except KeyError: - ttot = 0 - - keys = ['id','distance','duration','starttime','type'] - values = [i,d,ttot,s,r] - thedict = dict(zip(keys,values)) - - workouts.append(thedict) - - rower = getrower(request.user) - breadcrumbs = [ - { - 'url':'/rowers/list-workouts/', - 'name':'Workouts' - }, - { - 'url':reverse('workout_c2import_view'), - 'name':'Concept2' - }, - ] - - return render(request,'underarmour_list_import.html', - {'workouts':workouts, - 'breadcrumbs':breadcrumbs, - 'rower':rower, - 'active':'nav-workouts', - 'teams':get_my_teams(request.user), - }) - - return HttpResponse(res) # pragma: no cover # the page where you select which Polar workout to Import @login_required() @@ -2032,7 +1856,6 @@ importlistviews = { 'runkeeper':'workout_runkeeperimport_view', 'sporttracks':'workout_sporttracksimport_view', 'trainingpeaks':'workout_view', - 'underarmour':'workout_underarmourimport_view', 'nk':'workout_nkimport_view', } @@ -2044,7 +1867,6 @@ importsources = { 'runkeeper':runkeeperstuff, 'sporttracks':sporttracksstuff, 'trainingpeaks':tpstuff, - 'underarmour':underarmourstuff, 'nk':nkstuff, } @@ -2071,178 +1893,20 @@ def workout_getrp3importview(request,externalid): return HttpResponseRedirect(url) @login_required() -def workout_getimportview(request,externalid,source = 'c2',do_async=False): - data,strokedata = importsources[source].get_workout(request.user,externalid, +def workout_getimportview(request,externalid,source = 'c2',do_async=True): + result = importsources[source].get_workout(request.user,externalid, do_async=do_async) - if do_async: # pragma: no cover + if result: # pragma: no cover messages.info(request,"Your workout will be imported in the background") # this should return to the respective import list page - url = reverse(importlistviews[source]) - return HttpResponseRedirect(url) - - if not data: # pragma: no cover - messages.error(request,"No strokedata received") - url = reverse('workouts_view') - - return HttpResponseRedirect(url) - - - try: - workouttype = mytypes.c2mappinginv[data['type']] - except KeyError: - workouttype = 'rower' - - - # Now works only for C2 - try: - if strokedata == 0: - messages.error(request,'An error occurred importing the workout from Concept2') - url = reverse('workouts_view') - return HttpResponseRedirect(url) - except ValueError: - pass - - - if strokedata.empty: # pragma: no cover - distance = data['distance'] - c2id = data['id'] - workouttype = mytypes.c2mappinginv[data['type']] - verified = data['verified'] - startdatetime = iso8601.parse_date(data['date']) - weightclass = data['weight_class'] - weightcategory = 'hwt' - if weightclass == "L": - weightcategory = 'lwt' - totaltime = data['time']/10. - duration = dataprep.totaltime_sec_to_string(totaltime) - duration = datetime.datetime.strptime(duration,'%H:%M:%S.%f').time() - - try: - timezone_str = data['timezone'] - except: - timezone_str = 'UTC' - - if timezone_str is None: - timezone_str = 'UTC' - - - - - workoutdate = startdatetime.astimezone( - pytz.timezone(timezone_str) - ).strftime('%Y-%m-%d') - starttime = startdatetime.astimezone( - pytz.timezone(timezone_str) - ).strftime('%H:%M:%S') - - try: - notes = data['comments'] - name = notes[:40] - except (KeyError,TypeError): - comments = 'C2 Import Workout from {startdatetime}'.format(startdatetime=startdatetime) - name = notes - - r = getrower(request.user) - - id, message = dataprep.create_row_df(r, - distance, - duration, - startdatetime, - workouttype=workouttype) - - w = Workout.objects.get(id=id) - w.uploadedtoc2 = c2id - w.name = name - w.notes = notes - w.workouttype = workouttype - w.save() - - message = "This workout does not have any stroke data associated with it. We created synthetic stroke data." - messages.info(request,message) - url = reverse(r.defaultlandingpage, - kwargs = { - 'id':encoder.encode_hex(w.id), - }) - - return HttpResponseRedirect(url) - - - # strokedata not empty - continue - id,message = importsources[source].add_workout_from_data( - request.user, - externalid,data, - strokedata, - source=source, - workoutsource=source) - - w = get_workout(encoder.encode_hex(id)) - - if 'workout' in data: # pragma: no cover - if 'splits' in data['workout']: - splitdata = data['workout']['splits'] - elif 'intervals' in data['workout']: - splitdata = data['workout']['intervals'] - else: - splitdata = False else: - splitdata = False - - # splitdata (only for C2) - if splitdata: # pragma: no cover - w.summary,sa,results = c2stuff.summaryfromsplitdata(splitdata,data,w.csvfilename,workouttype=workouttype) - w.save() - - from rowingdata.trainingparser import getlist - # set stroke data in CSV file - if sa: - values = getlist(sa) - units = getlist(sa,sel='unit') - types = getlist(sa,sel='type') - - rowdata = rdata(csvfile=w.csvfilename) - if rowdata: - rowdata.updateintervaldata(values, - units,types,results) - - rowdata.write_csv(w.csvfilename,gzip=True) - dataprep.update_strokedata(w.id,rowdata.df) - - - - if source == 'strava': - w.uploadedtostrava = externalid - elif source == 'c2': - w.uploadedtoc2 = externalid - elif source == 'polar': # pragma: no cover - w.uploadedtopolar = externalid - elif source == 'runkeeper': - w.uploadedtorunkeeper = externalid - elif source == 'sporttracks': - w.uploadedtosporttracks = externalid - elif source == 'trainingpeaks': # pragma: no cover - w.uploadedtotp = externalid - elif source == 'underarmour': - w.uploadedtounderarmour = externalid - - w.save() - - if message: # pragma: no cover - messages.error(request,message) - - r = getrower(request.user) - - url = reverse(r.defaultlandingpage, - kwargs = { - 'id':encoder.encode_hex(w.id) - }) + messages.error(request,'Error getting the workout') + url = reverse(importlistviews[source]) return HttpResponseRedirect(url) - - - # Imports all new workouts from SportTracks @login_required() def workout_getsporttracksworkout_all(request): diff --git a/rowers/views/statements.py b/rowers/views/statements.py index b74f1616..4b8c9ff1 100644 --- a/rowers/views/statements.py +++ b/rowers/views/statements.py @@ -167,8 +167,8 @@ import rowers.garmin_stuff as garmin_stuff from rowers.stravastuff import strava_open import rowers.polarstuff as polarstuff import rowers.sporttracksstuff as sporttracksstuff -import rowers.underarmourstuff as underarmourstuff -from rowers.underarmourstuff import underarmour_open + + import rowers.tpstuff as tpstuff import rowers.runkeeperstuff as runkeeperstuff import rowers.rp3stuff as rp3stuff @@ -180,8 +180,6 @@ from rowsandall_app.settings import ( POLAR_CLIENT_ID, POLAR_REDIRECT_URI, POLAR_CLIENT_SECRET, SPORTTRACKS_CLIENT_ID, SPORTTRACKS_REDIRECT_URI, SPORTTRACKS_CLIENT_SECRET, - UNDERARMOUR_CLIENT_ID, UNDERARMOUR_REDIRECT_URI, - UNDERARMOUR_CLIENT_SECRET,UNDERARMOUR_CLIENT_KEY, RUNKEEPER_CLIENT_ID,RUNKEEPER_REDIRECT_URI,RUNKEEPER_CLIENT_SECRET, TP_CLIENT_ID,TP_REDIRECT_URI,TP_CLIENT_KEY,TP_CLIENT_SECRET, RP3_CLIENT_ID,RP3_REDIRECT_URI,RP3_CLIENT_KEY,RP3_CLIENT_SECRET, diff --git a/rowers/views/userviews.py b/rowers/views/userviews.py index 2d7104c1..ac73312c 100644 --- a/rowers/views/userviews.py +++ b/rowers/views/userviews.py @@ -329,7 +329,6 @@ def rower_exportsettings_view(request,userid=0): 'polar_auto_import':'polartoken', 'c2_auto_export':'c2token', 'c2_auto_import':'c2token', - 'mapmyfitness_auto_export':'underarmourtoken', 'runkeeper_auto_export':'runkeepertoken', 'sporttracks_auto_export':'sporttrackstoken', 'strava_auto_export':'stravatoken', diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py index ec44ea1a..8f23454d 100644 --- a/rowers/views/workoutviews.py +++ b/rowers/views/workoutviews.py @@ -5270,21 +5270,6 @@ def workout_upload_view(request, messages.error(request,message) - if (upload_to_ua): # pragma: no cover - try: - message,id = underarmourstuff.workout_ua_upload( - request.user,w - ) - except NoTokenError: - message = "Please connect to MapMyFitness first" - id = 0 - - if id>1: - messages.info(request,message) - else: - messages.error(request,message) - - if (upload_to_tp): # pragma: no cover try: message,id = tpstuff.workout_tp_upload( diff --git a/rowsandall_app/urls.py b/rowsandall_app/urls.py index a7d76249..6cf79af8 100644 --- a/rowsandall_app/urls.py +++ b/rowsandall_app/urls.py @@ -74,7 +74,6 @@ urlpatterns += [ re_path(r'^stravacall\_back',rowersviews.rower_process_stravacallback), re_path(r'^garmin\_callback',rowersviews.rower_process_garmincallback), re_path(r'^sporttracks\_callback',rowersviews.rower_process_sporttrackscallback), - re_path(r'^underarmour\_callback',rowersviews.rower_process_underarmourcallback), re_path(r'^polarflowcallback',rowersviews.rower_process_polarcallback), re_path(r'^runkeeper\_callback',rowersviews.rower_process_runkeepercallback), re_path(r'^tp\_callback',rowersviews.rower_process_tpcallback), From b53b56f909bcc8566a71353c8d109afd061009fd Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Fri, 21 May 2021 11:30:57 +0200 Subject: [PATCH 02/12] runkeeper retired, updated sporttraclks --- filename | 29 ++ rowers/admin.py | 2 - rowers/c2stuff.py | 9 +- rowers/models.py | 11 - rowers/runkeeperstuff.py | 530 --------------------- rowers/sporttracksstuff.py | 9 +- rowers/tasks.py | 1 - rowers/templates/menu_workout.html | 15 - rowers/templates/menu_workouts.html | 1 - rowers/templates/rower_exportsettings.html | 4 - rowers/templatetags/rowerfilters.py | 13 +- rowers/tests/statements.py | 1 - rowers/tests/test_imports.py | 116 +---- rowers/traverselinktest.py | 1 - rowers/uploads.py | 15 - rowers/urls.py | 4 - rowers/utils.py | 2 +- rowers/views/importviews.py | 186 +------- rowers/views/statements.py | 3 - rowers/views/workoutviews.py | 27 -- rowsandall_app/urls.py | 1 - 21 files changed, 74 insertions(+), 906 deletions(-) create mode 100644 filename delete mode 100644 rowers/runkeeperstuff.py diff --git a/filename b/filename new file mode 100644 index 00000000..c4492c6b --- /dev/null +++ b/filename @@ -0,0 +1,29 @@ + +May-21-2021 08:41:39 Upload to C2 user 1 +May-21-2021 08:41:39 {"type": "water", "date": "2016-05-20 13:50:26", "stroke_count": 189, "timezone": "Europe/Amsterdam", "distance": 2000, "time": 5400, "weight_class": "H", "comments": null, "stroke_rate": 21, "drag_factor": 104, "heart_rate": {"average": 148, "max": 156}, "stroke_data": [{"t": 32, "d": 131, "p": 2628, "spm": 19, "hr": 127}, {"t": 32, "d": 131, "p": 2394, "spm": 19, "hr": 127}, {"t": 61, "d": 210, "p": 1991, "spm": 20, "hr": 128}, {"t": 92, "d": 303, "p": 1764, "spm": 20, "hr": 129}, {"t": 121, "d": 390, "p": 1685, "spm": 20, "hr": 130}, {"t": 151, "d": 482, "p": 1639, "spm": 21, "hr": 131}, {"t": 181, "d": 576, "p": 1620, "spm": 20, "hr": 131}, {"t": 209, "d": 664, "p": 1597, "spm": 20, "hr": 132}, {"t": 238, "d": 755, "p": 1601, "spm": 21, "hr": 132}, {"t": 269, "d": 851, "p": 1589, "spm": 20, "hr": 132}, {"t": 296, "d": 950, "p": 1524, "spm": 21, "hr": 132}, {"t": 323, "d": 1050, "p": 1408, "spm": 22, "hr": 133}, {"t": 351, "d": 1153, "p": 1379, "spm": 21, "hr": 134}, {"t": 380, "d": 1258, "p": 1365, "spm": 21, "hr": 135}, {"t": 408, "d": 1366, "p": 1342, "spm": 21, "hr": 136}, {"t": 436, "d": 1472, "p": 1331, "spm": 22, "hr": 137}, {"t": 464, "d": 1576, "p": 1324, "spm": 22, "hr": 139}, {"t": 491, "d": 1678, "p": 1344, "spm": 21, "hr": 140}, {"t": 519, "d": 1785, "p": 1332, "spm": 22, "hr": 140}, {"t": 546, "d": 1885, "p": 1317, "spm": 21, "hr": 141}, {"t": 575, "d": 1993, "p": 1338, "spm": 21, "hr": 141}, {"t": 602, "d": 2094, "p": 1328, "spm": 22, "hr": 142}, {"t": 628, "d": 2194, "p": 1328, "spm": 22, "hr": 142}, {"t": 657, "d": 2302, "p": 1337, "spm": 22, "hr": 143}, {"t": 683, "d": 2402, "p": 1340, "spm": 22, "hr": 144}, {"t": 710, "d": 2501, "p": 1331, "spm": 23, "hr": 145}, {"t": 734, "d": 2596, "p": 1326, "spm": 23, "hr": 145}, {"t": 763, "d": 2703, "p": 1324, "spm": 23, "hr": 145}, {"t": 790, "d": 2806, "p": 1332, "spm": 22, "hr": 145}, {"t": 817, "d": 2907, "p": 1331, "spm": 22, "hr": 144}, {"t": 844, "d": 3008, "p": 1333, "spm": 23, "hr": 145}, {"t": 871, "d": 3111, "p": 1325, "spm": 22, "hr": 145}, {"t": 897, "d": 3212, "p": 1312, "spm": 22, "hr": 145}, {"t": 926, "d": 3319, "p": 1330, "spm": 21, "hr": 145}, {"t": 953, "d": 3420, "p": 1328, "spm": 22, "hr": 146}, {"t": 980, "d": 3524, "p": 1328, "spm": 22, "hr": 146}, {"t": 1008, "d": 3630, "p": 1321, "spm": 22, "hr": 146}, {"t": 1036, "d": 3734, "p": 1324, "spm": 22, "hr": 147}, {"t": 1063, "d": 3839, "p": 1322, "spm": 22, "hr": 147}, {"t": 1092, "d": 3946, "p": 1326, "spm": 22, "hr": 147}, {"t": 1119, "d": 4050, "p": 1335, "spm": 21, "hr": 147}, {"t": 1146, "d": 4153, "p": 1325, "spm": 22, "hr": 148}, {"t": 1176, "d": 4260, "p": 1329, "spm": 22, "hr": 148}, {"t": 1203, "d": 4365, "p": 1333, "spm": 21, "hr": 148}, {"t": 1231, "d": 4469, "p": 1335, "spm": 22, "hr": 148}, {"t": 1256, "d": 4569, "p": 1312, "spm": 22, "hr": 149}, {"t": 1284, "d": 4676, "p": 1316, "spm": 22, "hr": 149}, {"t": 1313, "d": 4785, "p": 1315, "spm": 22, "hr": 150}, {"t": 1341, "d": 4890, "p": 1318, "spm": 21, "hr": 150}, {"t": 1367, "d": 4991, "p": 1336, "spm": 21, "hr": 150}, {"t": 1397, "d": 5100, "p": 1329, "spm": 22, "hr": 150}, {"t": 1423, "d": 5199, "p": 1323, "spm": 22, "hr": 149}, {"t": 1451, "d": 5306, "p": 1327, "spm": 22, "hr": 149}, {"t": 1478, "d": 5408, "p": 1337, "spm": 22, "hr": 149}, {"t": 1505, "d": 5508, "p": 1334, "spm": 22, "hr": 148}, {"t": 1532, "d": 5608, "p": 1348, "spm": 22, "hr": 148}, {"t": 1559, "d": 5710, "p": 1333, "spm": 22, "hr": 147}, {"t": 1584, "d": 5807, "p": 1330, "spm": 22, "hr": 147}, {"t": 1612, "d": 5912, "p": 1329, "spm": 22, "hr": 147}, {"t": 1639, "d": 6014, "p": 1330, "spm": 22, "hr": 147}, {"t": 1666, "d": 6114, "p": 1321, "spm": 23, "hr": 147}, {"t": 1693, "d": 6218, "p": 1328, "spm": 23, "hr": 147}, {"t": 1720, "d": 6321, "p": 1317, "spm": 22, "hr": 147}, {"t": 1747, "d": 6423, "p": 1319, "spm": 22, "hr": 147}, {"t": 1772, "d": 6520, "p": 1310, "spm": 23, "hr": 148}, {"t": 1801, "d": 6627, "p": 1297, "spm": 23, "hr": 148}, {"t": 1826, "d": 6731, "p": 1296, "spm": 23, "hr": 148}, {"t": 1854, "d": 6836, "p": 1295, "spm": 22, "hr": 149}, {"t": 1880, "d": 6938, "p": 1297, "spm": 22, "hr": 149}, {"t": 1905, "d": 7038, "p": 1292, "spm": 22, "hr": 149}, {"t": 1934, "d": 7147, "p": 1297, "spm": 23, "hr": 150}, {"t": 1960, "d": 7249, "p": 1296, "spm": 22, "hr": 150}, {"t": 1987, "d": 7352, "p": 1306, "spm": 23, "hr": 151}, {"t": 2014, "d": 7454, "p": 1307, "spm": 22, "hr": 151}, {"t": 2041, "d": 7560, "p": 1291, "spm": 23, "hr": 151}, {"t": 2067, "d": 7663, "p": 1294, "spm": 22, "hr": 150}, {"t": 2094, "d": 7765, "p": 1300, "spm": 22, "hr": 150}, {"t": 2120, "d": 7869, "p": 1295, "spm": 23, "hr": 150}, {"t": 2147, "d": 7972, "p": 1290, "spm": 22, "hr": 150}, {"t": 2174, "d": 8078, "p": 1288, "spm": 23, "hr": 150}, {"t": 2201, "d": 8182, "p": 1286, "spm": 23, "hr": 150}, {"t": 2226, "d": 8284, "p": 1282, "spm": 22, "hr": 150}, {"t": 2254, "d": 8392, "p": 1279, "spm": 23, "hr": 150}, {"t": 2281, "d": 8496, "p": 1288, "spm": 23, "hr": 151}, {"t": 2307, "d": 8601, "p": 1272, "spm": 22, "hr": 151}, {"t": 2333, "d": 8703, "p": 1272, "spm": 22, "hr": 152}, {"t": 2361, "d": 8811, "p": 1280, "spm": 22, "hr": 152}, {"t": 2388, "d": 8917, "p": 1284, "spm": 23, "hr": 152}, {"t": 2415, "d": 9021, "p": 1293, "spm": 22, "hr": 152}, {"t": 2444, "d": 9131, "p": 1299, "spm": 22, "hr": 152}, {"t": 2472, "d": 9239, "p": 1309, "spm": 22, "hr": 153}, {"t": 2500, "d": 9346, "p": 1307, "spm": 21, "hr": 154}, {"t": 2528, "d": 9454, "p": 1320, "spm": 21, "hr": 154}, {"t": 2556, "d": 9560, "p": 1318, "spm": 21, "hr": 155}, {"t": 2585, "d": 9667, "p": 1326, "spm": 21, "hr": 155}, {"t": 2613, "d": 9774, "p": 1330, "spm": 21, "hr": 156}, {"t": 2641, "d": 9881, "p": 1310, "spm": 21, "hr": 156}, {"t": 2669, "d": 9988, "p": 1316, "spm": 21, "hr": 156}, {"t": 2698, "d": 10096, "p": 1327, "spm": 21, "hr": 156}, {"t": 2727, "d": 10206, "p": 1338, "spm": 21, "hr": 156}, {"t": 2757, "d": 10315, "p": 1345, "spm": 20, "hr": 156}, {"t": 2786, "d": 10425, "p": 1347, "spm": 21, "hr": 156}, {"t": 2815, "d": 10533, "p": 1347, "spm": 20, "hr": 155}, {"t": 2844, "d": 10641, "p": 1339, "spm": 21, "hr": 155}, {"t": 2874, "d": 10753, "p": 1354, "spm": 20, "hr": 155}, {"t": 2904, "d": 10861, "p": 1375, "spm": 20, "hr": 155}, {"t": 2935, "d": 10975, "p": 1359, "spm": 21, "hr": 155}, {"t": 2964, "d": 11085, "p": 1344, "spm": 20, "hr": 155}, {"t": 2993, "d": 11192, "p": 1353, "spm": 20, "hr": 155}, {"t": 3024, "d": 11306, "p": 1353, "spm": 20, "hr": 155}, {"t": 3054, "d": 11413, "p": 1353, "spm": 20, "hr": 155}, {"t": 3083, "d": 11524, "p": 1354, "spm": 21, "hr": 155}, {"t": 3113, "d": 11633, "p": 1367, "spm": 20, "hr": 155}, {"t": 3140, "d": 11738, "p": 1360, "spm": 20, "hr": 154}, {"t": 3170, "d": 11848, "p": 1342, "spm": 21, "hr": 154}, {"t": 3200, "d": 11958, "p": 1343, "spm": 21, "hr": 153}, {"t": 3229, "d": 12066, "p": 1357, "spm": 21, "hr": 152}, {"t": 3259, "d": 12173, "p": 1358, "spm": 21, "hr": 153}, {"t": 3287, "d": 12278, "p": 1363, "spm": 21, "hr": 152}, {"t": 3315, "d": 12387, "p": 1354, "spm": 21, "hr": 152}, {"t": 3345, "d": 12495, "p": 1334, "spm": 21, "hr": 151}, {"t": 3374, "d": 12601, "p": 1359, "spm": 20, "hr": 151}, {"t": 3403, "d": 12709, "p": 1357, "spm": 21, "hr": 151}, {"t": 3432, "d": 12818, "p": 1346, "spm": 21, "hr": 150}, {"t": 3461, "d": 12927, "p": 1355, "spm": 20, "hr": 151}, {"t": 3490, "d": 13034, "p": 1358, "spm": 20, "hr": 151}, {"t": 3519, "d": 13143, "p": 1357, "spm": 21, "hr": 151}, {"t": 3549, "d": 13252, "p": 1343, "spm": 21, "hr": 151}, {"t": 3578, "d": 13361, "p": 1352, "spm": 20, "hr": 152}, {"t": 3607, "d": 13469, "p": 1348, "spm": 21, "hr": 152}, {"t": 3636, "d": 13574, "p": 1358, "spm": 20, "hr": 152}, {"t": 3665, "d": 13681, "p": 1368, "spm": 21, "hr": 152}, {"t": 3694, "d": 13790, "p": 1355, "spm": 20, "hr": 152}, {"t": 3723, "d": 13895, "p": 1346, "spm": 21, "hr": 153}, {"t": 3751, "d": 13999, "p": 1369, "spm": 21, "hr": 152}, {"t": 3780, "d": 14107, "p": 1367, "spm": 20, "hr": 152}, {"t": 3811, "d": 14220, "p": 1364, "spm": 20, "hr": 152}, {"t": 3840, "d": 14328, "p": 1358, "spm": 20, "hr": 151}, {"t": 3869, "d": 14436, "p": 1344, "spm": 21, "hr": 151}, {"t": 3898, "d": 14544, "p": 1353, "spm": 20, "hr": 152}, {"t": 3927, "d": 14651, "p": 1351, "spm": 21, "hr": 151}, {"t": 3956, "d": 14759, "p": 1345, "spm": 21, "hr": 152}, {"t": 3984, "d": 14866, "p": 1336, "spm": 21, "hr": 152}, {"t": 4014, "d": 14974, "p": 1354, "spm": 21, "hr": 153}, {"t": 4043, "d": 15082, "p": 1363, "spm": 20, "hr": 153}, {"t": 4073, "d": 15192, "p": 1350, "spm": 20, "hr": 154}, {"t": 4102, "d": 15300, "p": 1351, "spm": 21, "hr": 154}, {"t": 4131, "d": 15409, "p": 1357, "spm": 20, "hr": 153}, {"t": 4159, "d": 15513, "p": 1351, "spm": 21, "hr": 153}, {"t": 4190, "d": 15626, "p": 1343, "spm": 21, "hr": 153}, {"t": 4219, "d": 15733, "p": 1359, "spm": 20, "hr": 153}, {"t": 4248, "d": 15842, "p": 1364, "spm": 20, "hr": 152}, {"t": 4276, "d": 15946, "p": 1345, "spm": 21, "hr": 152}, {"t": 4307, "d": 16060, "p": 1351, "spm": 21, "hr": 152}, {"t": 4334, "d": 16162, "p": 1369, "spm": 20, "hr": 152}, {"t": 4365, "d": 16274, "p": 1362, "spm": 21, "hr": 152}, {"t": 4394, "d": 16380, "p": 1349, "spm": 21, "hr": 152}, {"t": 4424, "d": 16492, "p": 1353, "spm": 20, "hr": 151}, {"t": 4453, "d": 16602, "p": 1353, "spm": 20, "hr": 152}, {"t": 4482, "d": 16708, "p": 1357, "spm": 20, "hr": 151}, {"t": 4511, "d": 16814, "p": 1361, "spm": 21, "hr": 151}, {"t": 4540, "d": 16921, "p": 1361, "spm": 21, "hr": 151}, {"t": 4568, "d": 17025, "p": 1358, "spm": 21, "hr": 150}, {"t": 4598, "d": 17137, "p": 1349, "spm": 21, "hr": 150}, {"t": 4627, "d": 17244, "p": 1344, "spm": 21, "hr": 150}, {"t": 4656, "d": 17351, "p": 1358, "spm": 20, "hr": 150}, {"t": 4685, "d": 17456, "p": 1361, "spm": 21, "hr": 150}, {"t": 4713, "d": 17563, "p": 1358, "spm": 21, "hr": 150}, {"t": 4740, "d": 17662, "p": 1357, "spm": 20, "hr": 151}, {"t": 4770, "d": 17771, "p": 1369, "spm": 22, "hr": 150}, {"t": 4798, "d": 17875, "p": 1369, "spm": 21, "hr": 150}, {"t": 4826, "d": 17977, "p": 1362, "spm": 22, "hr": 150}, {"t": 4855, "d": 18084, "p": 1361, "spm": 21, "hr": 150}, {"t": 4882, "d": 18184, "p": 1367, "spm": 21, "hr": 149}, {"t": 4910, "d": 18289, "p": 1344, "spm": 22, "hr": 149}, {"t": 4940, "d": 18399, "p": 1356, "spm": 21, "hr": 149}, {"t": 4968, "d": 18505, "p": 1357, "spm": 21, "hr": 148}, {"t": 4997, "d": 18612, "p": 1346, "spm": 21, "hr": 148}, {"t": 5027, "d": 18719, "p": 1354, "spm": 21, "hr": 147}, {"t": 5056, "d": 18826, "p": 1366, "spm": 20, "hr": 147}, {"t": 5084, "d": 18933, "p": 1363, "spm": 20, "hr": 148}, {"t": 5114, "d": 19043, "p": 1348, "spm": 21, "hr": 149}, {"t": 5144, "d": 19154, "p": 1336, "spm": 20, "hr": 149}, {"t": 5174, "d": 19262, "p": 1364, "spm": 20, "hr": 150}, {"t": 5203, "d": 19373, "p": 1361, "spm": 20, "hr": 151}, {"t": 5231, "d": 19478, "p": 1348, "spm": 20, "hr": 152}, {"t": 5262, "d": 19591, "p": 1355, "spm": 20, "hr": 152}, {"t": 5291, "d": 19698, "p": 1361, "spm": 20, "hr": 153}, {"t": 5320, "d": 19806, "p": 1353, "spm": 21, "hr": 153}, {"t": 5349, "d": 19914, "p": 1353, "spm": 21, "hr": 153}, {"t": 5372, "d": 20000, "p": 1340, "spm": 21, "hr": 154}], "workout": {"splits": [{"type": "distance", "time": 1397, "distance": 510, "heart_rate": {"average": 141}, "stroke_rate": 21}, {"type": "distance", "time": 1301, "distance": 499, "heart_rate": {"average": 150}, "stroke_rate": 22}, {"type": "distance", "time": 1344, "distance": 498, "heart_rate": {"average": 152}, "stroke_rate": 20}, {"type": "distance", "time": 1328, "distance": 491, "heart_rate": {"average": 150}, "stroke_rate": 20}]}} +May-21-2021 08:41:40 User 1, C2 ID 33991243 +May-21-2021 08:41:40 {"distance": 13878, "user_id": 457764, "ranked": false, "weight_class": "L", "verified": false, "workout_type": false, "comments": "\n from speedcoach2v2.15 via rowsandall.com", "heart_rate": {"max": 158, "average": 156}, "source": "rowingdata", "date_utc": "2018-06-30 05:31:01", "time_formatted": "1:21:16.7", "time": 48767, "date": "2018-06-30 07:31:01", "timezone": "Europe/Prague", "type": "water", "id": 33991243, "stroke_data": true} +May-21-2021 08:41:40 Time zone Europe/Prague, stardatetime 2018-06-30 06:09:44.300000+02:00, duration 01:21:16.6 +May-21-2021 08:49:18 Upload to C2 user 1 +May-21-2021 08:49:18 {"type": "water", "date": "2016-05-20 13:50:26", "stroke_count": 189, "timezone": "Europe/Amsterdam", "distance": 2000, "time": 5400, "weight_class": "H", "comments": null, "stroke_rate": 21, "drag_factor": 104, "heart_rate": {"average": 148, "max": 156}, "stroke_data": [{"t": 32, "d": 131, "p": 2628, "spm": 19, "hr": 127}, {"t": 32, "d": 131, "p": 2394, "spm": 19, "hr": 127}, {"t": 61, "d": 210, "p": 1991, "spm": 20, "hr": 128}, {"t": 92, "d": 303, "p": 1764, "spm": 20, "hr": 129}, {"t": 121, "d": 390, "p": 1685, "spm": 20, "hr": 130}, {"t": 151, "d": 482, "p": 1639, "spm": 21, "hr": 131}, {"t": 181, "d": 576, "p": 1620, "spm": 20, "hr": 131}, {"t": 209, "d": 664, "p": 1597, "spm": 20, "hr": 132}, {"t": 238, "d": 755, "p": 1601, "spm": 21, "hr": 132}, {"t": 269, "d": 851, "p": 1589, "spm": 20, "hr": 132}, {"t": 296, "d": 950, "p": 1524, "spm": 21, "hr": 132}, {"t": 323, "d": 1050, "p": 1408, "spm": 22, "hr": 133}, {"t": 351, "d": 1153, "p": 1379, "spm": 21, "hr": 134}, {"t": 380, "d": 1258, "p": 1365, "spm": 21, "hr": 135}, {"t": 408, "d": 1366, "p": 1342, "spm": 21, "hr": 136}, {"t": 436, "d": 1472, "p": 1331, "spm": 22, "hr": 137}, {"t": 464, "d": 1576, "p": 1324, "spm": 22, "hr": 139}, {"t": 491, "d": 1678, "p": 1344, "spm": 21, "hr": 140}, {"t": 519, "d": 1785, "p": 1332, "spm": 22, "hr": 140}, {"t": 546, "d": 1885, "p": 1317, "spm": 21, "hr": 141}, {"t": 575, "d": 1993, "p": 1338, "spm": 21, "hr": 141}, {"t": 602, "d": 2094, "p": 1328, "spm": 22, "hr": 142}, {"t": 628, "d": 2194, "p": 1328, "spm": 22, "hr": 142}, {"t": 657, "d": 2302, "p": 1337, "spm": 22, "hr": 143}, {"t": 683, "d": 2402, "p": 1340, "spm": 22, "hr": 144}, {"t": 710, "d": 2501, "p": 1331, "spm": 23, "hr": 145}, {"t": 734, "d": 2596, "p": 1326, "spm": 23, "hr": 145}, {"t": 763, "d": 2703, "p": 1324, "spm": 23, "hr": 145}, {"t": 790, "d": 2806, "p": 1332, "spm": 22, "hr": 145}, {"t": 817, "d": 2907, "p": 1331, "spm": 22, "hr": 144}, {"t": 844, "d": 3008, "p": 1333, "spm": 23, "hr": 145}, {"t": 871, "d": 3111, "p": 1325, "spm": 22, "hr": 145}, {"t": 897, "d": 3212, "p": 1312, "spm": 22, "hr": 145}, {"t": 926, "d": 3319, "p": 1330, "spm": 21, "hr": 145}, {"t": 953, "d": 3420, "p": 1328, "spm": 22, "hr": 146}, {"t": 980, "d": 3524, "p": 1328, "spm": 22, "hr": 146}, {"t": 1008, "d": 3630, "p": 1321, "spm": 22, "hr": 146}, {"t": 1036, "d": 3734, "p": 1324, "spm": 22, "hr": 147}, {"t": 1063, "d": 3839, "p": 1322, "spm": 22, "hr": 147}, {"t": 1092, "d": 3946, "p": 1326, "spm": 22, "hr": 147}, {"t": 1119, "d": 4050, "p": 1335, "spm": 21, "hr": 147}, {"t": 1146, "d": 4153, "p": 1325, "spm": 22, "hr": 148}, {"t": 1176, "d": 4260, "p": 1329, "spm": 22, "hr": 148}, {"t": 1203, "d": 4365, "p": 1333, "spm": 21, "hr": 148}, {"t": 1231, "d": 4469, "p": 1335, "spm": 22, "hr": 148}, {"t": 1256, "d": 4569, "p": 1312, "spm": 22, "hr": 149}, {"t": 1284, "d": 4676, "p": 1316, "spm": 22, "hr": 149}, {"t": 1313, "d": 4785, "p": 1315, "spm": 22, "hr": 150}, {"t": 1341, "d": 4890, "p": 1318, "spm": 21, "hr": 150}, {"t": 1367, "d": 4991, "p": 1336, "spm": 21, "hr": 150}, {"t": 1397, "d": 5100, "p": 1329, "spm": 22, "hr": 150}, {"t": 1423, "d": 5199, "p": 1323, "spm": 22, "hr": 149}, {"t": 1451, "d": 5306, "p": 1327, "spm": 22, "hr": 149}, {"t": 1478, "d": 5408, "p": 1337, "spm": 22, "hr": 149}, {"t": 1505, "d": 5508, "p": 1334, "spm": 22, "hr": 148}, {"t": 1532, "d": 5608, "p": 1348, "spm": 22, "hr": 148}, {"t": 1559, "d": 5710, "p": 1333, "spm": 22, "hr": 147}, {"t": 1584, "d": 5807, "p": 1330, "spm": 22, "hr": 147}, {"t": 1612, "d": 5912, "p": 1329, "spm": 22, "hr": 147}, {"t": 1639, "d": 6014, "p": 1330, "spm": 22, "hr": 147}, {"t": 1666, "d": 6114, "p": 1321, "spm": 23, "hr": 147}, {"t": 1693, "d": 6218, "p": 1328, "spm": 23, "hr": 147}, {"t": 1720, "d": 6321, "p": 1317, "spm": 22, "hr": 147}, {"t": 1747, "d": 6423, "p": 1319, "spm": 22, "hr": 147}, {"t": 1772, "d": 6520, "p": 1310, "spm": 23, "hr": 148}, {"t": 1801, "d": 6627, "p": 1297, "spm": 23, "hr": 148}, {"t": 1826, "d": 6731, "p": 1296, "spm": 23, "hr": 148}, {"t": 1854, "d": 6836, "p": 1295, "spm": 22, "hr": 149}, {"t": 1880, "d": 6938, "p": 1297, "spm": 22, "hr": 149}, {"t": 1905, "d": 7038, "p": 1292, "spm": 22, "hr": 149}, {"t": 1934, "d": 7147, "p": 1297, "spm": 23, "hr": 150}, {"t": 1960, "d": 7249, "p": 1296, "spm": 22, "hr": 150}, {"t": 1987, "d": 7352, "p": 1306, "spm": 23, "hr": 151}, {"t": 2014, "d": 7454, "p": 1307, "spm": 22, "hr": 151}, {"t": 2041, "d": 7560, "p": 1291, "spm": 23, "hr": 151}, {"t": 2067, "d": 7663, "p": 1294, "spm": 22, "hr": 150}, {"t": 2094, "d": 7765, "p": 1300, "spm": 22, "hr": 150}, {"t": 2120, "d": 7869, "p": 1295, "spm": 23, "hr": 150}, {"t": 2147, "d": 7972, "p": 1290, "spm": 22, "hr": 150}, {"t": 2174, "d": 8078, "p": 1288, "spm": 23, "hr": 150}, {"t": 2201, "d": 8182, "p": 1286, "spm": 23, "hr": 150}, {"t": 2226, "d": 8284, "p": 1282, "spm": 22, "hr": 150}, {"t": 2254, "d": 8392, "p": 1279, "spm": 23, "hr": 150}, {"t": 2281, "d": 8496, "p": 1288, "spm": 23, "hr": 151}, {"t": 2307, "d": 8601, "p": 1272, "spm": 22, "hr": 151}, {"t": 2333, "d": 8703, "p": 1272, "spm": 22, "hr": 152}, {"t": 2361, "d": 8811, "p": 1280, "spm": 22, "hr": 152}, {"t": 2388, "d": 8917, "p": 1284, "spm": 23, "hr": 152}, {"t": 2415, "d": 9021, "p": 1293, "spm": 22, "hr": 152}, {"t": 2444, "d": 9131, "p": 1299, "spm": 22, "hr": 152}, {"t": 2472, "d": 9239, "p": 1309, "spm": 22, "hr": 153}, {"t": 2500, "d": 9346, "p": 1307, "spm": 21, "hr": 154}, {"t": 2528, "d": 9454, "p": 1320, "spm": 21, "hr": 154}, {"t": 2556, "d": 9560, "p": 1318, "spm": 21, "hr": 155}, {"t": 2585, "d": 9667, "p": 1326, "spm": 21, "hr": 155}, {"t": 2613, "d": 9774, "p": 1330, "spm": 21, "hr": 156}, {"t": 2641, "d": 9881, "p": 1310, "spm": 21, "hr": 156}, {"t": 2669, "d": 9988, "p": 1316, "spm": 21, "hr": 156}, {"t": 2698, "d": 10096, "p": 1327, "spm": 21, "hr": 156}, {"t": 2727, "d": 10206, "p": 1338, "spm": 21, "hr": 156}, {"t": 2757, "d": 10315, "p": 1345, "spm": 20, "hr": 156}, {"t": 2786, "d": 10425, "p": 1347, "spm": 21, "hr": 156}, {"t": 2815, "d": 10533, "p": 1347, "spm": 20, "hr": 155}, {"t": 2844, "d": 10641, "p": 1339, "spm": 21, "hr": 155}, {"t": 2874, "d": 10753, "p": 1354, "spm": 20, "hr": 155}, {"t": 2904, "d": 10861, "p": 1375, "spm": 20, "hr": 155}, {"t": 2935, "d": 10975, "p": 1359, "spm": 21, "hr": 155}, {"t": 2964, "d": 11085, "p": 1344, "spm": 20, "hr": 155}, {"t": 2993, "d": 11192, "p": 1353, "spm": 20, "hr": 155}, {"t": 3024, "d": 11306, "p": 1353, "spm": 20, "hr": 155}, {"t": 3054, "d": 11413, "p": 1353, "spm": 20, "hr": 155}, {"t": 3083, "d": 11524, "p": 1354, "spm": 21, "hr": 155}, {"t": 3113, "d": 11633, "p": 1367, "spm": 20, "hr": 155}, {"t": 3140, "d": 11738, "p": 1360, "spm": 20, "hr": 154}, {"t": 3170, "d": 11848, "p": 1342, "spm": 21, "hr": 154}, {"t": 3200, "d": 11958, "p": 1343, "spm": 21, "hr": 153}, {"t": 3229, "d": 12066, "p": 1357, "spm": 21, "hr": 152}, {"t": 3259, "d": 12173, "p": 1358, "spm": 21, "hr": 153}, {"t": 3287, "d": 12278, "p": 1363, "spm": 21, "hr": 152}, {"t": 3315, "d": 12387, "p": 1354, "spm": 21, "hr": 152}, {"t": 3345, "d": 12495, "p": 1334, "spm": 21, "hr": 151}, {"t": 3374, "d": 12601, "p": 1359, "spm": 20, "hr": 151}, {"t": 3403, "d": 12709, "p": 1357, "spm": 21, "hr": 151}, {"t": 3432, "d": 12818, "p": 1346, "spm": 21, "hr": 150}, {"t": 3461, "d": 12927, "p": 1355, "spm": 20, "hr": 151}, {"t": 3490, "d": 13034, "p": 1358, "spm": 20, "hr": 151}, {"t": 3519, "d": 13143, "p": 1357, "spm": 21, "hr": 151}, {"t": 3549, "d": 13252, "p": 1343, "spm": 21, "hr": 151}, {"t": 3578, "d": 13361, "p": 1352, "spm": 20, "hr": 152}, {"t": 3607, "d": 13469, "p": 1348, "spm": 21, "hr": 152}, {"t": 3636, "d": 13574, "p": 1358, "spm": 20, "hr": 152}, {"t": 3665, "d": 13681, "p": 1368, "spm": 21, "hr": 152}, {"t": 3694, "d": 13790, "p": 1355, "spm": 20, "hr": 152}, {"t": 3723, "d": 13895, "p": 1346, "spm": 21, "hr": 153}, {"t": 3751, "d": 13999, "p": 1369, "spm": 21, "hr": 152}, {"t": 3780, "d": 14107, "p": 1367, "spm": 20, "hr": 152}, {"t": 3811, "d": 14220, "p": 1364, "spm": 20, "hr": 152}, {"t": 3840, "d": 14328, "p": 1358, "spm": 20, "hr": 151}, {"t": 3869, "d": 14436, "p": 1344, "spm": 21, "hr": 151}, {"t": 3898, "d": 14544, "p": 1353, "spm": 20, "hr": 152}, {"t": 3927, "d": 14651, "p": 1351, "spm": 21, "hr": 151}, {"t": 3956, "d": 14759, "p": 1345, "spm": 21, "hr": 152}, {"t": 3984, "d": 14866, "p": 1336, "spm": 21, "hr": 152}, {"t": 4014, "d": 14974, "p": 1354, "spm": 21, "hr": 153}, {"t": 4043, "d": 15082, "p": 1363, "spm": 20, "hr": 153}, {"t": 4073, "d": 15192, "p": 1350, "spm": 20, "hr": 154}, {"t": 4102, "d": 15300, "p": 1351, "spm": 21, "hr": 154}, {"t": 4131, "d": 15409, "p": 1357, "spm": 20, "hr": 153}, {"t": 4159, "d": 15513, "p": 1351, "spm": 21, "hr": 153}, {"t": 4190, "d": 15626, "p": 1343, "spm": 21, "hr": 153}, {"t": 4219, "d": 15733, "p": 1359, "spm": 20, "hr": 153}, {"t": 4248, "d": 15842, "p": 1364, "spm": 20, "hr": 152}, {"t": 4276, "d": 15946, "p": 1345, "spm": 21, "hr": 152}, {"t": 4307, "d": 16060, "p": 1351, "spm": 21, "hr": 152}, {"t": 4334, "d": 16162, "p": 1369, "spm": 20, "hr": 152}, {"t": 4365, "d": 16274, "p": 1362, "spm": 21, "hr": 152}, {"t": 4394, "d": 16380, "p": 1349, "spm": 21, "hr": 152}, {"t": 4424, "d": 16492, "p": 1353, "spm": 20, "hr": 151}, {"t": 4453, "d": 16602, "p": 1353, "spm": 20, "hr": 152}, {"t": 4482, "d": 16708, "p": 1357, "spm": 20, "hr": 151}, {"t": 4511, "d": 16814, "p": 1361, "spm": 21, "hr": 151}, {"t": 4540, "d": 16921, "p": 1361, "spm": 21, "hr": 151}, {"t": 4568, "d": 17025, "p": 1358, "spm": 21, "hr": 150}, {"t": 4598, "d": 17137, "p": 1349, "spm": 21, "hr": 150}, {"t": 4627, "d": 17244, "p": 1344, "spm": 21, "hr": 150}, {"t": 4656, "d": 17351, "p": 1358, "spm": 20, "hr": 150}, {"t": 4685, "d": 17456, "p": 1361, "spm": 21, "hr": 150}, {"t": 4713, "d": 17563, "p": 1358, "spm": 21, "hr": 150}, {"t": 4740, "d": 17662, "p": 1357, "spm": 20, "hr": 151}, {"t": 4770, "d": 17771, "p": 1369, "spm": 22, "hr": 150}, {"t": 4798, "d": 17875, "p": 1369, "spm": 21, "hr": 150}, {"t": 4826, "d": 17977, "p": 1362, "spm": 22, "hr": 150}, {"t": 4855, "d": 18084, "p": 1361, "spm": 21, "hr": 150}, {"t": 4882, "d": 18184, "p": 1367, "spm": 21, "hr": 149}, {"t": 4910, "d": 18289, "p": 1344, "spm": 22, "hr": 149}, {"t": 4940, "d": 18399, "p": 1356, "spm": 21, "hr": 149}, {"t": 4968, "d": 18505, "p": 1357, "spm": 21, "hr": 148}, {"t": 4997, "d": 18612, "p": 1346, "spm": 21, "hr": 148}, {"t": 5027, "d": 18719, "p": 1354, "spm": 21, "hr": 147}, {"t": 5056, "d": 18826, "p": 1366, "spm": 20, "hr": 147}, {"t": 5084, "d": 18933, "p": 1363, "spm": 20, "hr": 148}, {"t": 5114, "d": 19043, "p": 1348, "spm": 21, "hr": 149}, {"t": 5144, "d": 19154, "p": 1336, "spm": 20, "hr": 149}, {"t": 5174, "d": 19262, "p": 1364, "spm": 20, "hr": 150}, {"t": 5203, "d": 19373, "p": 1361, "spm": 20, "hr": 151}, {"t": 5231, "d": 19478, "p": 1348, "spm": 20, "hr": 152}, {"t": 5262, "d": 19591, "p": 1355, "spm": 20, "hr": 152}, {"t": 5291, "d": 19698, "p": 1361, "spm": 20, "hr": 153}, {"t": 5320, "d": 19806, "p": 1353, "spm": 21, "hr": 153}, {"t": 5349, "d": 19914, "p": 1353, "spm": 21, "hr": 153}, {"t": 5372, "d": 20000, "p": 1340, "spm": 21, "hr": 154}], "workout": {"splits": [{"type": "distance", "time": 1397, "distance": 510, "heart_rate": {"average": 141}, "stroke_rate": 21}, {"type": "distance", "time": 1301, "distance": 499, "heart_rate": {"average": 150}, "stroke_rate": 22}, {"type": "distance", "time": 1344, "distance": 498, "heart_rate": {"average": 152}, "stroke_rate": 20}, {"type": "distance", "time": 1328, "distance": 491, "heart_rate": {"average": 150}, "stroke_rate": 20}]}} +May-21-2021 08:49:18 User 1, C2 ID 33991243 +May-21-2021 08:49:18 {"distance": 13878, "user_id": 457764, "ranked": false, "weight_class": "L", "verified": false, "workout_type": false, "comments": "\n from speedcoach2v2.15 via rowsandall.com", "heart_rate": {"max": 158, "average": 156}, "source": "rowingdata", "date_utc": "2018-06-30 05:31:01", "time_formatted": "1:21:16.7", "time": 48767, "date": "2018-06-30 07:31:01", "timezone": "Europe/Prague", "type": "water", "id": 33991243, "stroke_data": true} +May-21-2021 08:49:18 Time zone Europe/Prague, stardatetime 2018-06-30 06:09:44.300000+02:00, duration 01:21:16.6 +May-21-2021 08:52:05 Upload to C2 user 1 +May-21-2021 08:52:05 {"type": "water", "date": "2016-05-20 13:50:26", "stroke_count": 189, "timezone": "Europe/Amsterdam", "distance": 2000, "time": 5400, "weight_class": "H", "comments": null, "stroke_rate": 21, "drag_factor": 104, "heart_rate": {"average": 148, "max": 156}, "stroke_data": [{"t": 32, "d": 131, "p": 2628, "spm": 19, "hr": 127}, {"t": 32, "d": 131, "p": 2394, "spm": 19, "hr": 127}, {"t": 61, "d": 210, "p": 1991, "spm": 20, "hr": 128}, {"t": 92, "d": 303, "p": 1764, "spm": 20, "hr": 129}, {"t": 121, "d": 390, "p": 1685, "spm": 20, "hr": 130}, {"t": 151, "d": 482, "p": 1639, "spm": 21, "hr": 131}, {"t": 181, "d": 576, "p": 1620, "spm": 20, "hr": 131}, {"t": 209, "d": 664, "p": 1597, "spm": 20, "hr": 132}, {"t": 238, "d": 755, "p": 1601, "spm": 21, "hr": 132}, {"t": 269, "d": 851, "p": 1589, "spm": 20, "hr": 132}, {"t": 296, "d": 950, "p": 1524, "spm": 21, "hr": 132}, {"t": 323, "d": 1050, "p": 1408, "spm": 22, "hr": 133}, {"t": 351, "d": 1153, "p": 1379, "spm": 21, "hr": 134}, {"t": 380, "d": 1258, "p": 1365, "spm": 21, "hr": 135}, {"t": 408, "d": 1366, "p": 1342, "spm": 21, "hr": 136}, {"t": 436, "d": 1472, "p": 1331, "spm": 22, "hr": 137}, {"t": 464, "d": 1576, "p": 1324, "spm": 22, "hr": 139}, {"t": 491, "d": 1678, "p": 1344, "spm": 21, "hr": 140}, {"t": 519, "d": 1785, "p": 1332, "spm": 22, "hr": 140}, {"t": 546, "d": 1885, "p": 1317, "spm": 21, "hr": 141}, {"t": 575, "d": 1993, "p": 1338, "spm": 21, "hr": 141}, {"t": 602, "d": 2094, "p": 1328, "spm": 22, "hr": 142}, {"t": 628, "d": 2194, "p": 1328, "spm": 22, "hr": 142}, {"t": 657, "d": 2302, "p": 1337, "spm": 22, "hr": 143}, {"t": 683, "d": 2402, "p": 1340, "spm": 22, "hr": 144}, {"t": 710, "d": 2501, "p": 1331, "spm": 23, "hr": 145}, {"t": 734, "d": 2596, "p": 1326, "spm": 23, "hr": 145}, {"t": 763, "d": 2703, "p": 1324, "spm": 23, "hr": 145}, {"t": 790, "d": 2806, "p": 1332, "spm": 22, "hr": 145}, {"t": 817, "d": 2907, "p": 1331, "spm": 22, "hr": 144}, {"t": 844, "d": 3008, "p": 1333, "spm": 23, "hr": 145}, {"t": 871, "d": 3111, "p": 1325, "spm": 22, "hr": 145}, {"t": 897, "d": 3212, "p": 1312, "spm": 22, "hr": 145}, {"t": 926, "d": 3319, "p": 1330, "spm": 21, "hr": 145}, {"t": 953, "d": 3420, "p": 1328, "spm": 22, "hr": 146}, {"t": 980, "d": 3524, "p": 1328, "spm": 22, "hr": 146}, {"t": 1008, "d": 3630, "p": 1321, "spm": 22, "hr": 146}, {"t": 1036, "d": 3734, "p": 1324, "spm": 22, "hr": 147}, {"t": 1063, "d": 3839, "p": 1322, "spm": 22, "hr": 147}, {"t": 1092, "d": 3946, "p": 1326, "spm": 22, "hr": 147}, {"t": 1119, "d": 4050, "p": 1335, "spm": 21, "hr": 147}, {"t": 1146, "d": 4153, "p": 1325, "spm": 22, "hr": 148}, {"t": 1176, "d": 4260, "p": 1329, "spm": 22, "hr": 148}, {"t": 1203, "d": 4365, "p": 1333, "spm": 21, "hr": 148}, {"t": 1231, "d": 4469, "p": 1335, "spm": 22, "hr": 148}, {"t": 1256, "d": 4569, "p": 1312, "spm": 22, "hr": 149}, {"t": 1284, "d": 4676, "p": 1316, "spm": 22, "hr": 149}, {"t": 1313, "d": 4785, "p": 1315, "spm": 22, "hr": 150}, {"t": 1341, "d": 4890, "p": 1318, "spm": 21, "hr": 150}, {"t": 1367, "d": 4991, "p": 1336, "spm": 21, "hr": 150}, {"t": 1397, "d": 5100, "p": 1329, "spm": 22, "hr": 150}, {"t": 1423, "d": 5199, "p": 1323, "spm": 22, "hr": 149}, {"t": 1451, "d": 5306, "p": 1327, "spm": 22, "hr": 149}, {"t": 1478, "d": 5408, "p": 1337, "spm": 22, "hr": 149}, {"t": 1505, "d": 5508, "p": 1334, "spm": 22, "hr": 148}, {"t": 1532, "d": 5608, "p": 1348, "spm": 22, "hr": 148}, {"t": 1559, "d": 5710, "p": 1333, "spm": 22, "hr": 147}, {"t": 1584, "d": 5807, "p": 1330, "spm": 22, "hr": 147}, {"t": 1612, "d": 5912, "p": 1329, "spm": 22, "hr": 147}, {"t": 1639, "d": 6014, "p": 1330, "spm": 22, "hr": 147}, {"t": 1666, "d": 6114, "p": 1321, "spm": 23, "hr": 147}, {"t": 1693, "d": 6218, "p": 1328, "spm": 23, "hr": 147}, {"t": 1720, "d": 6321, "p": 1317, "spm": 22, "hr": 147}, {"t": 1747, "d": 6423, "p": 1319, "spm": 22, "hr": 147}, {"t": 1772, "d": 6520, "p": 1310, "spm": 23, "hr": 148}, {"t": 1801, "d": 6627, "p": 1297, "spm": 23, "hr": 148}, {"t": 1826, "d": 6731, "p": 1296, "spm": 23, "hr": 148}, {"t": 1854, "d": 6836, "p": 1295, "spm": 22, "hr": 149}, {"t": 1880, "d": 6938, "p": 1297, "spm": 22, "hr": 149}, {"t": 1905, "d": 7038, "p": 1292, "spm": 22, "hr": 149}, {"t": 1934, "d": 7147, "p": 1297, "spm": 23, "hr": 150}, {"t": 1960, "d": 7249, "p": 1296, "spm": 22, "hr": 150}, {"t": 1987, "d": 7352, "p": 1306, "spm": 23, "hr": 151}, {"t": 2014, "d": 7454, "p": 1307, "spm": 22, "hr": 151}, {"t": 2041, "d": 7560, "p": 1291, "spm": 23, "hr": 151}, {"t": 2067, "d": 7663, "p": 1294, "spm": 22, "hr": 150}, {"t": 2094, "d": 7765, "p": 1300, "spm": 22, "hr": 150}, {"t": 2120, "d": 7869, "p": 1295, "spm": 23, "hr": 150}, {"t": 2147, "d": 7972, "p": 1290, "spm": 22, "hr": 150}, {"t": 2174, "d": 8078, "p": 1288, "spm": 23, "hr": 150}, {"t": 2201, "d": 8182, "p": 1286, "spm": 23, "hr": 150}, {"t": 2226, "d": 8284, "p": 1282, "spm": 22, "hr": 150}, {"t": 2254, "d": 8392, "p": 1279, "spm": 23, "hr": 150}, {"t": 2281, "d": 8496, "p": 1288, "spm": 23, "hr": 151}, {"t": 2307, "d": 8601, "p": 1272, "spm": 22, "hr": 151}, {"t": 2333, "d": 8703, "p": 1272, "spm": 22, "hr": 152}, {"t": 2361, "d": 8811, "p": 1280, "spm": 22, "hr": 152}, {"t": 2388, "d": 8917, "p": 1284, "spm": 23, "hr": 152}, {"t": 2415, "d": 9021, "p": 1293, "spm": 22, "hr": 152}, {"t": 2444, "d": 9131, "p": 1299, "spm": 22, "hr": 152}, {"t": 2472, "d": 9239, "p": 1309, "spm": 22, "hr": 153}, {"t": 2500, "d": 9346, "p": 1307, "spm": 21, "hr": 154}, {"t": 2528, "d": 9454, "p": 1320, "spm": 21, "hr": 154}, {"t": 2556, "d": 9560, "p": 1318, "spm": 21, "hr": 155}, {"t": 2585, "d": 9667, "p": 1326, "spm": 21, "hr": 155}, {"t": 2613, "d": 9774, "p": 1330, "spm": 21, "hr": 156}, {"t": 2641, "d": 9881, "p": 1310, "spm": 21, "hr": 156}, {"t": 2669, "d": 9988, "p": 1316, "spm": 21, "hr": 156}, {"t": 2698, "d": 10096, "p": 1327, "spm": 21, "hr": 156}, {"t": 2727, "d": 10206, "p": 1338, "spm": 21, "hr": 156}, {"t": 2757, "d": 10315, "p": 1345, "spm": 20, "hr": 156}, {"t": 2786, "d": 10425, "p": 1347, "spm": 21, "hr": 156}, {"t": 2815, "d": 10533, "p": 1347, "spm": 20, "hr": 155}, {"t": 2844, "d": 10641, "p": 1339, "spm": 21, "hr": 155}, {"t": 2874, "d": 10753, "p": 1354, "spm": 20, "hr": 155}, {"t": 2904, "d": 10861, "p": 1375, "spm": 20, "hr": 155}, {"t": 2935, "d": 10975, "p": 1359, "spm": 21, "hr": 155}, {"t": 2964, "d": 11085, "p": 1344, "spm": 20, "hr": 155}, {"t": 2993, "d": 11192, "p": 1353, "spm": 20, "hr": 155}, {"t": 3024, "d": 11306, "p": 1353, "spm": 20, "hr": 155}, {"t": 3054, "d": 11413, "p": 1353, "spm": 20, "hr": 155}, {"t": 3083, "d": 11524, "p": 1354, "spm": 21, "hr": 155}, {"t": 3113, "d": 11633, "p": 1367, "spm": 20, "hr": 155}, {"t": 3140, "d": 11738, "p": 1360, "spm": 20, "hr": 154}, {"t": 3170, "d": 11848, "p": 1342, "spm": 21, "hr": 154}, {"t": 3200, "d": 11958, "p": 1343, "spm": 21, "hr": 153}, {"t": 3229, "d": 12066, "p": 1357, "spm": 21, "hr": 152}, {"t": 3259, "d": 12173, "p": 1358, "spm": 21, "hr": 153}, {"t": 3287, "d": 12278, "p": 1363, "spm": 21, "hr": 152}, {"t": 3315, "d": 12387, "p": 1354, "spm": 21, "hr": 152}, {"t": 3345, "d": 12495, "p": 1334, "spm": 21, "hr": 151}, {"t": 3374, "d": 12601, "p": 1359, "spm": 20, "hr": 151}, {"t": 3403, "d": 12709, "p": 1357, "spm": 21, "hr": 151}, {"t": 3432, "d": 12818, "p": 1346, "spm": 21, "hr": 150}, {"t": 3461, "d": 12927, "p": 1355, "spm": 20, "hr": 151}, {"t": 3490, "d": 13034, "p": 1358, "spm": 20, "hr": 151}, {"t": 3519, "d": 13143, "p": 1357, "spm": 21, "hr": 151}, {"t": 3549, "d": 13252, "p": 1343, "spm": 21, "hr": 151}, {"t": 3578, "d": 13361, "p": 1352, "spm": 20, "hr": 152}, {"t": 3607, "d": 13469, "p": 1348, "spm": 21, "hr": 152}, {"t": 3636, "d": 13574, "p": 1358, "spm": 20, "hr": 152}, {"t": 3665, "d": 13681, "p": 1368, "spm": 21, "hr": 152}, {"t": 3694, "d": 13790, "p": 1355, "spm": 20, "hr": 152}, {"t": 3723, "d": 13895, "p": 1346, "spm": 21, "hr": 153}, {"t": 3751, "d": 13999, "p": 1369, "spm": 21, "hr": 152}, {"t": 3780, "d": 14107, "p": 1367, "spm": 20, "hr": 152}, {"t": 3811, "d": 14220, "p": 1364, "spm": 20, "hr": 152}, {"t": 3840, "d": 14328, "p": 1358, "spm": 20, "hr": 151}, {"t": 3869, "d": 14436, "p": 1344, "spm": 21, "hr": 151}, {"t": 3898, "d": 14544, "p": 1353, "spm": 20, "hr": 152}, {"t": 3927, "d": 14651, "p": 1351, "spm": 21, "hr": 151}, {"t": 3956, "d": 14759, "p": 1345, "spm": 21, "hr": 152}, {"t": 3984, "d": 14866, "p": 1336, "spm": 21, "hr": 152}, {"t": 4014, "d": 14974, "p": 1354, "spm": 21, "hr": 153}, {"t": 4043, "d": 15082, "p": 1363, "spm": 20, "hr": 153}, {"t": 4073, "d": 15192, "p": 1350, "spm": 20, "hr": 154}, {"t": 4102, "d": 15300, "p": 1351, "spm": 21, "hr": 154}, {"t": 4131, "d": 15409, "p": 1357, "spm": 20, "hr": 153}, {"t": 4159, "d": 15513, "p": 1351, "spm": 21, "hr": 153}, {"t": 4190, "d": 15626, "p": 1343, "spm": 21, "hr": 153}, {"t": 4219, "d": 15733, "p": 1359, "spm": 20, "hr": 153}, {"t": 4248, "d": 15842, "p": 1364, "spm": 20, "hr": 152}, {"t": 4276, "d": 15946, "p": 1345, "spm": 21, "hr": 152}, {"t": 4307, "d": 16060, "p": 1351, "spm": 21, "hr": 152}, {"t": 4334, "d": 16162, "p": 1369, "spm": 20, "hr": 152}, {"t": 4365, "d": 16274, "p": 1362, "spm": 21, "hr": 152}, {"t": 4394, "d": 16380, "p": 1349, "spm": 21, "hr": 152}, {"t": 4424, "d": 16492, "p": 1353, "spm": 20, "hr": 151}, {"t": 4453, "d": 16602, "p": 1353, "spm": 20, "hr": 152}, {"t": 4482, "d": 16708, "p": 1357, "spm": 20, "hr": 151}, {"t": 4511, "d": 16814, "p": 1361, "spm": 21, "hr": 151}, {"t": 4540, "d": 16921, "p": 1361, "spm": 21, "hr": 151}, {"t": 4568, "d": 17025, "p": 1358, "spm": 21, "hr": 150}, {"t": 4598, "d": 17137, "p": 1349, "spm": 21, "hr": 150}, {"t": 4627, "d": 17244, "p": 1344, "spm": 21, "hr": 150}, {"t": 4656, "d": 17351, "p": 1358, "spm": 20, "hr": 150}, {"t": 4685, "d": 17456, "p": 1361, "spm": 21, "hr": 150}, {"t": 4713, "d": 17563, "p": 1358, "spm": 21, "hr": 150}, {"t": 4740, "d": 17662, "p": 1357, "spm": 20, "hr": 151}, {"t": 4770, "d": 17771, "p": 1369, "spm": 22, "hr": 150}, {"t": 4798, "d": 17875, "p": 1369, "spm": 21, "hr": 150}, {"t": 4826, "d": 17977, "p": 1362, "spm": 22, "hr": 150}, {"t": 4855, "d": 18084, "p": 1361, "spm": 21, "hr": 150}, {"t": 4882, "d": 18184, "p": 1367, "spm": 21, "hr": 149}, {"t": 4910, "d": 18289, "p": 1344, "spm": 22, "hr": 149}, {"t": 4940, "d": 18399, "p": 1356, "spm": 21, "hr": 149}, {"t": 4968, "d": 18505, "p": 1357, "spm": 21, "hr": 148}, {"t": 4997, "d": 18612, "p": 1346, "spm": 21, "hr": 148}, {"t": 5027, "d": 18719, "p": 1354, "spm": 21, "hr": 147}, {"t": 5056, "d": 18826, "p": 1366, "spm": 20, "hr": 147}, {"t": 5084, "d": 18933, "p": 1363, "spm": 20, "hr": 148}, {"t": 5114, "d": 19043, "p": 1348, "spm": 21, "hr": 149}, {"t": 5144, "d": 19154, "p": 1336, "spm": 20, "hr": 149}, {"t": 5174, "d": 19262, "p": 1364, "spm": 20, "hr": 150}, {"t": 5203, "d": 19373, "p": 1361, "spm": 20, "hr": 151}, {"t": 5231, "d": 19478, "p": 1348, "spm": 20, "hr": 152}, {"t": 5262, "d": 19591, "p": 1355, "spm": 20, "hr": 152}, {"t": 5291, "d": 19698, "p": 1361, "spm": 20, "hr": 153}, {"t": 5320, "d": 19806, "p": 1353, "spm": 21, "hr": 153}, {"t": 5349, "d": 19914, "p": 1353, "spm": 21, "hr": 153}, {"t": 5372, "d": 20000, "p": 1340, "spm": 21, "hr": 154}], "workout": {"splits": [{"type": "distance", "time": 1397, "distance": 510, "heart_rate": {"average": 141}, "stroke_rate": 21}, {"type": "distance", "time": 1301, "distance": 499, "heart_rate": {"average": 150}, "stroke_rate": 22}, {"type": "distance", "time": 1344, "distance": 498, "heart_rate": {"average": 152}, "stroke_rate": 20}, {"type": "distance", "time": 1328, "distance": 491, "heart_rate": {"average": 150}, "stroke_rate": 20}]}} +May-21-2021 08:52:06 User 1, C2 ID 33991243 +May-21-2021 08:52:06 {"distance": 13878, "user_id": 457764, "ranked": false, "weight_class": "L", "verified": false, "workout_type": false, "comments": "\n from speedcoach2v2.15 via rowsandall.com", "heart_rate": {"max": 158, "average": 156}, "source": "rowingdata", "date_utc": "2018-06-30 05:31:01", "time_formatted": "1:21:16.7", "time": 48767, "date": "2018-06-30 07:31:01", "timezone": "Europe/Prague", "type": "water", "id": 33991243, "stroke_data": true} +May-21-2021 08:52:06 Time zone Europe/Prague, stardatetime 2018-06-30 06:09:44.300000+02:00, duration 01:21:16.6 +May-21-2021 08:55:14 User 1, C2 ID 54440491 +May-21-2021 08:55:14 {"id": 54440491, "user_id": 457764, "date": "2021-05-20 05:01:31", "timezone": "Europe/Amsterdam", "date_utc": "2021-05-20 03:01:31", "distance": 13008, "type": "water", "time": 40825, "time_formatted": "1:08:02.5", "workout_type": false, "source": "rowingdata", "weight_class": "H", "verified": false, "ranked": false, "comments": null, "stroke_data": true, "stroke_count": 1345, "stroke_rate": 20, "heart_rate": {"average": 153, "max": 174}, "workout": {"splits": [{"type": "distance", "time": 40826, "distance": 13008, "stroke_rate": 20, "heart_rate": {"average": 153}}]}} +May-21-2021 08:55:14 Time zone Europe/Amsterdam, stardatetime 2021-05-20 03:53:28.500000+02:00, duration 01:08:02.5 +May-21-2021 09:06:14 Upload to C2 user 1 +May-21-2021 09:06:14 {"type": "water", "date": "2016-05-20 13:50:26", "stroke_count": 189, "timezone": "Europe/Amsterdam", "distance": 2000, "time": 5400, "weight_class": "H", "comments": null, "stroke_rate": 21, "drag_factor": 104, "heart_rate": {"average": 148, "max": 156}, "stroke_data": [{"t": 32, "d": 131, "p": 2628, "spm": 19, "hr": 127}, {"t": 32, "d": 131, "p": 2394, "spm": 19, "hr": 127}, {"t": 61, "d": 210, "p": 1991, "spm": 20, "hr": 128}, {"t": 92, "d": 303, "p": 1764, "spm": 20, "hr": 129}, {"t": 121, "d": 390, "p": 1685, "spm": 20, "hr": 130}, {"t": 151, "d": 482, "p": 1639, "spm": 21, "hr": 131}, {"t": 181, "d": 576, "p": 1620, "spm": 20, "hr": 131}, {"t": 209, "d": 664, "p": 1597, "spm": 20, "hr": 132}, {"t": 238, "d": 755, "p": 1601, "spm": 21, "hr": 132}, {"t": 269, "d": 851, "p": 1589, "spm": 20, "hr": 132}, {"t": 296, "d": 950, "p": 1524, "spm": 21, "hr": 132}, {"t": 323, "d": 1050, "p": 1408, "spm": 22, "hr": 133}, {"t": 351, "d": 1153, "p": 1379, "spm": 21, "hr": 134}, {"t": 380, "d": 1258, "p": 1365, "spm": 21, "hr": 135}, {"t": 408, "d": 1366, "p": 1342, "spm": 21, "hr": 136}, {"t": 436, "d": 1472, "p": 1331, "spm": 22, "hr": 137}, {"t": 464, "d": 1576, "p": 1324, "spm": 22, "hr": 139}, {"t": 491, "d": 1678, "p": 1344, "spm": 21, "hr": 140}, {"t": 519, "d": 1785, "p": 1332, "spm": 22, "hr": 140}, {"t": 546, "d": 1885, "p": 1317, "spm": 21, "hr": 141}, {"t": 575, "d": 1993, "p": 1338, "spm": 21, "hr": 141}, {"t": 602, "d": 2094, "p": 1328, "spm": 22, "hr": 142}, {"t": 628, "d": 2194, "p": 1328, "spm": 22, "hr": 142}, {"t": 657, "d": 2302, "p": 1337, "spm": 22, "hr": 143}, {"t": 683, "d": 2402, "p": 1340, "spm": 22, "hr": 144}, {"t": 710, "d": 2501, "p": 1331, "spm": 23, "hr": 145}, {"t": 734, "d": 2596, "p": 1326, "spm": 23, "hr": 145}, {"t": 763, "d": 2703, "p": 1324, "spm": 23, "hr": 145}, {"t": 790, "d": 2806, "p": 1332, "spm": 22, "hr": 145}, {"t": 817, "d": 2907, "p": 1331, "spm": 22, "hr": 144}, {"t": 844, "d": 3008, "p": 1333, "spm": 23, "hr": 145}, {"t": 871, "d": 3111, "p": 1325, "spm": 22, "hr": 145}, {"t": 897, "d": 3212, "p": 1312, "spm": 22, "hr": 145}, {"t": 926, "d": 3319, "p": 1330, "spm": 21, "hr": 145}, {"t": 953, "d": 3420, "p": 1328, "spm": 22, "hr": 146}, {"t": 980, "d": 3524, "p": 1328, "spm": 22, "hr": 146}, {"t": 1008, "d": 3630, "p": 1321, "spm": 22, "hr": 146}, {"t": 1036, "d": 3734, "p": 1324, "spm": 22, "hr": 147}, {"t": 1063, "d": 3839, "p": 1322, "spm": 22, "hr": 147}, {"t": 1092, "d": 3946, "p": 1326, "spm": 22, "hr": 147}, {"t": 1119, "d": 4050, "p": 1335, "spm": 21, "hr": 147}, {"t": 1146, "d": 4153, "p": 1325, "spm": 22, "hr": 148}, {"t": 1176, "d": 4260, "p": 1329, "spm": 22, "hr": 148}, {"t": 1203, "d": 4365, "p": 1333, "spm": 21, "hr": 148}, {"t": 1231, "d": 4469, "p": 1335, "spm": 22, "hr": 148}, {"t": 1256, "d": 4569, "p": 1312, "spm": 22, "hr": 149}, {"t": 1284, "d": 4676, "p": 1316, "spm": 22, "hr": 149}, {"t": 1313, "d": 4785, "p": 1315, "spm": 22, "hr": 150}, {"t": 1341, "d": 4890, "p": 1318, "spm": 21, "hr": 150}, {"t": 1367, "d": 4991, "p": 1336, "spm": 21, "hr": 150}, {"t": 1397, "d": 5100, "p": 1329, "spm": 22, "hr": 150}, {"t": 1423, "d": 5199, "p": 1323, "spm": 22, "hr": 149}, {"t": 1451, "d": 5306, "p": 1327, "spm": 22, "hr": 149}, {"t": 1478, "d": 5408, "p": 1337, "spm": 22, "hr": 149}, {"t": 1505, "d": 5508, "p": 1334, "spm": 22, "hr": 148}, {"t": 1532, "d": 5608, "p": 1348, "spm": 22, "hr": 148}, {"t": 1559, "d": 5710, "p": 1333, "spm": 22, "hr": 147}, {"t": 1584, "d": 5807, "p": 1330, "spm": 22, "hr": 147}, {"t": 1612, "d": 5912, "p": 1329, "spm": 22, "hr": 147}, {"t": 1639, "d": 6014, "p": 1330, "spm": 22, "hr": 147}, {"t": 1666, "d": 6114, "p": 1321, "spm": 23, "hr": 147}, {"t": 1693, "d": 6218, "p": 1328, "spm": 23, "hr": 147}, {"t": 1720, "d": 6321, "p": 1317, "spm": 22, "hr": 147}, {"t": 1747, "d": 6423, "p": 1319, "spm": 22, "hr": 147}, {"t": 1772, "d": 6520, "p": 1310, "spm": 23, "hr": 148}, {"t": 1801, "d": 6627, "p": 1297, "spm": 23, "hr": 148}, {"t": 1826, "d": 6731, "p": 1296, "spm": 23, "hr": 148}, {"t": 1854, "d": 6836, "p": 1295, "spm": 22, "hr": 149}, {"t": 1880, "d": 6938, "p": 1297, "spm": 22, "hr": 149}, {"t": 1905, "d": 7038, "p": 1292, "spm": 22, "hr": 149}, {"t": 1934, "d": 7147, "p": 1297, "spm": 23, "hr": 150}, {"t": 1960, "d": 7249, "p": 1296, "spm": 22, "hr": 150}, {"t": 1987, "d": 7352, "p": 1306, "spm": 23, "hr": 151}, {"t": 2014, "d": 7454, "p": 1307, "spm": 22, "hr": 151}, {"t": 2041, "d": 7560, "p": 1291, "spm": 23, "hr": 151}, {"t": 2067, "d": 7663, "p": 1294, "spm": 22, "hr": 150}, {"t": 2094, "d": 7765, "p": 1300, "spm": 22, "hr": 150}, {"t": 2120, "d": 7869, "p": 1295, "spm": 23, "hr": 150}, {"t": 2147, "d": 7972, "p": 1290, "spm": 22, "hr": 150}, {"t": 2174, "d": 8078, "p": 1288, "spm": 23, "hr": 150}, {"t": 2201, "d": 8182, "p": 1286, "spm": 23, "hr": 150}, {"t": 2226, "d": 8284, "p": 1282, "spm": 22, "hr": 150}, {"t": 2254, "d": 8392, "p": 1279, "spm": 23, "hr": 150}, {"t": 2281, "d": 8496, "p": 1288, "spm": 23, "hr": 151}, {"t": 2307, "d": 8601, "p": 1272, "spm": 22, "hr": 151}, {"t": 2333, "d": 8703, "p": 1272, "spm": 22, "hr": 152}, {"t": 2361, "d": 8811, "p": 1280, "spm": 22, "hr": 152}, {"t": 2388, "d": 8917, "p": 1284, "spm": 23, "hr": 152}, {"t": 2415, "d": 9021, "p": 1293, "spm": 22, "hr": 152}, {"t": 2444, "d": 9131, "p": 1299, "spm": 22, "hr": 152}, {"t": 2472, "d": 9239, "p": 1309, "spm": 22, "hr": 153}, {"t": 2500, "d": 9346, "p": 1307, "spm": 21, "hr": 154}, {"t": 2528, "d": 9454, "p": 1320, "spm": 21, "hr": 154}, {"t": 2556, "d": 9560, "p": 1318, "spm": 21, "hr": 155}, {"t": 2585, "d": 9667, "p": 1326, "spm": 21, "hr": 155}, {"t": 2613, "d": 9774, "p": 1330, "spm": 21, "hr": 156}, {"t": 2641, "d": 9881, "p": 1310, "spm": 21, "hr": 156}, {"t": 2669, "d": 9988, "p": 1316, "spm": 21, "hr": 156}, {"t": 2698, "d": 10096, "p": 1327, "spm": 21, "hr": 156}, {"t": 2727, "d": 10206, "p": 1338, "spm": 21, "hr": 156}, {"t": 2757, "d": 10315, "p": 1345, "spm": 20, "hr": 156}, {"t": 2786, "d": 10425, "p": 1347, "spm": 21, "hr": 156}, {"t": 2815, "d": 10533, "p": 1347, "spm": 20, "hr": 155}, {"t": 2844, "d": 10641, "p": 1339, "spm": 21, "hr": 155}, {"t": 2874, "d": 10753, "p": 1354, "spm": 20, "hr": 155}, {"t": 2904, "d": 10861, "p": 1375, "spm": 20, "hr": 155}, {"t": 2935, "d": 10975, "p": 1359, "spm": 21, "hr": 155}, {"t": 2964, "d": 11085, "p": 1344, "spm": 20, "hr": 155}, {"t": 2993, "d": 11192, "p": 1353, "spm": 20, "hr": 155}, {"t": 3024, "d": 11306, "p": 1353, "spm": 20, "hr": 155}, {"t": 3054, "d": 11413, "p": 1353, "spm": 20, "hr": 155}, {"t": 3083, "d": 11524, "p": 1354, "spm": 21, "hr": 155}, {"t": 3113, "d": 11633, "p": 1367, "spm": 20, "hr": 155}, {"t": 3140, "d": 11738, "p": 1360, "spm": 20, "hr": 154}, {"t": 3170, "d": 11848, "p": 1342, "spm": 21, "hr": 154}, {"t": 3200, "d": 11958, "p": 1343, "spm": 21, "hr": 153}, {"t": 3229, "d": 12066, "p": 1357, "spm": 21, "hr": 152}, {"t": 3259, "d": 12173, "p": 1358, "spm": 21, "hr": 153}, {"t": 3287, "d": 12278, "p": 1363, "spm": 21, "hr": 152}, {"t": 3315, "d": 12387, "p": 1354, "spm": 21, "hr": 152}, {"t": 3345, "d": 12495, "p": 1334, "spm": 21, "hr": 151}, {"t": 3374, "d": 12601, "p": 1359, "spm": 20, "hr": 151}, {"t": 3403, "d": 12709, "p": 1357, "spm": 21, "hr": 151}, {"t": 3432, "d": 12818, "p": 1346, "spm": 21, "hr": 150}, {"t": 3461, "d": 12927, "p": 1355, "spm": 20, "hr": 151}, {"t": 3490, "d": 13034, "p": 1358, "spm": 20, "hr": 151}, {"t": 3519, "d": 13143, "p": 1357, "spm": 21, "hr": 151}, {"t": 3549, "d": 13252, "p": 1343, "spm": 21, "hr": 151}, {"t": 3578, "d": 13361, "p": 1352, "spm": 20, "hr": 152}, {"t": 3607, "d": 13469, "p": 1348, "spm": 21, "hr": 152}, {"t": 3636, "d": 13574, "p": 1358, "spm": 20, "hr": 152}, {"t": 3665, "d": 13681, "p": 1368, "spm": 21, "hr": 152}, {"t": 3694, "d": 13790, "p": 1355, "spm": 20, "hr": 152}, {"t": 3723, "d": 13895, "p": 1346, "spm": 21, "hr": 153}, {"t": 3751, "d": 13999, "p": 1369, "spm": 21, "hr": 152}, {"t": 3780, "d": 14107, "p": 1367, "spm": 20, "hr": 152}, {"t": 3811, "d": 14220, "p": 1364, "spm": 20, "hr": 152}, {"t": 3840, "d": 14328, "p": 1358, "spm": 20, "hr": 151}, {"t": 3869, "d": 14436, "p": 1344, "spm": 21, "hr": 151}, {"t": 3898, "d": 14544, "p": 1353, "spm": 20, "hr": 152}, {"t": 3927, "d": 14651, "p": 1351, "spm": 21, "hr": 151}, {"t": 3956, "d": 14759, "p": 1345, "spm": 21, "hr": 152}, {"t": 3984, "d": 14866, "p": 1336, "spm": 21, "hr": 152}, {"t": 4014, "d": 14974, "p": 1354, "spm": 21, "hr": 153}, {"t": 4043, "d": 15082, "p": 1363, "spm": 20, "hr": 153}, {"t": 4073, "d": 15192, "p": 1350, "spm": 20, "hr": 154}, {"t": 4102, "d": 15300, "p": 1351, "spm": 21, "hr": 154}, {"t": 4131, "d": 15409, "p": 1357, "spm": 20, "hr": 153}, {"t": 4159, "d": 15513, "p": 1351, "spm": 21, "hr": 153}, {"t": 4190, "d": 15626, "p": 1343, "spm": 21, "hr": 153}, {"t": 4219, "d": 15733, "p": 1359, "spm": 20, "hr": 153}, {"t": 4248, "d": 15842, "p": 1364, "spm": 20, "hr": 152}, {"t": 4276, "d": 15946, "p": 1345, "spm": 21, "hr": 152}, {"t": 4307, "d": 16060, "p": 1351, "spm": 21, "hr": 152}, {"t": 4334, "d": 16162, "p": 1369, "spm": 20, "hr": 152}, {"t": 4365, "d": 16274, "p": 1362, "spm": 21, "hr": 152}, {"t": 4394, "d": 16380, "p": 1349, "spm": 21, "hr": 152}, {"t": 4424, "d": 16492, "p": 1353, "spm": 20, "hr": 151}, {"t": 4453, "d": 16602, "p": 1353, "spm": 20, "hr": 152}, {"t": 4482, "d": 16708, "p": 1357, "spm": 20, "hr": 151}, {"t": 4511, "d": 16814, "p": 1361, "spm": 21, "hr": 151}, {"t": 4540, "d": 16921, "p": 1361, "spm": 21, "hr": 151}, {"t": 4568, "d": 17025, "p": 1358, "spm": 21, "hr": 150}, {"t": 4598, "d": 17137, "p": 1349, "spm": 21, "hr": 150}, {"t": 4627, "d": 17244, "p": 1344, "spm": 21, "hr": 150}, {"t": 4656, "d": 17351, "p": 1358, "spm": 20, "hr": 150}, {"t": 4685, "d": 17456, "p": 1361, "spm": 21, "hr": 150}, {"t": 4713, "d": 17563, "p": 1358, "spm": 21, "hr": 150}, {"t": 4740, "d": 17662, "p": 1357, "spm": 20, "hr": 151}, {"t": 4770, "d": 17771, "p": 1369, "spm": 22, "hr": 150}, {"t": 4798, "d": 17875, "p": 1369, "spm": 21, "hr": 150}, {"t": 4826, "d": 17977, "p": 1362, "spm": 22, "hr": 150}, {"t": 4855, "d": 18084, "p": 1361, "spm": 21, "hr": 150}, {"t": 4882, "d": 18184, "p": 1367, "spm": 21, "hr": 149}, {"t": 4910, "d": 18289, "p": 1344, "spm": 22, "hr": 149}, {"t": 4940, "d": 18399, "p": 1356, "spm": 21, "hr": 149}, {"t": 4968, "d": 18505, "p": 1357, "spm": 21, "hr": 148}, {"t": 4997, "d": 18612, "p": 1346, "spm": 21, "hr": 148}, {"t": 5027, "d": 18719, "p": 1354, "spm": 21, "hr": 147}, {"t": 5056, "d": 18826, "p": 1366, "spm": 20, "hr": 147}, {"t": 5084, "d": 18933, "p": 1363, "spm": 20, "hr": 148}, {"t": 5114, "d": 19043, "p": 1348, "spm": 21, "hr": 149}, {"t": 5144, "d": 19154, "p": 1336, "spm": 20, "hr": 149}, {"t": 5174, "d": 19262, "p": 1364, "spm": 20, "hr": 150}, {"t": 5203, "d": 19373, "p": 1361, "spm": 20, "hr": 151}, {"t": 5231, "d": 19478, "p": 1348, "spm": 20, "hr": 152}, {"t": 5262, "d": 19591, "p": 1355, "spm": 20, "hr": 152}, {"t": 5291, "d": 19698, "p": 1361, "spm": 20, "hr": 153}, {"t": 5320, "d": 19806, "p": 1353, "spm": 21, "hr": 153}, {"t": 5349, "d": 19914, "p": 1353, "spm": 21, "hr": 153}, {"t": 5372, "d": 20000, "p": 1340, "spm": 21, "hr": 154}], "workout": {"splits": [{"type": "distance", "time": 1397, "distance": 510, "heart_rate": {"average": 141}, "stroke_rate": 21}, {"type": "distance", "time": 1301, "distance": 499, "heart_rate": {"average": 150}, "stroke_rate": 22}, {"type": "distance", "time": 1344, "distance": 498, "heart_rate": {"average": 152}, "stroke_rate": 20}, {"type": "distance", "time": 1328, "distance": 491, "heart_rate": {"average": 150}, "stroke_rate": 20}]}} +May-21-2021 09:06:14 User 1, C2 ID 33991243 +May-21-2021 09:06:14 {"distance": 13878, "user_id": 457764, "ranked": false, "weight_class": "L", "verified": false, "workout_type": false, "comments": "\n from speedcoach2v2.15 via rowsandall.com", "heart_rate": {"max": 158, "average": 156}, "source": "rowingdata", "date_utc": "2018-06-30 05:31:01", "time_formatted": "1:21:16.7", "time": 48767, "date": "2018-06-30 07:31:01", "timezone": "Europe/Prague", "type": "water", "id": 33991243, "stroke_data": true} +May-21-2021 09:06:14 Time zone Europe/Prague, stardatetime 2018-06-30 06:09:44.300000+02:00, duration 01:21:16.6 +May-21-2021 09:30:31 Upload to C2 user 1 +May-21-2021 09:30:31 {"type": "water", "date": "2016-05-20 13:50:26", "stroke_count": 189, "timezone": "Europe/Amsterdam", "distance": 2000, "time": 5400, "weight_class": "H", "comments": null, "stroke_rate": 21, "drag_factor": 104, "heart_rate": {"average": 148, "max": 156}, "stroke_data": [{"t": 32, "d": 131, "p": 2628, "spm": 19, "hr": 127}, {"t": 32, "d": 131, "p": 2394, "spm": 19, "hr": 127}, {"t": 61, "d": 210, "p": 1991, "spm": 20, "hr": 128}, {"t": 92, "d": 303, "p": 1764, "spm": 20, "hr": 129}, {"t": 121, "d": 390, "p": 1685, "spm": 20, "hr": 130}, {"t": 151, "d": 482, "p": 1639, "spm": 21, "hr": 131}, {"t": 181, "d": 576, "p": 1620, "spm": 20, "hr": 131}, {"t": 209, "d": 664, "p": 1597, "spm": 20, "hr": 132}, {"t": 238, "d": 755, "p": 1601, "spm": 21, "hr": 132}, {"t": 269, "d": 851, "p": 1589, "spm": 20, "hr": 132}, {"t": 296, "d": 950, "p": 1524, "spm": 21, "hr": 132}, {"t": 323, "d": 1050, "p": 1408, "spm": 22, "hr": 133}, {"t": 351, "d": 1153, "p": 1379, "spm": 21, "hr": 134}, {"t": 380, "d": 1258, "p": 1365, "spm": 21, "hr": 135}, {"t": 408, "d": 1366, "p": 1342, "spm": 21, "hr": 136}, {"t": 436, "d": 1472, "p": 1331, "spm": 22, "hr": 137}, {"t": 464, "d": 1576, "p": 1324, "spm": 22, "hr": 139}, {"t": 491, "d": 1678, "p": 1344, "spm": 21, "hr": 140}, {"t": 519, "d": 1785, "p": 1332, "spm": 22, "hr": 140}, {"t": 546, "d": 1885, "p": 1317, "spm": 21, "hr": 141}, {"t": 575, "d": 1993, "p": 1338, "spm": 21, "hr": 141}, {"t": 602, "d": 2094, "p": 1328, "spm": 22, "hr": 142}, {"t": 628, "d": 2194, "p": 1328, "spm": 22, "hr": 142}, {"t": 657, "d": 2302, "p": 1337, "spm": 22, "hr": 143}, {"t": 683, "d": 2402, "p": 1340, "spm": 22, "hr": 144}, {"t": 710, "d": 2501, "p": 1331, "spm": 23, "hr": 145}, {"t": 734, "d": 2596, "p": 1326, "spm": 23, "hr": 145}, {"t": 763, "d": 2703, "p": 1324, "spm": 23, "hr": 145}, {"t": 790, "d": 2806, "p": 1332, "spm": 22, "hr": 145}, {"t": 817, "d": 2907, "p": 1331, "spm": 22, "hr": 144}, {"t": 844, "d": 3008, "p": 1333, "spm": 23, "hr": 145}, {"t": 871, "d": 3111, "p": 1325, "spm": 22, "hr": 145}, {"t": 897, "d": 3212, "p": 1312, "spm": 22, "hr": 145}, {"t": 926, "d": 3319, "p": 1330, "spm": 21, "hr": 145}, {"t": 953, "d": 3420, "p": 1328, "spm": 22, "hr": 146}, {"t": 980, "d": 3524, "p": 1328, "spm": 22, "hr": 146}, {"t": 1008, "d": 3630, "p": 1321, "spm": 22, "hr": 146}, {"t": 1036, "d": 3734, "p": 1324, "spm": 22, "hr": 147}, {"t": 1063, "d": 3839, "p": 1322, "spm": 22, "hr": 147}, {"t": 1092, "d": 3946, "p": 1326, "spm": 22, "hr": 147}, {"t": 1119, "d": 4050, "p": 1335, "spm": 21, "hr": 147}, {"t": 1146, "d": 4153, "p": 1325, "spm": 22, "hr": 148}, {"t": 1176, "d": 4260, "p": 1329, "spm": 22, "hr": 148}, {"t": 1203, "d": 4365, "p": 1333, "spm": 21, "hr": 148}, {"t": 1231, "d": 4469, "p": 1335, "spm": 22, "hr": 148}, {"t": 1256, "d": 4569, "p": 1312, "spm": 22, "hr": 149}, {"t": 1284, "d": 4676, "p": 1316, "spm": 22, "hr": 149}, {"t": 1313, "d": 4785, "p": 1315, "spm": 22, "hr": 150}, {"t": 1341, "d": 4890, "p": 1318, "spm": 21, "hr": 150}, {"t": 1367, "d": 4991, "p": 1336, "spm": 21, "hr": 150}, {"t": 1397, "d": 5100, "p": 1329, "spm": 22, "hr": 150}, {"t": 1423, "d": 5199, "p": 1323, "spm": 22, "hr": 149}, {"t": 1451, "d": 5306, "p": 1327, "spm": 22, "hr": 149}, {"t": 1478, "d": 5408, "p": 1337, "spm": 22, "hr": 149}, {"t": 1505, "d": 5508, "p": 1334, "spm": 22, "hr": 148}, {"t": 1532, "d": 5608, "p": 1348, "spm": 22, "hr": 148}, {"t": 1559, "d": 5710, "p": 1333, "spm": 22, "hr": 147}, {"t": 1584, "d": 5807, "p": 1330, "spm": 22, "hr": 147}, {"t": 1612, "d": 5912, "p": 1329, "spm": 22, "hr": 147}, {"t": 1639, "d": 6014, "p": 1330, "spm": 22, "hr": 147}, {"t": 1666, "d": 6114, "p": 1321, "spm": 23, "hr": 147}, {"t": 1693, "d": 6218, "p": 1328, "spm": 23, "hr": 147}, {"t": 1720, "d": 6321, "p": 1317, "spm": 22, "hr": 147}, {"t": 1747, "d": 6423, "p": 1319, "spm": 22, "hr": 147}, {"t": 1772, "d": 6520, "p": 1310, "spm": 23, "hr": 148}, {"t": 1801, "d": 6627, "p": 1297, "spm": 23, "hr": 148}, {"t": 1826, "d": 6731, "p": 1296, "spm": 23, "hr": 148}, {"t": 1854, "d": 6836, "p": 1295, "spm": 22, "hr": 149}, {"t": 1880, "d": 6938, "p": 1297, "spm": 22, "hr": 149}, {"t": 1905, "d": 7038, "p": 1292, "spm": 22, "hr": 149}, {"t": 1934, "d": 7147, "p": 1297, "spm": 23, "hr": 150}, {"t": 1960, "d": 7249, "p": 1296, "spm": 22, "hr": 150}, {"t": 1987, "d": 7352, "p": 1306, "spm": 23, "hr": 151}, {"t": 2014, "d": 7454, "p": 1307, "spm": 22, "hr": 151}, {"t": 2041, "d": 7560, "p": 1291, "spm": 23, "hr": 151}, {"t": 2067, "d": 7663, "p": 1294, "spm": 22, "hr": 150}, {"t": 2094, "d": 7765, "p": 1300, "spm": 22, "hr": 150}, {"t": 2120, "d": 7869, "p": 1295, "spm": 23, "hr": 150}, {"t": 2147, "d": 7972, "p": 1290, "spm": 22, "hr": 150}, {"t": 2174, "d": 8078, "p": 1288, "spm": 23, "hr": 150}, {"t": 2201, "d": 8182, "p": 1286, "spm": 23, "hr": 150}, {"t": 2226, "d": 8284, "p": 1282, "spm": 22, "hr": 150}, {"t": 2254, "d": 8392, "p": 1279, "spm": 23, "hr": 150}, {"t": 2281, "d": 8496, "p": 1288, "spm": 23, "hr": 151}, {"t": 2307, "d": 8601, "p": 1272, "spm": 22, "hr": 151}, {"t": 2333, "d": 8703, "p": 1272, "spm": 22, "hr": 152}, {"t": 2361, "d": 8811, "p": 1280, "spm": 22, "hr": 152}, {"t": 2388, "d": 8917, "p": 1284, "spm": 23, "hr": 152}, {"t": 2415, "d": 9021, "p": 1293, "spm": 22, "hr": 152}, {"t": 2444, "d": 9131, "p": 1299, "spm": 22, "hr": 152}, {"t": 2472, "d": 9239, "p": 1309, "spm": 22, "hr": 153}, {"t": 2500, "d": 9346, "p": 1307, "spm": 21, "hr": 154}, {"t": 2528, "d": 9454, "p": 1320, "spm": 21, "hr": 154}, {"t": 2556, "d": 9560, "p": 1318, "spm": 21, "hr": 155}, {"t": 2585, "d": 9667, "p": 1326, "spm": 21, "hr": 155}, {"t": 2613, "d": 9774, "p": 1330, "spm": 21, "hr": 156}, {"t": 2641, "d": 9881, "p": 1310, "spm": 21, "hr": 156}, {"t": 2669, "d": 9988, "p": 1316, "spm": 21, "hr": 156}, {"t": 2698, "d": 10096, "p": 1327, "spm": 21, "hr": 156}, {"t": 2727, "d": 10206, "p": 1338, "spm": 21, "hr": 156}, {"t": 2757, "d": 10315, "p": 1345, "spm": 20, "hr": 156}, {"t": 2786, "d": 10425, "p": 1347, "spm": 21, "hr": 156}, {"t": 2815, "d": 10533, "p": 1347, "spm": 20, "hr": 155}, {"t": 2844, "d": 10641, "p": 1339, "spm": 21, "hr": 155}, {"t": 2874, "d": 10753, "p": 1354, "spm": 20, "hr": 155}, {"t": 2904, "d": 10861, "p": 1375, "spm": 20, "hr": 155}, {"t": 2935, "d": 10975, "p": 1359, "spm": 21, "hr": 155}, {"t": 2964, "d": 11085, "p": 1344, "spm": 20, "hr": 155}, {"t": 2993, "d": 11192, "p": 1353, "spm": 20, "hr": 155}, {"t": 3024, "d": 11306, "p": 1353, "spm": 20, "hr": 155}, {"t": 3054, "d": 11413, "p": 1353, "spm": 20, "hr": 155}, {"t": 3083, "d": 11524, "p": 1354, "spm": 21, "hr": 155}, {"t": 3113, "d": 11633, "p": 1367, "spm": 20, "hr": 155}, {"t": 3140, "d": 11738, "p": 1360, "spm": 20, "hr": 154}, {"t": 3170, "d": 11848, "p": 1342, "spm": 21, "hr": 154}, {"t": 3200, "d": 11958, "p": 1343, "spm": 21, "hr": 153}, {"t": 3229, "d": 12066, "p": 1357, "spm": 21, "hr": 152}, {"t": 3259, "d": 12173, "p": 1358, "spm": 21, "hr": 153}, {"t": 3287, "d": 12278, "p": 1363, "spm": 21, "hr": 152}, {"t": 3315, "d": 12387, "p": 1354, "spm": 21, "hr": 152}, {"t": 3345, "d": 12495, "p": 1334, "spm": 21, "hr": 151}, {"t": 3374, "d": 12601, "p": 1359, "spm": 20, "hr": 151}, {"t": 3403, "d": 12709, "p": 1357, "spm": 21, "hr": 151}, {"t": 3432, "d": 12818, "p": 1346, "spm": 21, "hr": 150}, {"t": 3461, "d": 12927, "p": 1355, "spm": 20, "hr": 151}, {"t": 3490, "d": 13034, "p": 1358, "spm": 20, "hr": 151}, {"t": 3519, "d": 13143, "p": 1357, "spm": 21, "hr": 151}, {"t": 3549, "d": 13252, "p": 1343, "spm": 21, "hr": 151}, {"t": 3578, "d": 13361, "p": 1352, "spm": 20, "hr": 152}, {"t": 3607, "d": 13469, "p": 1348, "spm": 21, "hr": 152}, {"t": 3636, "d": 13574, "p": 1358, "spm": 20, "hr": 152}, {"t": 3665, "d": 13681, "p": 1368, "spm": 21, "hr": 152}, {"t": 3694, "d": 13790, "p": 1355, "spm": 20, "hr": 152}, {"t": 3723, "d": 13895, "p": 1346, "spm": 21, "hr": 153}, {"t": 3751, "d": 13999, "p": 1369, "spm": 21, "hr": 152}, {"t": 3780, "d": 14107, "p": 1367, "spm": 20, "hr": 152}, {"t": 3811, "d": 14220, "p": 1364, "spm": 20, "hr": 152}, {"t": 3840, "d": 14328, "p": 1358, "spm": 20, "hr": 151}, {"t": 3869, "d": 14436, "p": 1344, "spm": 21, "hr": 151}, {"t": 3898, "d": 14544, "p": 1353, "spm": 20, "hr": 152}, {"t": 3927, "d": 14651, "p": 1351, "spm": 21, "hr": 151}, {"t": 3956, "d": 14759, "p": 1345, "spm": 21, "hr": 152}, {"t": 3984, "d": 14866, "p": 1336, "spm": 21, "hr": 152}, {"t": 4014, "d": 14974, "p": 1354, "spm": 21, "hr": 153}, {"t": 4043, "d": 15082, "p": 1363, "spm": 20, "hr": 153}, {"t": 4073, "d": 15192, "p": 1350, "spm": 20, "hr": 154}, {"t": 4102, "d": 15300, "p": 1351, "spm": 21, "hr": 154}, {"t": 4131, "d": 15409, "p": 1357, "spm": 20, "hr": 153}, {"t": 4159, "d": 15513, "p": 1351, "spm": 21, "hr": 153}, {"t": 4190, "d": 15626, "p": 1343, "spm": 21, "hr": 153}, {"t": 4219, "d": 15733, "p": 1359, "spm": 20, "hr": 153}, {"t": 4248, "d": 15842, "p": 1364, "spm": 20, "hr": 152}, {"t": 4276, "d": 15946, "p": 1345, "spm": 21, "hr": 152}, {"t": 4307, "d": 16060, "p": 1351, "spm": 21, "hr": 152}, {"t": 4334, "d": 16162, "p": 1369, "spm": 20, "hr": 152}, {"t": 4365, "d": 16274, "p": 1362, "spm": 21, "hr": 152}, {"t": 4394, "d": 16380, "p": 1349, "spm": 21, "hr": 152}, {"t": 4424, "d": 16492, "p": 1353, "spm": 20, "hr": 151}, {"t": 4453, "d": 16602, "p": 1353, "spm": 20, "hr": 152}, {"t": 4482, "d": 16708, "p": 1357, "spm": 20, "hr": 151}, {"t": 4511, "d": 16814, "p": 1361, "spm": 21, "hr": 151}, {"t": 4540, "d": 16921, "p": 1361, "spm": 21, "hr": 151}, {"t": 4568, "d": 17025, "p": 1358, "spm": 21, "hr": 150}, {"t": 4598, "d": 17137, "p": 1349, "spm": 21, "hr": 150}, {"t": 4627, "d": 17244, "p": 1344, "spm": 21, "hr": 150}, {"t": 4656, "d": 17351, "p": 1358, "spm": 20, "hr": 150}, {"t": 4685, "d": 17456, "p": 1361, "spm": 21, "hr": 150}, {"t": 4713, "d": 17563, "p": 1358, "spm": 21, "hr": 150}, {"t": 4740, "d": 17662, "p": 1357, "spm": 20, "hr": 151}, {"t": 4770, "d": 17771, "p": 1369, "spm": 22, "hr": 150}, {"t": 4798, "d": 17875, "p": 1369, "spm": 21, "hr": 150}, {"t": 4826, "d": 17977, "p": 1362, "spm": 22, "hr": 150}, {"t": 4855, "d": 18084, "p": 1361, "spm": 21, "hr": 150}, {"t": 4882, "d": 18184, "p": 1367, "spm": 21, "hr": 149}, {"t": 4910, "d": 18289, "p": 1344, "spm": 22, "hr": 149}, {"t": 4940, "d": 18399, "p": 1356, "spm": 21, "hr": 149}, {"t": 4968, "d": 18505, "p": 1357, "spm": 21, "hr": 148}, {"t": 4997, "d": 18612, "p": 1346, "spm": 21, "hr": 148}, {"t": 5027, "d": 18719, "p": 1354, "spm": 21, "hr": 147}, {"t": 5056, "d": 18826, "p": 1366, "spm": 20, "hr": 147}, {"t": 5084, "d": 18933, "p": 1363, "spm": 20, "hr": 148}, {"t": 5114, "d": 19043, "p": 1348, "spm": 21, "hr": 149}, {"t": 5144, "d": 19154, "p": 1336, "spm": 20, "hr": 149}, {"t": 5174, "d": 19262, "p": 1364, "spm": 20, "hr": 150}, {"t": 5203, "d": 19373, "p": 1361, "spm": 20, "hr": 151}, {"t": 5231, "d": 19478, "p": 1348, "spm": 20, "hr": 152}, {"t": 5262, "d": 19591, "p": 1355, "spm": 20, "hr": 152}, {"t": 5291, "d": 19698, "p": 1361, "spm": 20, "hr": 153}, {"t": 5320, "d": 19806, "p": 1353, "spm": 21, "hr": 153}, {"t": 5349, "d": 19914, "p": 1353, "spm": 21, "hr": 153}, {"t": 5372, "d": 20000, "p": 1340, "spm": 21, "hr": 154}], "workout": {"splits": [{"type": "distance", "time": 1397, "distance": 510, "heart_rate": {"average": 141}, "stroke_rate": 21}, {"type": "distance", "time": 1301, "distance": 499, "heart_rate": {"average": 150}, "stroke_rate": 22}, {"type": "distance", "time": 1344, "distance": 498, "heart_rate": {"average": 152}, "stroke_rate": 20}, {"type": "distance", "time": 1328, "distance": 491, "heart_rate": {"average": 150}, "stroke_rate": 20}]}} +May-21-2021 09:30:32 User 1, C2 ID 33991243 +May-21-2021 09:30:32 {"distance": 13878, "user_id": 457764, "ranked": false, "weight_class": "L", "verified": false, "workout_type": false, "comments": "\n from speedcoach2v2.15 via rowsandall.com", "heart_rate": {"max": 158, "average": 156}, "source": "rowingdata", "date_utc": "2018-06-30 05:31:01", "time_formatted": "1:21:16.7", "time": 48767, "date": "2018-06-30 07:31:01", "timezone": "Europe/Prague", "type": "water", "id": 33991243, "stroke_data": true} +May-21-2021 09:30:32 Time zone Europe/Prague, stardatetime 2018-06-30 06:09:44.300000+02:00, duration 01:21:16.6 \ No newline at end of file diff --git a/rowers/admin.py b/rowers/admin.py index 5c179e88..46ee9a17 100644 --- a/rowers/admin.py +++ b/rowers/admin.py @@ -46,7 +46,6 @@ class RowerInline(admin.StackedInline): 'sporttrackstoken','sporttrackstokenexpirydate', 'sporttracksrefreshtoken', 'sporttracks_auto_export', - 'mapmyfitness_auto_export', 'tptoken','tptokenexpirydate','tprefreshtoken', 'trainingpeaks_auto_export', 'polartoken','polartokenexpirydate', @@ -55,7 +54,6 @@ class RowerInline(admin.StackedInline): 'stravatoken','stravatokenexpirydate','stravarefreshtoken', 'stravaexportas','strava_auto_export', 'strava_auto_import', - 'runkeepertoken','runkeeper_auto_export', 'garmintoken','garminrefreshtoken')}), ('Team', {'fields':('friends','privacy','team')}), diff --git a/rowers/c2stuff.py b/rowers/c2stuff.py index e533a713..02cf4410 100644 --- a/rowers/c2stuff.py +++ b/rowers/c2stuff.py @@ -825,14 +825,9 @@ def make_authorization_url(request): # pragma: no cover return HttpResponseRedirect(url) # Get workout from C2 ID -def get_workout(user,c2id,do_async=False): +def get_workout(user,c2id,do_async=True): r = Rower.objects.get(user=user) - if (r.c2token == '') or (r.c2token is None): # pragma: no cover - s = "Token doesn't exist. Need to authorize" - return custom_exception_handler(401,s) ,0 - elif (timezone.now()>r.tokenexpirydate): - s = "Token expired. Needs to refresh." - return custom_exception_handler(401,s),0 + thetoken = c2_open(user) job = myqueue(queuehigh, handle_c2_getworkout, diff --git a/rowers/models.py b/rowers/models.py index 7b72f243..fc6150e0 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -988,7 +988,6 @@ class Rower(models.Model): sporttracksrefreshtoken = models.CharField(default='',max_length=200, blank=True,null=True) sporttracks_auto_export = models.BooleanField(default=False) - mapmyfitness_auto_export = models.BooleanField(default=False) tptoken = models.CharField(default='',max_length=1000,blank=True,null=True) tptokenexpirydate = models.DateTimeField(blank=True,null=True) tprefreshtoken = models.CharField(default='',max_length=1000, @@ -1037,9 +1036,6 @@ class Rower(models.Model): strava_auto_export = models.BooleanField(default=False) strava_auto_import = models.BooleanField(default=False) strava_auto_delete = models.BooleanField(default=False) - runkeepertoken = models.CharField(default='',max_length=200, - blank=True,null=True) - runkeeper_auto_export = models.BooleanField(default=False) privacychoices = ( @@ -3198,7 +3194,6 @@ class Workout(models.Model): uploadedtostrava = models.BigIntegerField(default=0) uploadedtosporttracks = models.BigIntegerField(default=0) uploadedtotp = models.BigIntegerField(default=0) - uploadedtorunkeeper = models.BigIntegerField(default=0) uploadedtogarmin = models.BigIntegerField(default=0) uploadedtorp3 = models.BigIntegerField(default=0) uploadedtonk = models.BigIntegerField(default=0) @@ -3279,7 +3274,6 @@ class TombStone(models.Model): uploadedtostrava = models.BigIntegerField(default=0) uploadedtosporttracks = models.BigIntegerField(default=0) uploadedtotp = models.BigIntegerField(default=0) - uploadedtorunkeeper = models.BigIntegerField(default=0) uploadedtonk = models.BigIntegerField(default=0) @receiver(models.signals.pre_delete,sender=Workout) @@ -3289,7 +3283,6 @@ def create_tombstone_on_delete(sender, instance, **kwargs): uploadedtoc2 = instance.uploadedtoc2, uploadedtostrava = instance.uploadedtostrava, uploadedtotp = instance.uploadedtotp, - uploadedtorunkeeper = instance.uploadedtorunkeeper, uploadedtonk = instance.uploadedtonk ) t.save() @@ -3864,8 +3857,6 @@ class RowerExportForm(ModelForm): 'c2_auto_export', 'c2_auto_import', 'nk_auto_import', - 'mapmyfitness_auto_export', - 'runkeeper_auto_export', 'sporttracks_auto_export', 'strava_auto_export', 'strava_auto_import', @@ -4208,8 +4199,6 @@ class RowerImportExportForm(ModelForm): 'polar_auto_import', 'c2_auto_export', 'c2_auto_import', - 'mapmyfitness_auto_export', - 'runkeeper_auto_export', 'sporttracks_auto_export', 'strava_auto_export', 'strava_auto_import', diff --git a/rowers/runkeeperstuff.py b/rowers/runkeeperstuff.py deleted file mode 100644 index cc3b6998..00000000 --- a/rowers/runkeeperstuff.py +++ /dev/null @@ -1,530 +0,0 @@ -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals -from __future__ import unicode_literals, absolute_import -# All the functionality needed to connect to Runkeeper -from rowers.imports import * -import re - -import django_rq -queue = django_rq.get_queue('default') -queuelow = django_rq.get_queue('low') -queuehigh = django_rq.get_queue('low') -from rowers.utils import myqueue - -from rowers.rower_rules import is_workout_user - -from rowsandall_app.settings import ( - C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET, - STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, STRAVA_CLIENT_SECRET, - RUNKEEPER_CLIENT_ID, RUNKEEPER_CLIENT_SECRET,RUNKEEPER_REDIRECT_URI, - ) - -from rowers.tasks import handle_runkeeper_sync - -oauth_data = { - 'client_id': RUNKEEPER_CLIENT_ID, - 'client_secret': RUNKEEPER_CLIENT_SECRET, - 'redirect_uri': RUNKEEPER_REDIRECT_URI, - 'autorization_uri': "https://www.runkeeper.com/apps/authorize", - 'content_type': 'application/x-www-form-urlencoded', - 'tokenname': 'runkeepertoken', - 'refreshtokenname': None, - 'expirydatename': None, - 'bearer_auth': True, - 'base_url': "https://runkeeper.com/apps/token", - 'headers': {'user-agent': 'sanderroosendaal'}, - 'scope':'write', - } - - -import numpy - -def splitrunkeeperlatlongdata(lijst,tname,latname,lonname): - t = [] - lat = [] - lon = [] - for d in lijst: - t.append(d[tname]) - lat.append(d[latname]) - lon.append(d[lonname]) - - return [np.array(t),np.array(lat),np.array(lon)] - -def splitrunkeeperdata(lijst,xname,yname): - x = [] - y = [] - for d in lijst: - x.append(d[xname]) - y.append(d[yname]) - - return [np.array(x),np.array(y)] - - -# Checks if user has SportTracks token, renews them if they are expired -def runkeeper_open(user): - return imports_open(user,oauth_data) - -# Exchange access code for long-lived access token -def get_token(code): - return imports_get_token(code,oauth_data) - -# Make authorization URL including random string -def make_authorization_url(request): # pragma: no cover - return imports_make_authorization_url(oauth_data) - -# Get list of workouts available on Runkeeper -def get_runkeeper_workout_list(user): - r = Rower.objects.get(user=user) - if (r.runkeepertoken == '') or (r.runkeepertoken is None): - s = "Token doesn't exist. Need to authorize" - return custom_exception_handler(401,s) - else: - # ready to fetch. Hurray - authorizationstring = str('Bearer ' + r.runkeepertoken) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - url = "https://api.runkeeper.com/fitnessActivities" - s = requests.get(url,headers=headers) - - return s - -# Get workout summary data by Runkeeper ID -def get_workout(user,runkeeperid,do_async=False): - r = Rower.objects.get(user=user) - if (r.runkeepertoken == '') or (r.runkeepertoken is None): # pragma: no cover - return custom_exception_handler(401,s) - s = "Token doesn't exist. Need to authorize" - else: - # ready to fetch. Hurray - authorizationstring = str('Bearer ' + r.runkeepertoken) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - url = "https://api.runkeeper.com/fitnessActivities/"+str(runkeeperid) - s = requests.get(url,headers=headers) - - try: - data = s.json() - except ValueError: # pragma: no cover - data = {} - return data,"Something went wrong with the workout import" - - strokedata = pd.DataFrame.from_dict({ - key: pd.Series(value) for key, value in data.items() - }) - - return data,strokedata - -# Create Workout Data for upload to SportTracks -def createrunkeeperworkoutdata(w): - filename = w.csvfilename - try: - row = rowingdata(csvfile=filename) - except: # pragma: no cover - return 0 - - try: - averagehr = int(row.df[' HRCur (bpm)'].mean()) - maxhr = int(row.df[' HRCur (bpm)'].max()) - except KeyError: # pragma: no cover - averagehr = 0 - maxhr = 0 - - duration = w.duration.hour*3600 - duration += w.duration.minute*60 - duration += w.duration.second - duration += +1.0e-6*w.duration.microsecond - - try: - t = row.df.loc[:,'TimeStamp (sec)'].values-row.df.loc[:,'TimeStamp (sec)'].iloc[0] - except KeyError: # pragma: no cover - return pd.DataFrame() - - t[0] = t[1] - - d = row.df.loc[:,'cum_dist'].values - d[0] = d[1] - t = t.astype(int) - d = d.astype(int) - spm = row.df[' Cadence (stokes/min)'].astype(int) - spm[0] = spm[1] - hr = row.df[' HRCur (bpm)'].astype(int) - - haslatlon=1 - - try: - lat = row.df[' latitude'].values - lon = row.df[' longitude'].values - if not lat.std() and not lon.std(): # pragma: no cover - haslatlon = 0 - except KeyError: # pragma: no cover - haslatlon = 0 - - t = t.tolist() - hr = hr.tolist() - d = d.tolist() - - # path data - if haslatlon: - lat = lat.tolist() - lon = lon.tolist() - locdata = [] - for e in zip(t,lat,lon): - point = {'timestamp':e[0], - 'latitude':e[1], - 'longitude':e[2], - 'altitude':0, - "type":"gps"} - locdata.append(point) - - hrdata = [] - for e in zip(t,hr): - point = {'timestamp':e[0], - 'heart_rate':e[1] - } - hrdata.append(point) - - distancedata = [] - for e in zip(t,d): - point = {'timestamp':e[0], - 'distance':e[1] - } - distancedata.append(point) - - st = w.startdatetime.astimezone(pytz.timezone(w.timezone)) - start_time = st.strftime("%a, %d %b %Y %H:%M:%S") - - try: - newnotes = w.notes+'\n from '+w.workoutsource+' via rowsandall.com' - except TypeError: - newnotes = 'from '+w.workoutsource+' via rowsandall.com' - - if haslatlon: - data = { - "type": "Rowing", - "start_time": start_time, - "total_distance": int(w.distance), - "duration": duration, - "notes": newnotes, - "average_heart_rate": averagehr, - "path": locdata, - "distance": distancedata, - "heart_rate": hrdata, - "post_to_twitter":"false", - "post_to_facebook":"false", - } - else: - data = { - "type": "Rowing", - "start_time": start_time, - "total_distance": int(w.distance), - "duration": duration, - "notes": newnotes, - "avg_heartrate": averagehr, - "distance": distancedata, - "heart_rate": hrdata, - "post_to_twitter":"false", - "post_to_facebook":"false", - } - - - return data - -# Obtain Runkeeper Workout ID from the response returned on successful -# upload -def getidfromresponse(response): - uri = response.headers["Location"] - - tester = re.compile('^\/fitnessActivities\/(\d+)$') - id = int(tester.match(uri).group(1)) - - return int(id) - -def geturifromid(access_token,id): # pragma: no cover - authorizationstring = str('Bearer ' + access_token) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - import urllib - url = "https://api.runkeeper.com/fitnessActivities/"+str(id) - response = requests.get(url,headers=headers) - try: - me_json = response.json() - except: - return '' - - try: - res = me_json['uri'] - except KeyError: - res = '' - - return res - - -# Get user id, having access token -# Handy for checking if the API access is working -def get_userid(access_token): - authorizationstring = str('Bearer ' + access_token) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - import urllib - url = "https://api.runkeeper.com/user" - response = requests.get(url,headers=headers) - - - try: - me_json = response.json() - except: # pragma: no cover - return '' - - try: - res = me_json['userID'] - except KeyError: # pragma: no cover - res = '' - - return str(res) - -def default(o): # pragma: no cover - if isinstance(o, numpy.int64): return int(o) - raise TypeError - -def workout_runkeeper_upload(user,w,asynchron=False): # pragma: no cover - message = "Uploading to Runkeeper" - rkid = 0 - - r = w.user - - - thetoken = runkeeper_open(r.user) - - # ready to upload. Hurray - - if (is_workout_user(user,w)): - data = createrunkeeperworkoutdata(w) - if not data: - message = "Data error in Runkeeper Upload" - rkid = 0 - return message, rkid - - authorizationstring = str('Bearer ' + thetoken) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/vnd.com.runkeeper.NewFitnessActivity+json', - 'Content-Length':'nnn'} - - url = "https://api.runkeeper.com/fitnessActivities" - if asynchron: - job = myqueue(queue,handle_runkeeper_sync, - w.id,url,headers,json.dumps(data,default=default)) - return "Asynchronous sync",0 - response = requests.post(url,headers=headers,data=json.dumps(data,default=default)) - - # check for duplicate error first - if (response.status_code == 409 ): - message = "Duplicate error" - w.uploadedtorunkeeper = -1 - rkid = -1 - w.save() - return message, rkid - elif (response.status_code == 201 or response.status_code==200): - rkid = getidfromresponse(response) - rkuri = geturifromid(thetoken,rkid) - w.uploadedtorunkeeper = rkid - w.save() - return 'Successfully synchronized to Runkeeper',rkid - else: - s = response - message = "Something went wrong in workout_runkeeper_upload_view: %s - %s" % (s.reason,s.text) - rkid = 0 - return message, rkid - - else: - message = "You are not authorized to upload this workout" - rkid = 0 - return message, rkid - - return message,rkid - -# Create workout from RunKeeper Data -def add_workout_from_data(user,importid,data,strokedata,source='runkeeper', - workoutsource='runkeeper'): - # To Do - add utcoffset to time - workouttype = data['type'] - if workouttype not in [x[0] for x in Workout.workouttypes]: - workouttype = 'other' - try: - comments = data['notes'] - except: # pragma: no cover - comments = '' - - try: - utcoffset = tz(data['utcoffset']) - except: - utcoffset = 0 - - r = Rower.objects.get(user=user) - - try: - rowdatetime = iso8601.parse_date(data['start_time']) - except iso8601.ParseError: - try: # pragma: no cover - rowdatetime = datetime.strptime(data['start_time'],"%Y-%m-%d %H:%M:%S") - rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) - except ValueError: - try: - rowdatetime = parser.parse(data['start_time']) - #rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) - except: # pragma: no cover - rowdatetime = datetime.strptime(data['date'],"%Y-%m-%d %H:%M:%S") - rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) - starttimeunix = arrow.get(rowdatetime).timestamp() - #starttimeunix = mktime(rowdatetime.utctimetuple()) - starttimeunix += utcoffset*3600 - - - try: - title = data['name'] - except: - title = "Imported data" - - - - res = splitrunkeeperdata(data['distance'],'timestamp','distance') - - distance = res[1] - times_distance = res[0] - - try: - l = data['path'] - - res = splitrunkeeperlatlongdata(l,'timestamp','latitude','longitude') - times_location = res[0] - latcoord = res[1] - loncoord = res[2] - - except: # pragma: no cover - times_location = times_distance - latcoord = np.zeros(len(times_distance)) - loncoord = np.zeros(len(times_distance)) - if workouttype in types.otwtypes: - workouttype = 'rower' - - try: # pragma: no cover - res = splitrunkeeperdata(data['cadence'],'timestamp','cadence') - times_spm = res[0] - spm = res[1] - except KeyError: - times_spm = times_distance - spm = 0*times_distance - - try: - res = splitrunkeeperdata(data['heart_rate'],'timestamp','heart_rate') - hr = res[1] - times_hr = res[0] - except KeyError: # pragma: no cover - times_hr = times_distance - hr = 0*times_distance - - - # create data series and remove duplicates - distseries = pd.Series(distance,index=times_distance) - distseries = distseries.groupby(distseries.index).first() - latseries = pd.Series(latcoord,index=times_location) - try: - latseries = latseries.groupby(latseries.index).first() - except TypeError: # pragma: no cover - latseries = 0.0*distseries - - lonseries = pd.Series(loncoord,index=times_location) - try: - lonseries = lonseries.groupby(lonseries.index).first() - except TypeError: # pragma: no cover - lonseries = 0.0*distseries - - spmseries = pd.Series(spm,index=times_spm) - spmseries = spmseries.groupby(spmseries.index).first() - hrseries = pd.Series(hr,index=times_hr) - try: - hrseries = hrseries.groupby(hrseries.index).first() - except TypeError: # pragma: no cover - hrseries = 0*distseries - - - # Create dicts and big dataframe - d = { - ' Horizontal (meters)': distseries, - ' latitude': latseries, - ' longitude': lonseries, - ' Cadence (stokes/min)': spmseries, - ' HRCur (bpm)' : hrseries, - } - - - - df = pd.DataFrame(d) - - df = df.groupby(level=0).last() - - cum_time = df.index.values - df[' ElapsedTime (sec)'] = cum_time - - velo = df[' Horizontal (meters)'].diff()/df[' ElapsedTime (sec)'].diff() - - df[' Power (watts)'] = 0.0*velo - - nr_rows = len(velo.values) - - df[' DriveLength (meters)'] = np.zeros(nr_rows) - df[' StrokeDistance (meters)'] = np.zeros(nr_rows) - df[' DriveTime (ms)'] = np.zeros(nr_rows) - df[' StrokeRecoveryTime (ms)'] = np.zeros(nr_rows) - df[' AverageDriveForce (lbs)'] = np.zeros(nr_rows) - df[' PeakDriveForce (lbs)'] = np.zeros(nr_rows) - df[' lapIdx'] = np.zeros(nr_rows) - - - - unixtime = cum_time+starttimeunix - try: - unixtime[0] = starttimeunix - except IndexError: # pragma: no cover - return (0,'No data to import') - - df['TimeStamp (sec)'] = unixtime - - - dt = np.diff(cum_time).mean() - wsize = round(5./dt) - - # velo2 = stravastuff.ewmovingaverage(velo,wsize) - - # df[' Stroke500mPace (sec/500m)'] = 500./velo2 - - - df = df.fillna(0) - - df.sort_values(by='TimeStamp (sec)',ascending=True) - - timestr = strftime("%Y%m%d-%H%M%S") - -# csvfilename ='media/Import_'+str(importid)+'.csv' - csvfilename ='media/{code}_{importid}.csv'.format( - importid=importid, - code = uuid4().hex[:16] - ) - - res = df.to_csv(csvfilename+'.gz',index_label='index', - compression='gzip') - - id,message = dataprep.save_workout_database(csvfilename,r, - workouttype=workouttype, - workoutsource='runkeeper', - title=title, - dosmooth=r.dosmooth, - notes=comments) - - return (id,message) diff --git a/rowers/sporttracksstuff.py b/rowers/sporttracksstuff.py index 09c54675..56ce890e 100644 --- a/rowers/sporttracksstuff.py +++ b/rowers/sporttracksstuff.py @@ -120,7 +120,14 @@ def get_workout(user,sporttracksid,do_async=False): key: pd.Series(value) for key, value in data.items() }) - return data,strokedata + id,message = add_workout_from_data( + user, + sporttracksid,data, + strokedata, + source='sporttracks', + workoutsource='sporttracks') + + return id # Create Workout Data for upload to SportTracks def createsporttracksworkoutdata(w): diff --git a/rowers/tasks.py b/rowers/tasks.py index df1a1c5d..35293887 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -25,7 +25,6 @@ from rowingdata import rowingdata as rdata from datetime import timedelta from sqlalchemy import create_engine -from rowers.imports import splituadata #from celery import app from rowers.celery import app diff --git a/rowers/templates/menu_workout.html b/rowers/templates/menu_workout.html index 2b77156f..1a10cc85 100644 --- a/rowers/templates/menu_workout.html +++ b/rowers/templates/menu_workout.html @@ -192,21 +192,6 @@ {% endif %} -
  • - {% if workout.uploadedtorunkeeper %} - - Runkeeper - - {% elif user.rower.runkeepertoken == None or user.rower.runkeepertoken == '' %} - - Connect to Runkeeper - - {% else %} - - Runkeeper - - {% endif %} -
  • {% if workout.uploadedtotp %} diff --git a/rowers/templates/menu_workouts.html b/rowers/templates/menu_workouts.html index 82045548..4d0e2d02 100644 --- a/rowers/templates/menu_workouts.html +++ b/rowers/templates/menu_workouts.html @@ -40,7 +40,6 @@
  • Concept2
  • Strava
  • -
  • RunKeeper
  • SportTracks
  • Polar
  • RP3
  • diff --git a/rowers/templates/rower_exportsettings.html b/rowers/templates/rower_exportsettings.html index d6aabe5d..7f77f1d2 100644 --- a/rowers/templates/rower_exportsettings.html +++ b/rowers/templates/rower_exportsettings.html @@ -29,9 +29,6 @@ {% if rower.stravatoken is not None and rower.stravatoken != '' %} Strava, {% endif %} - {% if rower.runkeepertoken is not None and rower.runkeepertoken != '' %} - Runkeeper, - {% endif %} {% if rower.rp3token is not None and rower.rp3token != '' %} RP3 {% endif %} @@ -76,7 +73,6 @@

    connect with Concept2

    connect with NK Logbook

    connect with SportTracks

    -

    connect with RunKeeper

    connect with Polar

    \d+)/',views.workout_polarimport_view,name='workout_polarimport_view'), - re_path(r'^workout/runkeeperimport/$',views.workout_runkeeperimport_view,name='workout_runkeeperimport_view'), - re_path(r'^workout/runkeeperimport/user/(?P\d+)/$',views.workout_runkeeperimport_view,name='workout_runkeeperimport_view'), re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/c2uploadw/$',views.workout_c2_upload_view,name='workout_c2_upload_view'), re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/stravauploadw/$',views.workout_strava_upload_view,name='workout_strava_upload_view'), re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/recalcsummary/$',views.workout_recalcsummary_view,name='workout_recalcsummary_view'), re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/sporttracksuploadw/$',views.workout_sporttracks_upload_view,name='workout_sporttracks_upload_view'), - re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/runkeeperuploadw/$',views.workout_runkeeper_upload_view,name='workout_runkeeper_upload_view'), re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/tpuploadw/$',views.workout_tp_upload_view,name='workout_tp_upload_view'), re_path(r'^multi-compare/workout/(?P\b[0-9A-Fa-f]+\b)/user/(?P\d+)/$',views.multi_compare_view, name='multi_compare_view'), @@ -599,7 +596,6 @@ urlpatterns = [ re_path(r'^me/sporttracksauthorize/$',views.rower_sporttracks_authorize,name='rower_sporttracks_authorize'), re_path(r'^me/tpauthorize/$',views.rower_tp_authorize,name='rower_tp_authorize'), re_path(r'^me/rp3authorize/$',views.rower_rp3_authorize,name='rower_rp3_authorize'), - re_path(r'^me/runkeeperauthorize/$',views.rower_runkeeper_authorize,name='rower_runkeeper_authorize'), re_path(r'^me/sporttracksrefresh/$',views.rower_sporttracks_token_refresh,name='rower_sporttracks_token_refresh'), re_path(r'^me/tprefresh/$',views.rower_tp_token_refresh,name='rower_tp_token_refresh'), re_path(r'^me/c2refresh/$',views.rower_c2_token_refresh,name='rower_c2_token_refresh'), diff --git a/rowers/utils.py b/rowers/utils.py index 2722def7..bd24e3f6 100644 --- a/rowers/utils.py +++ b/rowers/utils.py @@ -15,7 +15,7 @@ import uuid import datetime import json - +import time from fitparse import FitFile from django.conf import settings diff --git a/rowers/views/importviews.py b/rowers/views/importviews.py index c1740e50..7fd0d483 100644 --- a/rowers/views/importviews.py +++ b/rowers/views/importviews.py @@ -225,67 +225,6 @@ def workout_c2_upload_view(request,id=0): return response -# Upload workout to RunKeeper -@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True) -def workout_runkeeper_upload_view(request,id=0): - message = "" - w = get_workout(id) - r = w.user - - try: - thetoken = runkeeper_open(r.user) - except NoTokenError: # pragma: no cover - return HttpResponseRedirect("/rowers/me/runkeeperauthorize/") - - # ready to upload. Hurray - - - data = runkeeperstuff.createrunkeeperworkoutdata(w) - if not data: # pragma: no cover - message = "Data error" - messages.error(request,message) - url = reverse(r.defaultlandingpage, - kwargs = { - 'id':id, - }) - return HttpResponseRedirect(url) - - authorizationstring = str('Bearer ' + thetoken) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/vnd.com.runkeeper.NewFitnessActivity+json', - 'Content-Length':'nnn'} - - url = "https://api.runkeeper.com/fitnessActivities" - response = requests.post(url,headers=headers,data=json.dumps(data,default=default)) - - # check for duplicate error first - if (response.status_code == 409 ): # pragma: no cover # pragma: no cover - message = "Duplicate error" - messages.error(request,message) - w.uploadedtorunkeeper = -1 - w.save() - elif (response.status_code == 201 or response.status_code==200): - runkeeperid = runkeeperstuff.getidfromresponse(response) - w.uploadedtorunkeeper = runkeeperid - w.save() - url = reverse('workout_edit_view', - kwargs={'id':encoder.encode_hex(w.id)}) - - return HttpResponseRedirect(url) - else: # pragma: no cover - s = response - message = "Something went wrong in workout_runkeeper_upload_view: %s - %s" % (s.reason,s.text) - messages.error(request,message) - - - url = reverse(r.defaultlandingpage, - kwargs = { - 'id':encoder.encode_hex(w.id), - }) # pragma: no cover - - return HttpResponseRedirect(url) # pragma: no cover - # Upload workout to SportTracks @permission_required('workout.change_workout',fn=get_workout_by_opaqueid) @@ -384,6 +323,7 @@ def rower_c2_authorize(request): # pragma: no cover "redirect_uri": C2_REDIRECT_URI} url = "http://log.concept2.com/oauth/authorize?"+ urllib.parse.urlencode(params) url += "&scope="+scope + return HttpResponseRedirect(url) # Garmin authorization @@ -429,23 +369,6 @@ def rower_polar_authorize(request): # pragma: no cover -# Runkeeper authorization -@login_required() -def rower_runkeeper_authorize(request): # pragma: no cover - # Generate a random string for the state parameter - # Save it for use later to prevent xsrf attacks - - state = str(uuid4()) - - params = {"client_id": RUNKEEPER_CLIENT_ID, - "response_type": "code", - "state": state, - "redirect_uri": RUNKEEPER_REDIRECT_URI} - - url = "https://runkeeper.com/apps/authorize?"+ urllib.parse.urlencode(params) - - - return HttpResponseRedirect(url) # SportTracks Authorization @login_required() @@ -923,31 +846,6 @@ def rower_process_stravacallback(request): return HttpResponseRedirect(url) -# Process Runkeeper callback -@login_required() -def rower_process_runkeepercallback(request): - code = request.GET['code'] - res = runkeeperstuff.get_token(code) - access_token = res[0] - - if access_token == 0:# pragma: no cover - messages.error(request,"Something went wrong importing the token") - url = reverse('workouts_view') - - return HttpResponseRedirect(url) - - - - r = getrower(request.user) - r.runkeepertoken = access_token - - r.save() - - successmessage = "Tokens stored. Good to go. Please check your import/export settings" - messages.info(request,successmessage) - url = reverse('rower_exportsettings_view') - return HttpResponseRedirect(url) - # Process SportTracks callback @@ -1498,61 +1396,6 @@ def garmin_details_view(request): return HttpResponse(status=200) -# The page where you select which RunKeeper workout to import -@login_required() -@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True) -def workout_runkeeperimport_view(request,message="",userid=0): - res = runkeeperstuff.get_runkeeper_workout_list(request.user) - if (res.status_code != 200): - if (res.status_code == 401): - r = getrower(request.user) - if (r.runkeepertoken == '') or (r.runkeepertoken is None): - s = "Token doesn't exist. Need to authorize" - return HttpResponseRedirect("/rowers/me/runkeeperauthorize/") - message = "Something went wrong in workout_runkeeperimport_view" # pragma: no cover - messages.error(request,message) # pragma: no cover - - if settings.DEBUG: # pragma: no cover - return HttpResponse(res) - else: # pragma: no cover - url = reverse('workouts_view') - return HttpResponseRedirect(url) - - workouts = [] - for item in res.json()['items']: - d = int(float(item['total_distance'])) - i = getidfromuri(item['uri']) - ttot = str(datetime.timedelta(seconds=int(float(item['duration'])))) - s = item['start_time'] - r = item['type'] - keys = ['id','distance','duration','starttime','type'] - values = [i,d,ttot,s,r] - - res = dict(zip(keys,values)) - workouts.append(res) - - breadcrumbs = [ - { - 'url':'/rowers/list-workouts/', - 'name':'Workouts' - }, - { - 'url':reverse('workout_runkeeperimport_view'), - 'name':'Runkeeper' - } - ] - - r = getrower(request.user) - - return render(request,'runkeeper_list_import.html', - {'workouts':workouts, - 'rower':r, - 'active':'nav-workouts', - 'breadcrumbs':breadcrumbs, - 'teams':get_my_teams(request.user), - }) - - return HttpResponse(res) # pragma: no cover # the page where you select which Polar workout to Import @@ -1853,18 +1696,26 @@ importlistviews = { 'strava':'workout_stravaimport_view', 'polar':'workout_polarimport_view', 'ownapi':'workout_view', - 'runkeeper':'workout_runkeeperimport_view', 'sporttracks':'workout_sporttracksimport_view', 'trainingpeaks':'workout_view', 'nk':'workout_nkimport_view', } +importauthorizeviews = { + 'c2':'rower_c2_authorize', + 'strava':'rower_strava_authorize', + 'polar':'rower_polar_authorize', + 'ownapi':'workout_view', + 'sporttracks':'rower_sporttracks_authorize', + 'trainingpeaks':'rower_tp_authorize', + 'nk':'rower_nk_authorize', +} + importsources = { 'c2':c2stuff, 'strava':stravastuff, 'polar':polarstuff, 'ownapi':ownapistuff, - 'runkeeper':runkeeperstuff, 'sporttracks':sporttracksstuff, 'trainingpeaks':tpstuff, 'nk':nkstuff, @@ -1894,8 +1745,12 @@ def workout_getrp3importview(request,externalid): @login_required() def workout_getimportview(request,externalid,source = 'c2',do_async=True): - result = importsources[source].get_workout(request.user,externalid, - do_async=do_async) + try: + result = importsources[source].get_workout(request.user,externalid, + do_async=do_async) + except NoTokenError: + + return HttpResponseRedirect(reverse(importauthorizeviews[source])) if result: # pragma: no cover messages.info(request,"Your workout will be imported in the background") @@ -1919,14 +1774,11 @@ def workout_getsporttracksworkout_all(request): ]) newids = [stid for stid in stids if not stid in knownstids] for sporttracksid in newids: - data,strokedata = sporttracksstuff.get_workout( + id = sporttracksstuff.get_workout( request.user,sporttracksid) - id,message = sporttracksstuff.add_workout_from_data( - request.user,sporttracksid,data,strokedata - ) if id==0: # pragma: no cover - messages.error(request,message) + messages.error(request,"Something went wrong with workout {id}".format(id=sporttracksid)) else: w = Workout.objects.get(id=id) diff --git a/rowers/views/statements.py b/rowers/views/statements.py index 4b8c9ff1..db7dc791 100644 --- a/rowers/views/statements.py +++ b/rowers/views/statements.py @@ -158,7 +158,6 @@ import rowers.nkstuff as nkstuff from rowers.c2stuff import c2_open from rowers.nkstuff import nk_open from rowers.rp3stuff import rp3_open -from rowers.runkeeperstuff import runkeeper_open from rowers.sporttracksstuff import sporttracks_open from rowers.tpstuff import tp_open from iso8601 import ParseError @@ -170,7 +169,6 @@ import rowers.sporttracksstuff as sporttracksstuff import rowers.tpstuff as tpstuff -import rowers.runkeeperstuff as runkeeperstuff import rowers.rp3stuff as rp3stuff import rowers.ownapistuff as ownapistuff from rowers.ownapistuff import TEST_CLIENT_ID, TEST_CLIENT_SECRET, TEST_REDIRECT_URI @@ -180,7 +178,6 @@ from rowsandall_app.settings import ( POLAR_CLIENT_ID, POLAR_REDIRECT_URI, POLAR_CLIENT_SECRET, SPORTTRACKS_CLIENT_ID, SPORTTRACKS_REDIRECT_URI, SPORTTRACKS_CLIENT_SECRET, - RUNKEEPER_CLIENT_ID,RUNKEEPER_REDIRECT_URI,RUNKEEPER_CLIENT_SECRET, TP_CLIENT_ID,TP_REDIRECT_URI,TP_CLIENT_KEY,TP_CLIENT_SECRET, RP3_CLIENT_ID,RP3_REDIRECT_URI,RP3_CLIENT_KEY,RP3_CLIENT_SECRET, BRAINTREE_MERCHANT_ID,BRAINTREE_PUBLIC_KEY,BRAINTREE_PRIVATE_KEY, diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py index 8f23454d..394d10f1 100644 --- a/rowers/views/workoutviews.py +++ b/rowers/views/workoutviews.py @@ -4864,8 +4864,6 @@ def workout_upload_api(request): upload_to_c2 = optionsform.cleaned_data['upload_to_C2'] upload_to_strava = optionsform.cleaned_data['upload_to_Strava'] upload_to_st = optionsform.cleaned_data['upload_to_SportTracks'] - upload_to_rk = optionsform.cleaned_data['upload_to_RunKeeper'] - upload_to_ua = optionsform.cleaned_data['upload_to_MapMyFitness'] upload_to_tp = optionsform.cleaned_data['upload_to_TrainingPeaks'] makeprivate = optionsform.cleaned_data['makeprivate'] else: # pragma: no cover @@ -5042,8 +5040,6 @@ def workout_upload_view(request, upload_to_c2 = uploadoptions.get('upload_to_C2',False) upload_to_strava = uploadoptions.get('upload_to_Strava',False) upload_to_st = uploadoptions.get('upload_to_SportTracks',False) - upload_to_rk = uploadoptions.get('upload_to_RunKeeper',False) - upload_to_ua = uploadoptions.get('upload_to_MapMyFitness',False) upload_to_tp = uploadoptions.get('upload_to_TrainingPeaks',False) response = {} @@ -5093,8 +5089,6 @@ def workout_upload_view(request, upload_to_c2 = optionsform.cleaned_data['upload_to_C2'] upload_to_strava = optionsform.cleaned_data['upload_to_Strava'] upload_to_st = optionsform.cleaned_data['upload_to_SportTracks'] - upload_to_rk = optionsform.cleaned_data['upload_to_RunKeeper'] - upload_to_ua = optionsform.cleaned_data['upload_to_MapMyFitness'] upload_to_tp = optionsform.cleaned_data['upload_to_TrainingPeaks'] makeprivate = optionsform.cleaned_data['makeprivate'] landingpage = optionsform.cleaned_data['landingpage'] @@ -5112,8 +5106,6 @@ def workout_upload_view(request, 'upload_to_C2':upload_to_c2, 'upload_to_Strava':upload_to_strava, 'upload_to_SportTracks':upload_to_st, - 'upload_to_RunKeeper':upload_to_rk, - 'upload_to_MapMyFitness':upload_to_ua, 'upload_to_TrainingPeaks':upload_to_tp, 'landingpage':landingpage, 'boattype': boattype, @@ -5255,20 +5247,6 @@ def workout_upload_view(request, else: messages.error(request,message) - if (upload_to_rk): # pragma: no cover - try: - message,id = runkeeperstuff.workout_runkeeper_upload( - request.user,w - ) - except NoTokenError: - message = "Please connect to Runkeeper first" - id = 0 - - if id>1: - messages.info(request,message) - else: - messages.error(request,message) - if (upload_to_tp): # pragma: no cover try: @@ -5447,14 +5425,9 @@ def workout_upload_view(request, if r.sporttracks_auto_export and ispromember(r.user): # pragma: no cover uploadoptions['upload_to_SportTracks'] = True - if r.runkeeper_auto_export and ispromember(r.user): # pragma: no cover - uploadoptions['upload_to_RunKeeper'] = True - if r.trainingpeaks_auto_export and ispromember(r.user): # pragma: no cover uploadoptions['upload_to_TrainingPeaks'] = True - if r.mapmyfitness_auto_export and ispromember(r.user): # pragma: no cover - uploadoptions['upload_to_MapMyFitness'] = True form = DocumentsForm(initial=docformoptions) optionsform = UploadOptionsForm(initial=uploadoptions, diff --git a/rowsandall_app/urls.py b/rowsandall_app/urls.py index 6cf79af8..db752767 100644 --- a/rowsandall_app/urls.py +++ b/rowsandall_app/urls.py @@ -75,7 +75,6 @@ urlpatterns += [ re_path(r'^garmin\_callback',rowersviews.rower_process_garmincallback), re_path(r'^sporttracks\_callback',rowersviews.rower_process_sporttrackscallback), re_path(r'^polarflowcallback',rowersviews.rower_process_polarcallback), - re_path(r'^runkeeper\_callback',rowersviews.rower_process_runkeepercallback), re_path(r'^tp\_callback',rowersviews.rower_process_tpcallback), re_path(r'^rp3\_callback',rowersviews.rower_process_rp3callback), re_path(r'^twitter\_callback',rowersviews.rower_process_twittercallback), From d6fc68021860123b04f25a41378187898638faee Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Fri, 21 May 2021 11:37:37 +0200 Subject: [PATCH 03/12] updated import tests --- rowers/tests/test_imports.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/rowers/tests/test_imports.py b/rowers/tests/test_imports.py index 089d7ddc..260e8c97 100644 --- a/rowers/tests/test_imports.py +++ b/rowers/tests/test_imports.py @@ -326,9 +326,10 @@ class C2Objects(DjangoTestCase): def test_c2_import_tz(self, mock_get, mocked_sqlalchemy): response = self.c.get('/rowers/workout/c2import/22/',follow=True) + expected_url = '/rower/workout/c2list/' self.assertRedirects(response, - expected_url='/rowers/workout/'+encoded2+'/edit/', + expected_url=expected_url, status_code=302,target_status_code=200) self.assertEqual(response.status_code, 200) @@ -342,9 +343,10 @@ class C2Objects(DjangoTestCase): def test_c2_import_tz3(self, mock_get, mocked_sqlalchemy): response = self.c.get('/rowers/workout/c2import/32/',follow=True) + expected_url = '/rower/workout/c2list/' self.assertRedirects(response, - expected_url='/rowers/workout/'+encoded2+'/edit/', + expected_url=expected_url, status_code=302,target_status_code=200) self.assertEqual(response.status_code, 200) @@ -357,9 +359,10 @@ class C2Objects(DjangoTestCase): def test_c2_import_tz2(self, mock_get, mocked_sqlalchemy): response = self.c.get('/rowers/workout/c2import/31/',follow=True) + expected_url = '/rower/workout/c2list/' self.assertRedirects(response, - expected_url='/rowers/workout/'+encoded2+'/edit/', + expected_url=expected_url, status_code=302,target_status_code=200) self.assertEqual(response.status_code, 200) From 199bc47a957168cac9a6aff6066b200ad4234bcc Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Fri, 21 May 2021 11:38:03 +0200 Subject: [PATCH 04/12] typo fix --- rowers/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rowers/utils.py b/rowers/utils.py index bd24e3f6..e9781a8a 100644 --- a/rowers/utils.py +++ b/rowers/utils.py @@ -108,7 +108,7 @@ import random def dologging(filename,s): tstamp = time.localtime() timestamp = time.strftime('%b-%d-%Y %H:%M:%S', tstamp) - with open('filename','a') as f: + with open(filename,'a') as f: f.write('\n') f.write(timestamp) f.write(' ') From bc5ad4109d0320226bb7e757d1c9e39106d83ab4 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Fri, 21 May 2021 14:17:50 +0200 Subject: [PATCH 05/12] passing tests --- filename | 7 +- rowers/mytypes.py | 34 ---------- rowers/stravastuff.py | 113 +------------------------------ rowers/tasks.py | 37 ++-------- rowers/tests/mocks.py | 10 +++ rowers/tests/test_async_tasks.py | 20 +----- rowers/tests/test_imports.py | 31 ++++++--- rowers/tests/viewnames.csv | 9 --- rowers/utils.py | 39 +++++++++++ 9 files changed, 84 insertions(+), 216 deletions(-) diff --git a/filename b/filename index c4492c6b..5fa57cea 100644 --- a/filename +++ b/filename @@ -26,4 +26,9 @@ May-21-2021 09:30:31 Upload to C2 user 1 May-21-2021 09:30:31 {"type": "water", "date": "2016-05-20 13:50:26", "stroke_count": 189, "timezone": "Europe/Amsterdam", "distance": 2000, "time": 5400, "weight_class": "H", "comments": null, "stroke_rate": 21, "drag_factor": 104, "heart_rate": {"average": 148, "max": 156}, "stroke_data": [{"t": 32, "d": 131, "p": 2628, "spm": 19, "hr": 127}, {"t": 32, "d": 131, "p": 2394, "spm": 19, "hr": 127}, {"t": 61, "d": 210, "p": 1991, "spm": 20, "hr": 128}, {"t": 92, "d": 303, "p": 1764, "spm": 20, "hr": 129}, {"t": 121, "d": 390, "p": 1685, "spm": 20, "hr": 130}, {"t": 151, "d": 482, "p": 1639, "spm": 21, "hr": 131}, {"t": 181, "d": 576, "p": 1620, "spm": 20, "hr": 131}, {"t": 209, "d": 664, "p": 1597, "spm": 20, "hr": 132}, {"t": 238, "d": 755, "p": 1601, "spm": 21, "hr": 132}, {"t": 269, "d": 851, "p": 1589, "spm": 20, "hr": 132}, {"t": 296, "d": 950, "p": 1524, "spm": 21, "hr": 132}, {"t": 323, "d": 1050, "p": 1408, "spm": 22, "hr": 133}, {"t": 351, "d": 1153, "p": 1379, "spm": 21, "hr": 134}, {"t": 380, "d": 1258, "p": 1365, "spm": 21, "hr": 135}, {"t": 408, "d": 1366, "p": 1342, "spm": 21, "hr": 136}, {"t": 436, "d": 1472, "p": 1331, "spm": 22, "hr": 137}, {"t": 464, "d": 1576, "p": 1324, "spm": 22, "hr": 139}, {"t": 491, "d": 1678, "p": 1344, "spm": 21, "hr": 140}, {"t": 519, "d": 1785, "p": 1332, "spm": 22, "hr": 140}, {"t": 546, "d": 1885, "p": 1317, "spm": 21, "hr": 141}, {"t": 575, "d": 1993, "p": 1338, "spm": 21, "hr": 141}, {"t": 602, "d": 2094, "p": 1328, "spm": 22, "hr": 142}, {"t": 628, "d": 2194, "p": 1328, "spm": 22, "hr": 142}, {"t": 657, "d": 2302, "p": 1337, "spm": 22, "hr": 143}, {"t": 683, "d": 2402, "p": 1340, "spm": 22, "hr": 144}, {"t": 710, "d": 2501, "p": 1331, "spm": 23, "hr": 145}, {"t": 734, "d": 2596, "p": 1326, "spm": 23, "hr": 145}, {"t": 763, "d": 2703, "p": 1324, "spm": 23, "hr": 145}, {"t": 790, "d": 2806, "p": 1332, "spm": 22, "hr": 145}, {"t": 817, "d": 2907, "p": 1331, "spm": 22, "hr": 144}, {"t": 844, "d": 3008, "p": 1333, "spm": 23, "hr": 145}, {"t": 871, "d": 3111, "p": 1325, "spm": 22, "hr": 145}, {"t": 897, "d": 3212, "p": 1312, "spm": 22, "hr": 145}, {"t": 926, "d": 3319, "p": 1330, "spm": 21, "hr": 145}, {"t": 953, "d": 3420, "p": 1328, "spm": 22, "hr": 146}, {"t": 980, "d": 3524, "p": 1328, "spm": 22, "hr": 146}, {"t": 1008, "d": 3630, "p": 1321, "spm": 22, "hr": 146}, {"t": 1036, "d": 3734, "p": 1324, "spm": 22, "hr": 147}, {"t": 1063, "d": 3839, "p": 1322, "spm": 22, "hr": 147}, {"t": 1092, "d": 3946, "p": 1326, "spm": 22, "hr": 147}, {"t": 1119, "d": 4050, "p": 1335, "spm": 21, "hr": 147}, {"t": 1146, "d": 4153, "p": 1325, "spm": 22, "hr": 148}, {"t": 1176, "d": 4260, "p": 1329, "spm": 22, "hr": 148}, {"t": 1203, "d": 4365, "p": 1333, "spm": 21, "hr": 148}, {"t": 1231, "d": 4469, "p": 1335, "spm": 22, "hr": 148}, {"t": 1256, "d": 4569, "p": 1312, "spm": 22, "hr": 149}, {"t": 1284, "d": 4676, "p": 1316, "spm": 22, "hr": 149}, {"t": 1313, "d": 4785, "p": 1315, "spm": 22, "hr": 150}, {"t": 1341, "d": 4890, "p": 1318, "spm": 21, "hr": 150}, {"t": 1367, "d": 4991, "p": 1336, "spm": 21, "hr": 150}, {"t": 1397, "d": 5100, "p": 1329, "spm": 22, "hr": 150}, {"t": 1423, "d": 5199, "p": 1323, "spm": 22, "hr": 149}, {"t": 1451, "d": 5306, "p": 1327, "spm": 22, "hr": 149}, {"t": 1478, "d": 5408, "p": 1337, "spm": 22, "hr": 149}, {"t": 1505, "d": 5508, "p": 1334, "spm": 22, "hr": 148}, {"t": 1532, "d": 5608, "p": 1348, "spm": 22, "hr": 148}, {"t": 1559, "d": 5710, "p": 1333, "spm": 22, "hr": 147}, {"t": 1584, "d": 5807, "p": 1330, "spm": 22, "hr": 147}, {"t": 1612, "d": 5912, "p": 1329, "spm": 22, "hr": 147}, {"t": 1639, "d": 6014, "p": 1330, "spm": 22, "hr": 147}, {"t": 1666, "d": 6114, "p": 1321, "spm": 23, "hr": 147}, {"t": 1693, "d": 6218, "p": 1328, "spm": 23, "hr": 147}, {"t": 1720, "d": 6321, "p": 1317, "spm": 22, "hr": 147}, {"t": 1747, "d": 6423, "p": 1319, "spm": 22, "hr": 147}, {"t": 1772, "d": 6520, "p": 1310, "spm": 23, "hr": 148}, {"t": 1801, "d": 6627, "p": 1297, "spm": 23, "hr": 148}, {"t": 1826, "d": 6731, "p": 1296, "spm": 23, "hr": 148}, {"t": 1854, "d": 6836, "p": 1295, "spm": 22, "hr": 149}, {"t": 1880, "d": 6938, "p": 1297, "spm": 22, "hr": 149}, {"t": 1905, "d": 7038, "p": 1292, "spm": 22, "hr": 149}, {"t": 1934, "d": 7147, "p": 1297, "spm": 23, "hr": 150}, {"t": 1960, "d": 7249, "p": 1296, "spm": 22, "hr": 150}, {"t": 1987, "d": 7352, "p": 1306, "spm": 23, "hr": 151}, {"t": 2014, "d": 7454, "p": 1307, "spm": 22, "hr": 151}, {"t": 2041, "d": 7560, "p": 1291, "spm": 23, "hr": 151}, {"t": 2067, "d": 7663, "p": 1294, "spm": 22, "hr": 150}, {"t": 2094, "d": 7765, "p": 1300, "spm": 22, "hr": 150}, {"t": 2120, "d": 7869, "p": 1295, "spm": 23, "hr": 150}, {"t": 2147, "d": 7972, "p": 1290, "spm": 22, "hr": 150}, {"t": 2174, "d": 8078, "p": 1288, "spm": 23, "hr": 150}, {"t": 2201, "d": 8182, "p": 1286, "spm": 23, "hr": 150}, {"t": 2226, "d": 8284, "p": 1282, "spm": 22, "hr": 150}, {"t": 2254, "d": 8392, "p": 1279, "spm": 23, "hr": 150}, {"t": 2281, "d": 8496, "p": 1288, "spm": 23, "hr": 151}, {"t": 2307, "d": 8601, "p": 1272, "spm": 22, "hr": 151}, {"t": 2333, "d": 8703, "p": 1272, "spm": 22, "hr": 152}, {"t": 2361, "d": 8811, "p": 1280, "spm": 22, "hr": 152}, {"t": 2388, "d": 8917, "p": 1284, "spm": 23, "hr": 152}, {"t": 2415, "d": 9021, "p": 1293, "spm": 22, "hr": 152}, {"t": 2444, "d": 9131, "p": 1299, "spm": 22, "hr": 152}, {"t": 2472, "d": 9239, "p": 1309, "spm": 22, "hr": 153}, {"t": 2500, "d": 9346, "p": 1307, "spm": 21, "hr": 154}, {"t": 2528, "d": 9454, "p": 1320, "spm": 21, "hr": 154}, {"t": 2556, "d": 9560, "p": 1318, "spm": 21, "hr": 155}, {"t": 2585, "d": 9667, "p": 1326, "spm": 21, "hr": 155}, {"t": 2613, "d": 9774, "p": 1330, "spm": 21, "hr": 156}, {"t": 2641, "d": 9881, "p": 1310, "spm": 21, "hr": 156}, {"t": 2669, "d": 9988, "p": 1316, "spm": 21, "hr": 156}, {"t": 2698, "d": 10096, "p": 1327, "spm": 21, "hr": 156}, {"t": 2727, "d": 10206, "p": 1338, "spm": 21, "hr": 156}, {"t": 2757, "d": 10315, "p": 1345, "spm": 20, "hr": 156}, {"t": 2786, "d": 10425, "p": 1347, "spm": 21, "hr": 156}, {"t": 2815, "d": 10533, "p": 1347, "spm": 20, "hr": 155}, {"t": 2844, "d": 10641, "p": 1339, "spm": 21, "hr": 155}, {"t": 2874, "d": 10753, "p": 1354, "spm": 20, "hr": 155}, {"t": 2904, "d": 10861, "p": 1375, "spm": 20, "hr": 155}, {"t": 2935, "d": 10975, "p": 1359, "spm": 21, "hr": 155}, {"t": 2964, "d": 11085, "p": 1344, "spm": 20, "hr": 155}, {"t": 2993, "d": 11192, "p": 1353, "spm": 20, "hr": 155}, {"t": 3024, "d": 11306, "p": 1353, "spm": 20, "hr": 155}, {"t": 3054, "d": 11413, "p": 1353, "spm": 20, "hr": 155}, {"t": 3083, "d": 11524, "p": 1354, "spm": 21, "hr": 155}, {"t": 3113, "d": 11633, "p": 1367, "spm": 20, "hr": 155}, {"t": 3140, "d": 11738, "p": 1360, "spm": 20, "hr": 154}, {"t": 3170, "d": 11848, "p": 1342, "spm": 21, "hr": 154}, {"t": 3200, "d": 11958, "p": 1343, "spm": 21, "hr": 153}, {"t": 3229, "d": 12066, "p": 1357, "spm": 21, "hr": 152}, {"t": 3259, "d": 12173, "p": 1358, "spm": 21, "hr": 153}, {"t": 3287, "d": 12278, "p": 1363, "spm": 21, "hr": 152}, {"t": 3315, "d": 12387, "p": 1354, "spm": 21, "hr": 152}, {"t": 3345, "d": 12495, "p": 1334, "spm": 21, "hr": 151}, {"t": 3374, "d": 12601, "p": 1359, "spm": 20, "hr": 151}, {"t": 3403, "d": 12709, "p": 1357, "spm": 21, "hr": 151}, {"t": 3432, "d": 12818, "p": 1346, "spm": 21, "hr": 150}, {"t": 3461, "d": 12927, "p": 1355, "spm": 20, "hr": 151}, {"t": 3490, "d": 13034, "p": 1358, "spm": 20, "hr": 151}, {"t": 3519, "d": 13143, "p": 1357, "spm": 21, "hr": 151}, {"t": 3549, "d": 13252, "p": 1343, "spm": 21, "hr": 151}, {"t": 3578, "d": 13361, "p": 1352, "spm": 20, "hr": 152}, {"t": 3607, "d": 13469, "p": 1348, "spm": 21, "hr": 152}, {"t": 3636, "d": 13574, "p": 1358, "spm": 20, "hr": 152}, {"t": 3665, "d": 13681, "p": 1368, "spm": 21, "hr": 152}, {"t": 3694, "d": 13790, "p": 1355, "spm": 20, "hr": 152}, {"t": 3723, "d": 13895, "p": 1346, "spm": 21, "hr": 153}, {"t": 3751, "d": 13999, "p": 1369, "spm": 21, "hr": 152}, {"t": 3780, "d": 14107, "p": 1367, "spm": 20, "hr": 152}, {"t": 3811, "d": 14220, "p": 1364, "spm": 20, "hr": 152}, {"t": 3840, "d": 14328, "p": 1358, "spm": 20, "hr": 151}, {"t": 3869, "d": 14436, "p": 1344, "spm": 21, "hr": 151}, {"t": 3898, "d": 14544, "p": 1353, "spm": 20, "hr": 152}, {"t": 3927, "d": 14651, "p": 1351, "spm": 21, "hr": 151}, {"t": 3956, "d": 14759, "p": 1345, "spm": 21, "hr": 152}, {"t": 3984, "d": 14866, "p": 1336, "spm": 21, "hr": 152}, {"t": 4014, "d": 14974, "p": 1354, "spm": 21, "hr": 153}, {"t": 4043, "d": 15082, "p": 1363, "spm": 20, "hr": 153}, {"t": 4073, "d": 15192, "p": 1350, "spm": 20, "hr": 154}, {"t": 4102, "d": 15300, "p": 1351, "spm": 21, "hr": 154}, {"t": 4131, "d": 15409, "p": 1357, "spm": 20, "hr": 153}, {"t": 4159, "d": 15513, "p": 1351, "spm": 21, "hr": 153}, {"t": 4190, "d": 15626, "p": 1343, "spm": 21, "hr": 153}, {"t": 4219, "d": 15733, "p": 1359, "spm": 20, "hr": 153}, {"t": 4248, "d": 15842, "p": 1364, "spm": 20, "hr": 152}, {"t": 4276, "d": 15946, "p": 1345, "spm": 21, "hr": 152}, {"t": 4307, "d": 16060, "p": 1351, "spm": 21, "hr": 152}, {"t": 4334, "d": 16162, "p": 1369, "spm": 20, "hr": 152}, {"t": 4365, "d": 16274, "p": 1362, "spm": 21, "hr": 152}, {"t": 4394, "d": 16380, "p": 1349, "spm": 21, "hr": 152}, {"t": 4424, "d": 16492, "p": 1353, "spm": 20, "hr": 151}, {"t": 4453, "d": 16602, "p": 1353, "spm": 20, "hr": 152}, {"t": 4482, "d": 16708, "p": 1357, "spm": 20, "hr": 151}, {"t": 4511, "d": 16814, "p": 1361, "spm": 21, "hr": 151}, {"t": 4540, "d": 16921, "p": 1361, "spm": 21, "hr": 151}, {"t": 4568, "d": 17025, "p": 1358, "spm": 21, "hr": 150}, {"t": 4598, "d": 17137, "p": 1349, "spm": 21, "hr": 150}, {"t": 4627, "d": 17244, "p": 1344, "spm": 21, "hr": 150}, {"t": 4656, "d": 17351, "p": 1358, "spm": 20, "hr": 150}, {"t": 4685, "d": 17456, "p": 1361, "spm": 21, "hr": 150}, {"t": 4713, "d": 17563, "p": 1358, "spm": 21, "hr": 150}, {"t": 4740, "d": 17662, "p": 1357, "spm": 20, "hr": 151}, {"t": 4770, "d": 17771, "p": 1369, "spm": 22, "hr": 150}, {"t": 4798, "d": 17875, "p": 1369, "spm": 21, "hr": 150}, {"t": 4826, "d": 17977, "p": 1362, "spm": 22, "hr": 150}, {"t": 4855, "d": 18084, "p": 1361, "spm": 21, "hr": 150}, {"t": 4882, "d": 18184, "p": 1367, "spm": 21, "hr": 149}, {"t": 4910, "d": 18289, "p": 1344, "spm": 22, "hr": 149}, {"t": 4940, "d": 18399, "p": 1356, "spm": 21, "hr": 149}, {"t": 4968, "d": 18505, "p": 1357, "spm": 21, "hr": 148}, {"t": 4997, "d": 18612, "p": 1346, "spm": 21, "hr": 148}, {"t": 5027, "d": 18719, "p": 1354, "spm": 21, "hr": 147}, {"t": 5056, "d": 18826, "p": 1366, "spm": 20, "hr": 147}, {"t": 5084, "d": 18933, "p": 1363, "spm": 20, "hr": 148}, {"t": 5114, "d": 19043, "p": 1348, "spm": 21, "hr": 149}, {"t": 5144, "d": 19154, "p": 1336, "spm": 20, "hr": 149}, {"t": 5174, "d": 19262, "p": 1364, "spm": 20, "hr": 150}, {"t": 5203, "d": 19373, "p": 1361, "spm": 20, "hr": 151}, {"t": 5231, "d": 19478, "p": 1348, "spm": 20, "hr": 152}, {"t": 5262, "d": 19591, "p": 1355, "spm": 20, "hr": 152}, {"t": 5291, "d": 19698, "p": 1361, "spm": 20, "hr": 153}, {"t": 5320, "d": 19806, "p": 1353, "spm": 21, "hr": 153}, {"t": 5349, "d": 19914, "p": 1353, "spm": 21, "hr": 153}, {"t": 5372, "d": 20000, "p": 1340, "spm": 21, "hr": 154}], "workout": {"splits": [{"type": "distance", "time": 1397, "distance": 510, "heart_rate": {"average": 141}, "stroke_rate": 21}, {"type": "distance", "time": 1301, "distance": 499, "heart_rate": {"average": 150}, "stroke_rate": 22}, {"type": "distance", "time": 1344, "distance": 498, "heart_rate": {"average": 152}, "stroke_rate": 20}, {"type": "distance", "time": 1328, "distance": 491, "heart_rate": {"average": 150}, "stroke_rate": 20}]}} May-21-2021 09:30:32 User 1, C2 ID 33991243 May-21-2021 09:30:32 {"distance": 13878, "user_id": 457764, "ranked": false, "weight_class": "L", "verified": false, "workout_type": false, "comments": "\n from speedcoach2v2.15 via rowsandall.com", "heart_rate": {"max": 158, "average": 156}, "source": "rowingdata", "date_utc": "2018-06-30 05:31:01", "time_formatted": "1:21:16.7", "time": 48767, "date": "2018-06-30 07:31:01", "timezone": "Europe/Prague", "type": "water", "id": 33991243, "stroke_data": true} -May-21-2021 09:30:32 Time zone Europe/Prague, stardatetime 2018-06-30 06:09:44.300000+02:00, duration 01:21:16.6 \ No newline at end of file +May-21-2021 09:30:32 Time zone Europe/Prague, stardatetime 2018-06-30 06:09:44.300000+02:00, duration 01:21:16.6 +May-21-2021 09:40:10 Upload to C2 user 1 +May-21-2021 09:40:10 {"type": "water", "date": "2016-05-20 13:50:26", "stroke_count": 189, "timezone": "Europe/Amsterdam", "distance": 2000, "time": 5400, "weight_class": "H", "comments": null, "stroke_rate": 21, "drag_factor": 104, "heart_rate": {"average": 148, "max": 156}, "stroke_data": [{"t": 32, "d": 131, "p": 2628, "spm": 19, "hr": 127}, {"t": 32, "d": 131, "p": 2394, "spm": 19, "hr": 127}, {"t": 61, "d": 210, "p": 1991, "spm": 20, "hr": 128}, {"t": 92, "d": 303, "p": 1764, "spm": 20, "hr": 129}, {"t": 121, "d": 390, "p": 1685, "spm": 20, "hr": 130}, {"t": 151, "d": 482, "p": 1639, "spm": 21, "hr": 131}, {"t": 181, "d": 576, "p": 1620, "spm": 20, "hr": 131}, {"t": 209, "d": 664, "p": 1597, "spm": 20, "hr": 132}, {"t": 238, "d": 755, "p": 1601, "spm": 21, "hr": 132}, {"t": 269, "d": 851, "p": 1589, "spm": 20, "hr": 132}, {"t": 296, "d": 950, "p": 1524, "spm": 21, "hr": 132}, {"t": 323, "d": 1050, "p": 1408, "spm": 22, "hr": 133}, {"t": 351, "d": 1153, "p": 1379, "spm": 21, "hr": 134}, {"t": 380, "d": 1258, "p": 1365, "spm": 21, "hr": 135}, {"t": 408, "d": 1366, "p": 1342, "spm": 21, "hr": 136}, {"t": 436, "d": 1472, "p": 1331, "spm": 22, "hr": 137}, {"t": 464, "d": 1576, "p": 1324, "spm": 22, "hr": 139}, {"t": 491, "d": 1678, "p": 1344, "spm": 21, "hr": 140}, {"t": 519, "d": 1785, "p": 1332, "spm": 22, "hr": 140}, {"t": 546, "d": 1885, "p": 1317, "spm": 21, "hr": 141}, {"t": 575, "d": 1993, "p": 1338, "spm": 21, "hr": 141}, {"t": 602, "d": 2094, "p": 1328, "spm": 22, "hr": 142}, {"t": 628, "d": 2194, "p": 1328, "spm": 22, "hr": 142}, {"t": 657, "d": 2302, "p": 1337, "spm": 22, "hr": 143}, {"t": 683, "d": 2402, "p": 1340, "spm": 22, "hr": 144}, {"t": 710, "d": 2501, "p": 1331, "spm": 23, "hr": 145}, {"t": 734, "d": 2596, "p": 1326, "spm": 23, "hr": 145}, {"t": 763, "d": 2703, "p": 1324, "spm": 23, "hr": 145}, {"t": 790, "d": 2806, "p": 1332, "spm": 22, "hr": 145}, {"t": 817, "d": 2907, "p": 1331, "spm": 22, "hr": 144}, {"t": 844, "d": 3008, "p": 1333, "spm": 23, "hr": 145}, {"t": 871, "d": 3111, "p": 1325, "spm": 22, "hr": 145}, {"t": 897, "d": 3212, "p": 1312, "spm": 22, "hr": 145}, {"t": 926, "d": 3319, "p": 1330, "spm": 21, "hr": 145}, {"t": 953, "d": 3420, "p": 1328, "spm": 22, "hr": 146}, {"t": 980, "d": 3524, "p": 1328, "spm": 22, "hr": 146}, {"t": 1008, "d": 3630, "p": 1321, "spm": 22, "hr": 146}, {"t": 1036, "d": 3734, "p": 1324, "spm": 22, "hr": 147}, {"t": 1063, "d": 3839, "p": 1322, "spm": 22, "hr": 147}, {"t": 1092, "d": 3946, "p": 1326, "spm": 22, "hr": 147}, {"t": 1119, "d": 4050, "p": 1335, "spm": 21, "hr": 147}, {"t": 1146, "d": 4153, "p": 1325, "spm": 22, "hr": 148}, {"t": 1176, "d": 4260, "p": 1329, "spm": 22, "hr": 148}, {"t": 1203, "d": 4365, "p": 1333, "spm": 21, "hr": 148}, {"t": 1231, "d": 4469, "p": 1335, "spm": 22, "hr": 148}, {"t": 1256, "d": 4569, "p": 1312, "spm": 22, "hr": 149}, {"t": 1284, "d": 4676, "p": 1316, "spm": 22, "hr": 149}, {"t": 1313, "d": 4785, "p": 1315, "spm": 22, "hr": 150}, {"t": 1341, "d": 4890, "p": 1318, "spm": 21, "hr": 150}, {"t": 1367, "d": 4991, "p": 1336, "spm": 21, "hr": 150}, {"t": 1397, "d": 5100, "p": 1329, "spm": 22, "hr": 150}, {"t": 1423, "d": 5199, "p": 1323, "spm": 22, "hr": 149}, {"t": 1451, "d": 5306, "p": 1327, "spm": 22, "hr": 149}, {"t": 1478, "d": 5408, "p": 1337, "spm": 22, "hr": 149}, {"t": 1505, "d": 5508, "p": 1334, "spm": 22, "hr": 148}, {"t": 1532, "d": 5608, "p": 1348, "spm": 22, "hr": 148}, {"t": 1559, "d": 5710, "p": 1333, "spm": 22, "hr": 147}, {"t": 1584, "d": 5807, "p": 1330, "spm": 22, "hr": 147}, {"t": 1612, "d": 5912, "p": 1329, "spm": 22, "hr": 147}, {"t": 1639, "d": 6014, "p": 1330, "spm": 22, "hr": 147}, {"t": 1666, "d": 6114, "p": 1321, "spm": 23, "hr": 147}, {"t": 1693, "d": 6218, "p": 1328, "spm": 23, "hr": 147}, {"t": 1720, "d": 6321, "p": 1317, "spm": 22, "hr": 147}, {"t": 1747, "d": 6423, "p": 1319, "spm": 22, "hr": 147}, {"t": 1772, "d": 6520, "p": 1310, "spm": 23, "hr": 148}, {"t": 1801, "d": 6627, "p": 1297, "spm": 23, "hr": 148}, {"t": 1826, "d": 6731, "p": 1296, "spm": 23, "hr": 148}, {"t": 1854, "d": 6836, "p": 1295, "spm": 22, "hr": 149}, {"t": 1880, "d": 6938, "p": 1297, "spm": 22, "hr": 149}, {"t": 1905, "d": 7038, "p": 1292, "spm": 22, "hr": 149}, {"t": 1934, "d": 7147, "p": 1297, "spm": 23, "hr": 150}, {"t": 1960, "d": 7249, "p": 1296, "spm": 22, "hr": 150}, {"t": 1987, "d": 7352, "p": 1306, "spm": 23, "hr": 151}, {"t": 2014, "d": 7454, "p": 1307, "spm": 22, "hr": 151}, {"t": 2041, "d": 7560, "p": 1291, "spm": 23, "hr": 151}, {"t": 2067, "d": 7663, "p": 1294, "spm": 22, "hr": 150}, {"t": 2094, "d": 7765, "p": 1300, "spm": 22, "hr": 150}, {"t": 2120, "d": 7869, "p": 1295, "spm": 23, "hr": 150}, {"t": 2147, "d": 7972, "p": 1290, "spm": 22, "hr": 150}, {"t": 2174, "d": 8078, "p": 1288, "spm": 23, "hr": 150}, {"t": 2201, "d": 8182, "p": 1286, "spm": 23, "hr": 150}, {"t": 2226, "d": 8284, "p": 1282, "spm": 22, "hr": 150}, {"t": 2254, "d": 8392, "p": 1279, "spm": 23, "hr": 150}, {"t": 2281, "d": 8496, "p": 1288, "spm": 23, "hr": 151}, {"t": 2307, "d": 8601, "p": 1272, "spm": 22, "hr": 151}, {"t": 2333, "d": 8703, "p": 1272, "spm": 22, "hr": 152}, {"t": 2361, "d": 8811, "p": 1280, "spm": 22, "hr": 152}, {"t": 2388, "d": 8917, "p": 1284, "spm": 23, "hr": 152}, {"t": 2415, "d": 9021, "p": 1293, "spm": 22, "hr": 152}, {"t": 2444, "d": 9131, "p": 1299, "spm": 22, "hr": 152}, {"t": 2472, "d": 9239, "p": 1309, "spm": 22, "hr": 153}, {"t": 2500, "d": 9346, "p": 1307, "spm": 21, "hr": 154}, {"t": 2528, "d": 9454, "p": 1320, "spm": 21, "hr": 154}, {"t": 2556, "d": 9560, "p": 1318, "spm": 21, "hr": 155}, {"t": 2585, "d": 9667, "p": 1326, "spm": 21, "hr": 155}, {"t": 2613, "d": 9774, "p": 1330, "spm": 21, "hr": 156}, {"t": 2641, "d": 9881, "p": 1310, "spm": 21, "hr": 156}, {"t": 2669, "d": 9988, "p": 1316, "spm": 21, "hr": 156}, {"t": 2698, "d": 10096, "p": 1327, "spm": 21, "hr": 156}, {"t": 2727, "d": 10206, "p": 1338, "spm": 21, "hr": 156}, {"t": 2757, "d": 10315, "p": 1345, "spm": 20, "hr": 156}, {"t": 2786, "d": 10425, "p": 1347, "spm": 21, "hr": 156}, {"t": 2815, "d": 10533, "p": 1347, "spm": 20, "hr": 155}, {"t": 2844, "d": 10641, "p": 1339, "spm": 21, "hr": 155}, {"t": 2874, "d": 10753, "p": 1354, "spm": 20, "hr": 155}, {"t": 2904, "d": 10861, "p": 1375, "spm": 20, "hr": 155}, {"t": 2935, "d": 10975, "p": 1359, "spm": 21, "hr": 155}, {"t": 2964, "d": 11085, "p": 1344, "spm": 20, "hr": 155}, {"t": 2993, "d": 11192, "p": 1353, "spm": 20, "hr": 155}, {"t": 3024, "d": 11306, "p": 1353, "spm": 20, "hr": 155}, {"t": 3054, "d": 11413, "p": 1353, "spm": 20, "hr": 155}, {"t": 3083, "d": 11524, "p": 1354, "spm": 21, "hr": 155}, {"t": 3113, "d": 11633, "p": 1367, "spm": 20, "hr": 155}, {"t": 3140, "d": 11738, "p": 1360, "spm": 20, "hr": 154}, {"t": 3170, "d": 11848, "p": 1342, "spm": 21, "hr": 154}, {"t": 3200, "d": 11958, "p": 1343, "spm": 21, "hr": 153}, {"t": 3229, "d": 12066, "p": 1357, "spm": 21, "hr": 152}, {"t": 3259, "d": 12173, "p": 1358, "spm": 21, "hr": 153}, {"t": 3287, "d": 12278, "p": 1363, "spm": 21, "hr": 152}, {"t": 3315, "d": 12387, "p": 1354, "spm": 21, "hr": 152}, {"t": 3345, "d": 12495, "p": 1334, "spm": 21, "hr": 151}, {"t": 3374, "d": 12601, "p": 1359, "spm": 20, "hr": 151}, {"t": 3403, "d": 12709, "p": 1357, "spm": 21, "hr": 151}, {"t": 3432, "d": 12818, "p": 1346, "spm": 21, "hr": 150}, {"t": 3461, "d": 12927, "p": 1355, "spm": 20, "hr": 151}, {"t": 3490, "d": 13034, "p": 1358, "spm": 20, "hr": 151}, {"t": 3519, "d": 13143, "p": 1357, "spm": 21, "hr": 151}, {"t": 3549, "d": 13252, "p": 1343, "spm": 21, "hr": 151}, {"t": 3578, "d": 13361, "p": 1352, "spm": 20, "hr": 152}, {"t": 3607, "d": 13469, "p": 1348, "spm": 21, "hr": 152}, {"t": 3636, "d": 13574, "p": 1358, "spm": 20, "hr": 152}, {"t": 3665, "d": 13681, "p": 1368, "spm": 21, "hr": 152}, {"t": 3694, "d": 13790, "p": 1355, "spm": 20, "hr": 152}, {"t": 3723, "d": 13895, "p": 1346, "spm": 21, "hr": 153}, {"t": 3751, "d": 13999, "p": 1369, "spm": 21, "hr": 152}, {"t": 3780, "d": 14107, "p": 1367, "spm": 20, "hr": 152}, {"t": 3811, "d": 14220, "p": 1364, "spm": 20, "hr": 152}, {"t": 3840, "d": 14328, "p": 1358, "spm": 20, "hr": 151}, {"t": 3869, "d": 14436, "p": 1344, "spm": 21, "hr": 151}, {"t": 3898, "d": 14544, "p": 1353, "spm": 20, "hr": 152}, {"t": 3927, "d": 14651, "p": 1351, "spm": 21, "hr": 151}, {"t": 3956, "d": 14759, "p": 1345, "spm": 21, "hr": 152}, {"t": 3984, "d": 14866, "p": 1336, "spm": 21, "hr": 152}, {"t": 4014, "d": 14974, "p": 1354, "spm": 21, "hr": 153}, {"t": 4043, "d": 15082, "p": 1363, "spm": 20, "hr": 153}, {"t": 4073, "d": 15192, "p": 1350, "spm": 20, "hr": 154}, {"t": 4102, "d": 15300, "p": 1351, "spm": 21, "hr": 154}, {"t": 4131, "d": 15409, "p": 1357, "spm": 20, "hr": 153}, {"t": 4159, "d": 15513, "p": 1351, "spm": 21, "hr": 153}, {"t": 4190, "d": 15626, "p": 1343, "spm": 21, "hr": 153}, {"t": 4219, "d": 15733, "p": 1359, "spm": 20, "hr": 153}, {"t": 4248, "d": 15842, "p": 1364, "spm": 20, "hr": 152}, {"t": 4276, "d": 15946, "p": 1345, "spm": 21, "hr": 152}, {"t": 4307, "d": 16060, "p": 1351, "spm": 21, "hr": 152}, {"t": 4334, "d": 16162, "p": 1369, "spm": 20, "hr": 152}, {"t": 4365, "d": 16274, "p": 1362, "spm": 21, "hr": 152}, {"t": 4394, "d": 16380, "p": 1349, "spm": 21, "hr": 152}, {"t": 4424, "d": 16492, "p": 1353, "spm": 20, "hr": 151}, {"t": 4453, "d": 16602, "p": 1353, "spm": 20, "hr": 152}, {"t": 4482, "d": 16708, "p": 1357, "spm": 20, "hr": 151}, {"t": 4511, "d": 16814, "p": 1361, "spm": 21, "hr": 151}, {"t": 4540, "d": 16921, "p": 1361, "spm": 21, "hr": 151}, {"t": 4568, "d": 17025, "p": 1358, "spm": 21, "hr": 150}, {"t": 4598, "d": 17137, "p": 1349, "spm": 21, "hr": 150}, {"t": 4627, "d": 17244, "p": 1344, "spm": 21, "hr": 150}, {"t": 4656, "d": 17351, "p": 1358, "spm": 20, "hr": 150}, {"t": 4685, "d": 17456, "p": 1361, "spm": 21, "hr": 150}, {"t": 4713, "d": 17563, "p": 1358, "spm": 21, "hr": 150}, {"t": 4740, "d": 17662, "p": 1357, "spm": 20, "hr": 151}, {"t": 4770, "d": 17771, "p": 1369, "spm": 22, "hr": 150}, {"t": 4798, "d": 17875, "p": 1369, "spm": 21, "hr": 150}, {"t": 4826, "d": 17977, "p": 1362, "spm": 22, "hr": 150}, {"t": 4855, "d": 18084, "p": 1361, "spm": 21, "hr": 150}, {"t": 4882, "d": 18184, "p": 1367, "spm": 21, "hr": 149}, {"t": 4910, "d": 18289, "p": 1344, "spm": 22, "hr": 149}, {"t": 4940, "d": 18399, "p": 1356, "spm": 21, "hr": 149}, {"t": 4968, "d": 18505, "p": 1357, "spm": 21, "hr": 148}, {"t": 4997, "d": 18612, "p": 1346, "spm": 21, "hr": 148}, {"t": 5027, "d": 18719, "p": 1354, "spm": 21, "hr": 147}, {"t": 5056, "d": 18826, "p": 1366, "spm": 20, "hr": 147}, {"t": 5084, "d": 18933, "p": 1363, "spm": 20, "hr": 148}, {"t": 5114, "d": 19043, "p": 1348, "spm": 21, "hr": 149}, {"t": 5144, "d": 19154, "p": 1336, "spm": 20, "hr": 149}, {"t": 5174, "d": 19262, "p": 1364, "spm": 20, "hr": 150}, {"t": 5203, "d": 19373, "p": 1361, "spm": 20, "hr": 151}, {"t": 5231, "d": 19478, "p": 1348, "spm": 20, "hr": 152}, {"t": 5262, "d": 19591, "p": 1355, "spm": 20, "hr": 152}, {"t": 5291, "d": 19698, "p": 1361, "spm": 20, "hr": 153}, {"t": 5320, "d": 19806, "p": 1353, "spm": 21, "hr": 153}, {"t": 5349, "d": 19914, "p": 1353, "spm": 21, "hr": 153}, {"t": 5372, "d": 20000, "p": 1340, "spm": 21, "hr": 154}], "workout": {"splits": [{"type": "distance", "time": 1397, "distance": 510, "heart_rate": {"average": 141}, "stroke_rate": 21}, {"type": "distance", "time": 1301, "distance": 499, "heart_rate": {"average": 150}, "stroke_rate": 22}, {"type": "distance", "time": 1344, "distance": 498, "heart_rate": {"average": 152}, "stroke_rate": 20}, {"type": "distance", "time": 1328, "distance": 491, "heart_rate": {"average": 150}, "stroke_rate": 20}]}} +May-21-2021 09:40:10 User 1, C2 ID 33991243 +May-21-2021 09:40:10 {"distance": 13878, "user_id": 457764, "ranked": false, "weight_class": "L", "verified": false, "workout_type": false, "comments": "\n from speedcoach2v2.15 via rowsandall.com", "heart_rate": {"max": 158, "average": 156}, "source": "rowingdata", "date_utc": "2018-06-30 05:31:01", "time_formatted": "1:21:16.7", "time": 48767, "date": "2018-06-30 07:31:01", "timezone": "Europe/Prague", "type": "water", "id": 33991243, "stroke_data": true} +May-21-2021 09:40:10 Time zone Europe/Prague, stardatetime 2018-06-30 06:09:44.300000+02:00, duration 01:21:16.6 \ No newline at end of file diff --git a/rowers/mytypes.py b/rowers/mytypes.py index 89ddb6af..881cd311 100644 --- a/rowers/mytypes.py +++ b/rowers/mytypes.py @@ -183,38 +183,6 @@ stcollection = ( stmapping = {key:value for key,value in Reverse(stcollection)} -rkcollection = ( - ('water','Rowing'), - ('rower','Rowing'), - ('skierg','Cross-Country Skiing'), - ('bike','Cycling'), - ('bikeerg','Cycling'), - ('dynamic','Rowing'), - ('slides','Rowing'), - ('paddle','Other:Paddling'), - ('snow','Cross-Country Skiing'), - ('coastal','Rowing'), - ('c-boat','Rowing'), - ('churchboat','Rowing'), - ('Ride','Cycling'), - ('Run','Running'), - ('NordicSki','Cross-Country Skiing'), - ('Swim','Swimming'), - ('Hike','Hiking'), - ('Walk','Walking'), - ('Canoeing','Other'), - ('Crossfit','CrossFit'), - ('StandUpPaddling','Other'), - ('IceSkate','Skating'), - ('WeightTraining','Other'), - ('InlineSkate','Skating'), - ('Kayaking','Other'), - ('Workout','Other'), - ('other','Other'), - ('Yoga','Other'), -) - -rkmapping = {key:value for key,value in Reverse(rkcollection)} polarcollection = ( ('water','Rowing'), @@ -320,7 +288,6 @@ stravamappinginv = {value:key for key,value in Reverse(stravacollection) if valu stmappinginv = {value:key for key,value in Reverse(stcollection) if value is not None} -rkmappinginv = {value:key for key,value in Reverse(rkcollection) if value is not None} polarmappinginv = {value:key for key,value in Reverse(polarcollection) if value is not None} @@ -365,7 +332,6 @@ workoutsources = ( ('strava','strava'), ('concept2','concept2'), ('sporttracks','sporttracks'), - ('runkeeper','runkeeper'), ('mapmyfitness','mapmyfitness'), ('csv','painsled'), ('tcx','tcx'), diff --git a/rowers/stravastuff.py b/rowers/stravastuff.py index 7e13afbd..46ae20df 100644 --- a/rowers/stravastuff.py +++ b/rowers/stravastuff.py @@ -382,118 +382,9 @@ def async_get_workout(user,stravaid): return job # Get a Strava workout summary data and stroke data by ID -def get_workout(user,stravaid,do_async=False): - if do_async: # pragma: no cover - res = async_get_workout(user,stravaid) - return {},pd.DataFrame() - try: - thetoken = strava_open(user) - except NoTokenError: # pragma: no cover - s = "Token error" - return custom_exception_handler(401,s) +def get_workout(user,stravaid,do_async=True): + return async_get_workout(user,stravaid) - r = Rower.objects.get(user=user) - if (r.stravatoken == '') or (r.stravatoken is None): # pragma: no cover - s = "Token doesn't exist. Need to authorize" - return custom_exception_handler(401,s) - elif (r.stravatokenexpirydate is not None and timezone.now()>r.stravatokenexpirydate): # pragma: no cover - s = "Token expired. Needs to refresh." - return custom_exception_handler(401,s) - else: - # ready to fetch. Hurray - fetchresolution = 'high' - series_type = 'time' - authorizationstring = str('Bearer ' + r.stravatoken) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json', - 'resolution': 'medium',} - url = "https://www.strava.com/api/v3/activities/"+str(stravaid) - workoutsummary = requests.get(url,headers=headers).json() - - workoutsummary['timezone'] = "Etc/UTC" - try: - startdatetime = workoutsummary['start_date'] - except KeyError: # pragma: no cover - startdatetime = timezone.now() - - spm = get_strava_stream(r,'cadence',stravaid) - hr = get_strava_stream(r,'heartrate',stravaid) - t = get_strava_stream(r,'time',stravaid) - velo = get_strava_stream(r,'velocity_smooth',stravaid) - d = get_strava_stream(r,'distance',stravaid) - coords = get_strava_stream(r,'latlng',stravaid) - power = get_strava_stream(r,'watts',stravaid) - - if t is not None: - nr_rows = len(t) - else: # pragma: no cover - duration = int(workoutsummary['elapsed_time']) - t = pd.Series(range(duration+1)) - - nr_rows = len(t) - - - if nr_rows == 0: # pragma: no cover - return (0,"Error: Time data had zero length") - - if d is None: # pragma: no cover - d = 0*t - - if spm is None: # pragma: no cover - spm = np.zeros(nr_rows) - - if power is None: # pragma: no cover - power = np.zeros(nr_rows) - - if hr is None: # pragma: no cover - hr = np.zeros(nr_rows) - - if velo is None: # pragma: no cover - velo = np.zeros(nr_rows) - - dt = np.diff(t).mean() - wsize = round(5./dt) - - velo2 = ewmovingaverage(velo,wsize) - - if coords is not None: - try: - lat = coords[:,0] - lon = coords[:,1] - except IndexError: # pragma: no cover - lat = np.zeros(len(t)) - lon = np.zeros(len(t)) - else: # pragma: no cover - lat = np.zeros(len(t)) - lon = np.zeros(len(t)) - - - - - strokelength = velo*60./(spm) - strokelength[np.isinf(strokelength)] = 0.0 - - - pace = 500./(1.0*velo2) - pace[np.isinf(pace)] = 0.0 - - df = pd.DataFrame({'t':10*t, - 'd':10*d, - 'p':10*pace, - 'spm':spm, - 'hr':hr, - 'lat':lat, - 'lon':lon, - 'power':power, - 'strokelength':strokelength, - }) - - - - # startdatetime = datetime.datetime.strptime(startdatetime,"%Y-%m-%d-%H:%M:%S") - - return [workoutsummary,df] # Generate Workout data for Strava (a TCX file) def createstravaworkoutdata(w,dozip=True): diff --git a/rowers/tasks.py b/rowers/tasks.py index 35293887..710f77e0 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -66,6 +66,7 @@ from django.utils import timezone from django.utils.html import strip_tags from rowers.utils import deserialize_list,ewmovingaverage,wavg,dologging +import rowers.utils as utils from rowers.emails import htmlstrip from rowers import mytypes @@ -317,20 +318,6 @@ def handle_sporttracks_sync(workoutid,url,headers,data,debug=False,**kwargs): return 1 -@app.task -def handle_runkeeper_sync(workoutid,url,headers,data,debug=False,**kwargs): - response = requests.post(url,headers=headers,data=data) - if response.status_code not in [200,201]: # pragma: no cover - return 0 - - uri = response.headers["Location"] - - tester = re.compile('^\/fitnessActivities\/(\d+)$') - id = int(tester.match(uri).group(1)) - - res = update_workout_field_sql(workoutid,'uploadedtorunkeeper',id,debug=debug) - - return 1 @app.task def handle_strava_sync(stravatoken,workoutid,filename,name,activity_type,description,debug=False,**kwargs): @@ -3008,10 +2995,7 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone c2id = data['id'] workouttype = data['type'] verified = data['verified'] - try: - startdatetime = iso8601.parse_date(data['date_utc']) - except: # pragma: no cover - startdatetime = iso8601.parse_date(data['date']) + weightclass = data['weight_class'] s = 'User {userid}, C2 ID {c2id}'.format(userid=userid,c2id=c2id) @@ -3035,16 +3019,8 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone # Create CSV file name and save data to CSV file csvfilename ='media/Import_'+str(c2id)+'.csv.gz' - totaltime = data['time']/10. - duration = totaltime_sec_to_string(totaltime) - starttimeunix = arrow.get(startdatetime).timestamp()-totaltime - startdatetime = arrow.get(starttimeunix) + startdatetime,starttime,workoutdate,duration,starttimeunix,timezone = utils.get_startdatetime_from_c2data(data) - try: - timezone = pytz.timezone(data['timezone']) - except UnknownTimeZoneError: - timezone = 'UTC' - startdatetime = startdatetime.astimezone(timezone) s = 'Time zone {timezone}, stardatetime {startdatetime}, duration {duration}'.format( timezone=timezone,startdatetime=startdatetime, @@ -3053,12 +3029,7 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone - workoutdate = startdatetime.astimezone( - timezone - ).strftime('%Y-%m-%d') - starttime = startdatetime.astimezone( - timezone - ).strftime('%H:%M:%S') + try: notes = data['comments'] diff --git a/rowers/tests/mocks.py b/rowers/tests/mocks.py index 7dea2622..10e2e1d9 100644 --- a/rowers/tests/mocks.py +++ b/rowers/tests/mocks.py @@ -334,6 +334,16 @@ def mocked_getsmallrowdata_db(*args, **kwargs): return df +def mocked_getsmallrowdata_db_updatecp(*args, **kwargs): + df = pd.read_csv('rowers/tests/testdata/colsfromdb.csv') + + return df + +def mocked_getsmallrowdata_db_setcp(*args, **kwargs): + df = pd.read_csv('rowers/tests/testdata/colsfromdb.csv') + + return df + def mocked_getsmallrowdata_db_water(*args, **kwargs): df = pd.read_csv('rowers/tests/testdata/colsfromdb.csv') diff --git a/rowers/tests/test_async_tasks.py b/rowers/tests/test_async_tasks.py index 745880ca..a327a1c6 100644 --- a/rowers/tests/test_async_tasks.py +++ b/rowers/tests/test_async_tasks.py @@ -462,22 +462,6 @@ class AsyncTaskTests(TestCase): res = tasks.handle_sporttracks_sync(1,url,headers,json.dumps(data,default=sporttracksstuff.default)) self.assertEqual(res,1) - @patch('rowers.runkeeperstuff.requests.post', side_effect=mocked_requests) - @patch('rowers.runkeeperstuff.requests.get', side_effect=mocked_requests) - def test_runkeeper_sync(self, mock_get, mock_post): - authorizationstring = str('Bearer aap') - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/vnd.com.runkeeper.NewFitnessActivity+json', - 'Content-Length':'nnn'} - - url = "https://api.runkeeper.com/fitnessActivities" - - data = runkeeperstuff.createrunkeeperworkoutdata(self.wwater) - - - res = tasks.handle_runkeeper_sync(1,url,headers,json.dumps(data,default=sporttracksstuff.default)) - self.assertEqual(res,1) @patch('rowers.c2stuff.requests.post',side_effect=mocked_requests) @patch('rowers.c2stuff.requests.get',side_effect=mocked_requests) @@ -518,14 +502,14 @@ class AsyncTaskTests(TestCase): self.assertEqual(res,1) - @patch('rowers.dataprepnodjango.getsmallrowdata_db') + @patch('rowers.dataprepnodjango.getsmallrowdata_db_updatecp') def test_handle_updatecp(self,mocked_getsmallrowdata_db): rower_id = 1 workoutids = [1] res = tasks.handle_updatecp(rower_id,workoutids) self.assertEqual(res,1) - @patch('rowers.dataprepnodjango.getsmallrowdata_db') + @patch('rowers.dataprepnodjango.getsmallrowdata_db_setcp') def test_handle_setcp(self,mocked_getsmallrowdata_db): strokesdf = pd.read_csv('rowers/tests/testdata/uhfull.csv') filename = 'rowers/tests/testdata/temp/pq.gz' diff --git a/rowers/tests/test_imports.py b/rowers/tests/test_imports.py index 260e8c97..e3e863f8 100644 --- a/rowers/tests/test_imports.py +++ b/rowers/tests/test_imports.py @@ -19,6 +19,8 @@ from rowers import stravastuff import urllib import json +import rowers.utils as utils + from django.db import transaction import rowers.garmin_stuff as gs @@ -326,7 +328,7 @@ class C2Objects(DjangoTestCase): def test_c2_import_tz(self, mock_get, mocked_sqlalchemy): response = self.c.get('/rowers/workout/c2import/22/',follow=True) - expected_url = '/rower/workout/c2list/' + expected_url = '/rowers/workout/c2list/' self.assertRedirects(response, expected_url=expected_url, @@ -334,8 +336,10 @@ class C2Objects(DjangoTestCase): self.assertEqual(response.status_code, 200) - w = Workout.objects.get(id=2) - self.assertEqual(w.timezone,'Europe/Prague') + with open('rowers/tests/testdata/c2_timezone.json','r') as infile: + data = json.load(infile) + timezone = str(utils.get_timezone_from_c2data(data['data'])) + self.assertEqual(timezone,'Europe/Prague') @patch('rowers.c2stuff.requests.get', side_effect=mocked_requests) @@ -343,7 +347,7 @@ class C2Objects(DjangoTestCase): def test_c2_import_tz3(self, mock_get, mocked_sqlalchemy): response = self.c.get('/rowers/workout/c2import/32/',follow=True) - expected_url = '/rower/workout/c2list/' + expected_url = '/rowers/workout/c2list/' self.assertRedirects(response, expected_url=expected_url, @@ -351,15 +355,18 @@ class C2Objects(DjangoTestCase): self.assertEqual(response.status_code, 200) - w = Workout.objects.get(id=2) - self.assertEqual(w.timezone,'UTC') + with open('rowers/tests/testdata/c2_timezonebad.json','r') as infile: + data = json.load(infile) + + timezone = str(utils.get_timezone_from_c2data(data['data'])) + self.assertEqual(timezone,'UTC') @patch('rowers.c2stuff.requests.get', side_effect=mocked_requests) @patch('rowers.dataprep.create_engine') def test_c2_import_tz2(self, mock_get, mocked_sqlalchemy): response = self.c.get('/rowers/workout/c2import/31/',follow=True) - expected_url = '/rower/workout/c2list/' + expected_url = '/rowers/workout/c2list/' self.assertRedirects(response, expected_url=expected_url, @@ -367,10 +374,14 @@ class C2Objects(DjangoTestCase): self.assertEqual(response.status_code, 200) - w = Workout.objects.get(id=2) - self.assertEqual(w.timezone,'Europe/Amsterdam') + with open('rowers/tests/testdata/c2_timezone2.json','r') as infile: + data = json.load(infile) - self.assertEqual(w.starttime.strftime("%H:%M:%S"),"20:04:56") + timezone = str(utils.get_timezone_from_c2data(data['data'])) + self.assertEqual(timezone,'Europe/Amsterdam') + + startdatetime,starttime,workoutdate,duration,starttimeunix,timezone = utils.get_startdatetime_from_c2data(data['data']) + self.assertEqual(starttime,"20:04:55") diff --git a/rowers/tests/viewnames.csv b/rowers/tests/viewnames.csv index 8d399ca0..6f14f22d 100644 --- a/rowers/tests/viewnames.csv +++ b/rowers/tests/viewnames.csv @@ -94,14 +94,10 @@ 104,127,workout_sporttracksimport_view,list workouts to be imported (test stops at notokenerror),TRUE,302,basic,302,302,basic,403,403,coach,302,403,FALSE,TRUE,FALSE,TRUE,TRUE, 105,129,workout_getsporttracksworkout_all,gets all C2 workouts (now redirects due to NoTokenError,TRUE,302,basic,302,302,FALSE,302,302,FALSE,302,302,FALSE,FALSE,FALSE,TRUE,TRUE, 106,130,workout_polarimport_view,list workouts to be imported (test stops at notokenerror),TRUE,302,basic,302,302,basic,403,403,coach,302,403,FALSE,TRUE,FALSE,TRUE,TRUE, -107,132,workout_runkeeperimport_view,list workouts to be imported (test stops at notokenerror),TRUE,302,basic,302,302,basic,403,403,coach,302,403,FALSE,TRUE,FALSE,TRUE,TRUE, -108,134,workout_underarmourimport_view,list workouts to be imported (test stops at notokenerror),TRUE,302,basic,302,302,basic,403,403,coach,302,403,FALSE,TRUE,FALSE,TRUE,TRUE, 109,135,workout_c2_upload_view,uploads workout to C2,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE, 110,136,workout_strava_upload_view,uploads workout to C2,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE, 111,137,workout_recalcsummary_view,recalculates workout summary,TRUE,403,basic,302,403,basic,403,403,coach,302,403,FALSE,FALSE,TRUE,TRUE,TRUE, 112,138,workout_sporttracks_upload_view,uploads workout to C2,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE, -113,139,workout_runkeeper_upload_view,uploads workout to C2,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE, -114,140,workout_underarmour_upload_view,uploads workout to C2,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE, 115,141,workout_tp_upload_view,uploads workout to C2,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE, 116,142,multi_compare_view,compare workouts ,TRUE,302,basic,302,403,basic,302,403,coach,302,302,FALSE,FALSE,TRUE,TRUE,TRUE, 117,145,alerts_view,view alerts,TRUE,302,basic,200,403,basic,403,403,coach,200,302,FALSE,TRUE,FALSE,TRUE,TRUE, @@ -151,11 +147,8 @@ 165,210,rower_revokeapp_view,revoke app,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 166,211,rower_strava_authorize,authorize on strava,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 167,212,rower_sporttracks_authorize,authorize on sporttracks,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, -168,213,rower_underarmour_authorize,authorize on UA,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 169,214,rower_tp_authorize,authorize on TP,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, -170,215,rower_runkeeper_authorize,authorize on RK,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 171,216,rower_sporttracks_token_refresh,refresh token,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, -172,217,rower_underarmour_token_refresh,refresh token,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 173,218,rower_tp_token_refresh,refresh token,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 174,219,rower_c2_token_refresh,refresh token,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 175,220,rower_favoritecharts_view,See favorite charts,TRUE,302,pro,200,302,pro,403,403,coach,200,403,FALSE,TRUE,FALSE,TRUE,TRUE, @@ -232,9 +225,7 @@ 247,343,rower_process_callback,Tested in specific test suite,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 248,344,rower_process_stravacallback,Tested in specific test suite,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 249,345,rower_process_sporttrackscallback,Tested in specific test suite,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, -250,346,rower_process_underarmourcallback,Tested in specific test suite,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 251,347,rower_process_polarcallback,Tested in specific test suite,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, -252,348,rower_process_runkeepercallback,Tested in specific test suite,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 253,349,rower_process_tpcallback,Tested in specific test suite,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 254,350,rower_process_twittercallback,Tested in specific test suite,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 255,351,set_language,Set language,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, diff --git a/rowers/utils.py b/rowers/utils.py index e9781a8a..6ef5e013 100644 --- a/rowers/utils.py +++ b/rowers/utils.py @@ -26,6 +26,11 @@ import requests from django.http import HttpResponse import humanize +from pytz.exceptions import UnknownTimeZoneError +import pytz +import iso8601 +from iso8601 import ParseError +import arrow lbstoN = 4.44822 @@ -1232,3 +1237,37 @@ def intervals_to_string(vals, units, typ): s = s[1:] return s + +def get_timezone_from_c2data(data): + + try: + timezone = pytz.timezone(data['timezone']) + except UnknownTimeZoneError: + timezone = pytz.utc + except KeyError: + timezone = pytz.utc + + return timezone + + +def get_startdatetime_from_c2data(data): + timezone = get_timezone_from_c2data(data) + try: + startdatetime = iso8601.parse_date(data['date_utc']) + except: # pragma: no cover + startdatetime = iso8601.parse_date(data['date']) + + totaltime = data['time']/10. + duration = totaltime_sec_to_string(totaltime) + starttimeunix = arrow.get(startdatetime).timestamp()-totaltime + startdatetime = arrow.get(starttimeunix) + startdatetime = startdatetime.astimezone(timezone) + + workoutdate = startdatetime.astimezone( + timezone + ).strftime('%Y-%m-%d') + starttime = startdatetime.astimezone( + timezone + ).strftime('%H:%M:%S') + + return startdatetime,starttime,workoutdate,duration,starttimeunix,timezone From 71fdecaf42047f82b779692b563dd5b956c5884c Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Fri, 21 May 2021 14:55:49 +0200 Subject: [PATCH 06/12] increase test coverage --- rowers/c2stuff.py | 206 ---- rowers/dataprep.py | 2 +- rowers/imports.py | 14 +- rowers/nkimportutils.py | 4 +- rowers/nkstuff.py | 93 +- rowers/stravastuff.py | 156 --- rowers/templatetags/rowerfilters.py | 15 - rowers/tests/mocks.py | 4 +- rowers/tests/test_async_tasks.py | 8 +- rowers/tests/test_imports.py | 33 - rowers/tests/testdata/colsfromdb2.csv | 1399 +++++++++++++++++++++++++ rowers/tests/testdata/colsfromdb3.csv | 1399 +++++++++++++++++++++++++ rowers/utils.py | 2 +- rowers/views/importviews.py | 2 +- rowers/views/statements.py | 160 --- 15 files changed, 2830 insertions(+), 667 deletions(-) create mode 100644 rowers/tests/testdata/colsfromdb2.csv create mode 100644 rowers/tests/testdata/colsfromdb3.csv diff --git a/rowers/c2stuff.py b/rowers/c2stuff.py index 02cf4410..58c14b07 100644 --- a/rowers/c2stuff.py +++ b/rowers/c2stuff.py @@ -838,25 +838,6 @@ def get_workout(user,c2id,do_async=True): return 1 -# Get stroke data belonging to C2 ID -def get_c2_workout_strokes(user,c2id): - r = Rower.objects.get(user=user) - if (r.c2token == '') or (r.c2token is None): # pragma: no cover - return custom_exception_handler(401,s) - s = "Token doesn't exist. Need to authorize" - elif (timezone.now()>r.tokenexpirydate): # pragma: no cover - s = "Token expired. Needs to refresh." - return custom_exception_handler(401,s) - else: - # ready to fetch. Hurray - authorizationstring = str('Bearer ' + r.c2token) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - url = "https://log.concept2.com/api/users/me/results/"+str(c2id)+"/strokes" - s = requests.get(url,headers=headers) - - return s # Get list of C2 workouts. We load only the first page, # assuming that users don't want to import their old workouts @@ -1028,190 +1009,3 @@ def rower_c2_token_refresh(user): return r.c2token else: # pragma: no cover return None - -# Create workout data from Strava or Concept2 -# data and create the associated Workout object and save it -def add_workout_from_data(user,importid,data,strokedata, - source='c2',splitdata=None, - workoutsource='concept2'): - try: - workouttype = mytypes.c2mappinginv[data['type']] - except KeyError: # pragma: no cover - workouttype = 'rower' - - if workouttype not in [x[0] for x in Workout.workouttypes]: # pragma: no cover - workouttype = 'other' - try: - comments = data['comments'] - except: # pragma: no cover - comments = ' ' - - try: - thetimezone = pytz.timezone(data['timezone']) - except UnknownTimeZoneError: - thetimezone = 'UTC' - - - r = Rower.objects.get(user=user) - - try: - rowdatetime = iso8601.parse_date(data['date_utc']) - thetimezone = 'UTC' - except KeyError: # pragma: no cover - rowdatetime = iso8601.parse_date(data['start_date']) - rowdatetime = rowdatetime.make_aware(thetimezone) - except ParseError: # pragma: no cover - rowdatetime = iso8601.parse_date(data['date']) - rowdatetime = rowdatetime.make_aware(thetimezone) - - - try: - c2intervaltype = data['workout_type'] - - except KeyError: # pragma: no cover - c2intervaltype = '' - - try: - title = data['name'] - except KeyError: - title = "" - try: - t = data['comments'].split('\n', 1)[0] - title += t[:40] - except: # pragma: no cover - title = '' - - try: - comments = data['comments'] - except KeyError: # pragma: no cover - comments = '' - - starttimeunix = arrow.get(rowdatetime).timestamp() - - res = make_cumvalues(0.1*strokedata['t']) - cum_time = res[0] - lapidx = res[1] - - totaltime = data['time']/10. - starttimeunix = starttimeunix - totaltime - - - unixtime = cum_time+starttimeunix - # unixtime[0] = starttimeunix - seconds = 0.1*strokedata.loc[:,'t'] - - nr_rows = len(unixtime) - - try: # pragma: no cover - latcoord = strokedata.loc[:,'lat'] - loncoord = strokedata.loc[:,'lon'] - except: - latcoord = np.zeros(nr_rows) - loncoord = np.zeros(nr_rows) - - - try: - strokelength = strokedata.loc[:,'strokelength'] - except: - strokelength = np.zeros(nr_rows) - - dist2 = 0.1*strokedata.loc[:,'d'] - - try: - spm = strokedata.loc[:,'spm'] - except KeyError: # pragma: no cover - spm = 0*dist2 - - try: - hr = strokedata.loc[:,'hr'] - except KeyError: # pragma: no cover - hr = 0*spm - pace = strokedata.loc[:,'p']/10. - pace = np.clip(pace,0,1e4) - pace = pace.replace(0,300) - - velo = 500./pace - power = 2.8*velo**3 - if workouttype in ['bike','bikeerg']: # pragma: no cover - velo = 1000./pace - pace = 500./velo - - # save csv - # Create data frame with all necessary data to write to csv - df = pd.DataFrame({'TimeStamp (sec)':unixtime, - ' Horizontal (meters)': dist2, - ' Cadence (stokes/min)':spm, - ' HRCur (bpm)':hr, - ' longitude':loncoord, - ' latitude':latcoord, - ' Stroke500mPace (sec/500m)':pace, - ' Power (watts)':power, - ' DragFactor':np.zeros(nr_rows), - ' DriveLength (meters)':np.zeros(nr_rows), - ' StrokeDistance (meters)':strokelength, - ' DriveTime (ms)':np.zeros(nr_rows), - ' StrokeRecoveryTime (ms)':np.zeros(nr_rows), - ' AverageDriveForce (lbs)':np.zeros(nr_rows), - ' PeakDriveForce (lbs)':np.zeros(nr_rows), - ' lapIdx':lapidx, - ' WorkoutState': 4, - ' ElapsedTime (sec)':seconds - }) - - - df.sort_values(by='TimeStamp (sec)',ascending=True) - - timestr = strftime("%Y%m%d-%H%M%S") - - - # Create CSV file name and save data to CSV file - csvfilename ='media/{code}_{importid}.csv'.format( - importid=importid, - code = uuid4().hex[:16] - ) - - res = df.to_csv(csvfilename+'.gz',index_label='index', - compression='gzip') - - - # with Concept2 - if source=='c2': - try: - totaldist = data['distance'] - totaltime = data['time']/10. - except KeyError: # pragma: no cover - totaldist = 0 - totaltime = 0 - else: # pragma: no cover - totaldist = 0 - totaltime = 0 - - id,message = dataprep.save_workout_database( - csvfilename,r, - workouttype=workouttype, - title=title,notes=comments, - workoutsource=workoutsource, - dosummary=True,dosmooth=False, - ) - - - w = Workout.objects.get(id=id) - - try: - local_tz = pytz.timezone(data['timezone']) - except UnknownTimeZoneError: - local_tz = pytz.utc -# local_tz = pytz.timezone(thetimezone) - - w.startdatetime = w.startdatetime.astimezone(local_tz) - w.starttime = w.startdatetime.strftime('%H:%M:%S') - w.timezone = local_tz - - w.duration = dataprep.totaltime_sec_to_string(totaltime) - w.distance = totaldist - - - w.save() - - - return id,message diff --git a/rowers/dataprep.py b/rowers/dataprep.py index 1f1cf9de..4b934b05 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -800,7 +800,7 @@ def clean_df_stats(datadf, workstrokesonly=True, ignorehr=True, def getpartofday(row,r): workoutstartdatetime = row.rowdatetime - try: + try: # pragma: no cover latavg = row.df[' latitude'].mean() lonavg = row.df[' longitude'].mean() diff --git a/rowers/imports.py b/rowers/imports.py index 697bf62e..71a76357 100644 --- a/rowers/imports.py +++ b/rowers/imports.py @@ -71,26 +71,18 @@ def splitstdata(lijst): return [np.array(t),np.array(latlong)] -def splituadata(lijst): - t = [] - y = [] - for d in lijst: - t.append(d[0]) - y.append(d[1]) - - return np.array(t),np.array(y) def imports_open(user,oauth_data): r = Rower.objects.get(user=user) token = getattr(r,oauth_data['tokenname']) try: refreshtoken = getattr(r,oauth_data['refreshtokenname']) - except (TypeError,AttributeError,KeyError): + except (TypeError,AttributeError,KeyError): # pragma: no cover refreshtoken = None try: tokenexpirydate = getattr(r,oauth_data['expirydatename']) - except (TypeError,AttributeError,KeyError): + except (TypeError,AttributeError,KeyError): # pragma: no cover tokenexpirydate = None @@ -243,7 +235,7 @@ def imports_get_token( base_uri, data=json.dumps(post_data), headers=headers) - else: + else: # pragma: no cover response = requests.post( base_uri, data=post_data, diff --git a/rowers/nkimportutils.py b/rowers/nkimportutils.py index 82c17815..ab3890b8 100644 --- a/rowers/nkimportutils.py +++ b/rowers/nkimportutils.py @@ -35,7 +35,7 @@ def add_workout_from_data(userid,nkid,data,strokedata,source='nk',splitdata=None try: userid=int(userid) - except TypeError: + except TypeError: # pragma: no cover userid = userid.id strokedata.to_csv(csvfilename, index_label='index', compression='gzip') @@ -108,7 +108,7 @@ def add_workout_from_data(userid,nkid,data,strokedata,source='nk',splitdata=None try: workoutid = response.json()['id'] - except KeyError: + except KeyError: # pragma: no cover workoutid = 1 diff --git a/rowers/nkstuff.py b/rowers/nkstuff.py index cff6cd7b..81b32202 100644 --- a/rowers/nkstuff.py +++ b/rowers/nkstuff.py @@ -247,7 +247,7 @@ def get_nk_workout_list(user,fake=False,after=0,before=0): # -def get_workout(user,nkid,do_async=False): +def get_workout(user,nkid,do_async=True): r = Rower.objects.get(user=user) if (r.nktoken == '') or (r.nktoken is None): # pragma: no cover s = "Token doesn't exist. Need to authorize" @@ -260,79 +260,22 @@ def get_workout(user,nkid,do_async=False): 'sessionIds': nkid, } - if do_async: # pragma: no cover - res = get_nk_workout_list(r.user) - if res.status_code != 200: - return 0 - alldata = {} - for item in res.json(): - alldata[item['id']] = item + res = get_nk_workout_list(r.user) + if res.status_code != 200: # pragma: no cover + return 0 + alldata = {} + for item in res.json(): + alldata[item['id']] = item - res = myqueue( - queuehigh, - handle_nk_async_workout, - alldata, - r.user.id, - r.nktoken, - nkid, - 0, - r.defaulttimezone, - ) + res = myqueue( + queuehigh, + handle_nk_async_workout, + alldata, + r.user.id, + r.nktoken, + nkid, + 0, + r.defaulttimezone, + ) - return {},pd.DataFrame() - - - authorizationstring = str('Bearer ' + r.nktoken) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json', - } - - # get strokes - url = NK_API_LOCATION+"api/v1/sessions/strokes" - - response = requests.get(url,headers=headers,params=params) - - if response.status_code != 200: # pragma: no cover - # error handling and logging - return {},pd.DataFrame() - - jsonData = response.json() - - strokeData = jsonData[str(nkid)] - - df = strokeDataToDf(strokeData) - - # get workout data - after = df['timestamp'].min() - before = df['timestamp'].max() - - after = arrow.get(after/1000.) - before = arrow.get(before/1000.) - after = after-timedelta(days=1) - before = before+timedelta(days=1) - before = str(int(before.timestamp())*1000) - after = str(int(after.timestamp())*1000) - - - url = NK_API_LOCATION+"api/v1/sessions/" - params = { - 'after':after, - 'before': before, - } - - response = requests.get(url, headers=headers,params=params) - - if response.status_code != 200: # pragma: no cover - # error handling and logging - return {},df - - jsondata = response.json() - workoutdata = {} - - for w in jsondata: - if str(w['id']) == str(nkid): - workoutdata = w - - - return workoutdata, df + return res diff --git a/rowers/stravastuff.py b/rowers/stravastuff.py index 46ae20df..209fe0b7 100644 --- a/rowers/stravastuff.py +++ b/rowers/stravastuff.py @@ -468,162 +468,6 @@ def handle_stravaexport(f2,workoutname,stravatoken,description='', return (res.id,message) -# Create workout data from Strava or Concept2 -# data and create the associated Workout object and save it -def add_workout_from_data(user,importid,data,strokedata, - source='strava',splitdata=None, - workoutsource='strava'): - try: - workouttype = mytypes.stravamappinginv[data['type']] - except KeyError: # pragma: no cover - workouttype = 'other' - - if workouttype.lower() == 'rowing': # pragma: no cover - workouttype = 'rower' - - if 'summary_polyline' in data['map'] and workouttype=='rower': # pragma: no cover - workouttype = 'water' - - if workouttype not in [x[0] for x in Workout.workouttypes]: # pragma: no cover - workouttype = 'other' - try: - comments = data['comments'] - except: - comments = ' ' - - try: - thetimezone = tz(data['timezone']) - except: - thetimezone = 'UTC' - - r = Rower.objects.get(user=user) - try: - rowdatetime = iso8601.parse_date(data['date_utc']) - except KeyError: - rowdatetime = iso8601.parse_date(data['start_date']) - except ParseError: # pragma: no cover - rowdatetime = iso8601.parse_date(data['date']) - - - try: - intervaltype = data['workout_type'] - - except KeyError: - intervaltype = '' - - try: - title = data['name'] - except KeyError: # pragma: no cover - title = "" - try: - t = data['comments'].split('\n', 1)[0] - title += t[:20] - except: - title = '' - - starttimeunix = arrow.get(rowdatetime).timestamp() - - res = make_cumvalues(0.1*strokedata['t']) - cum_time = res[0] - lapidx = res[1] - - unixtime = cum_time+starttimeunix - seconds = 0.1*strokedata.loc[:,'t'] - - nr_rows = len(unixtime) - - try: - latcoord = strokedata.loc[:,'lat'] - loncoord = strokedata.loc[:,'lon'] - if latcoord.std() == 0 and loncoord.std() == 0 and workouttype == 'water': # pragma: no cover - workouttype = 'rower' - except: # pragma: no cover - latcoord = np.zeros(nr_rows) - loncoord = np.zeros(nr_rows) - if workouttype == 'water': - workouttype = 'rower' - - - - try: - strokelength = strokedata.loc[:,'strokelength'] - except: # pragma: no cover - strokelength = np.zeros(nr_rows) - - dist2 = 0.1*strokedata.loc[:,'d'] - - try: - spm = strokedata.loc[:,'spm'] - except KeyError: # pragma: no cover - spm = 0*dist2 - - try: - hr = strokedata.loc[:,'hr'] - except KeyError: # pragma: no cover - hr = 0*spm - pace = strokedata.loc[:,'p']/10. - pace = np.clip(pace,0,1e4) - pace = pace.replace(0,300) - - velo = 500./pace - - try: - power = strokedata.loc[:,'power'] - except KeyError: # pragma: no cover - power = 2.8*velo**3 - - #if power.std() == 0 and power.mean() == 0: - # power = 2.8*velo**3 - - # save csv - # Create data frame with all necessary data to write to csv - df = pd.DataFrame({'TimeStamp (sec)':unixtime, - ' Horizontal (meters)': dist2, - ' Cadence (stokes/min)':spm, - ' HRCur (bpm)':hr, - ' longitude':loncoord, - ' latitude':latcoord, - ' Stroke500mPace (sec/500m)':pace, - ' Power (watts)':power, - ' DragFactor':np.zeros(nr_rows), - ' DriveLength (meters)':np.zeros(nr_rows), - ' StrokeDistance (meters)':strokelength, - ' DriveTime (ms)':np.zeros(nr_rows), - ' StrokeRecoveryTime (ms)':np.zeros(nr_rows), - ' AverageDriveForce (lbs)':np.zeros(nr_rows), - ' PeakDriveForce (lbs)':np.zeros(nr_rows), - ' lapIdx':lapidx, - ' ElapsedTime (sec)':seconds - }) - - - df.sort_values(by='TimeStamp (sec)',ascending=True) - - - timestr = strftime("%Y%m%d-%H%M%S") - - - # Create CSV file name and save data to CSV file - csvfilename ='media/{code}_{importid}.csv'.format( - importid=importid, - code = uuid4().hex[:16] - ) - - res = df.to_csv(csvfilename+'.gz',index_label='index', - compression='gzip') - - - id,message = dataprep.save_workout_database( - csvfilename,r, - dosmooth=r.dosmooth, - workouttype=workouttype, - title=title,notes=comments, - workoutsource=workoutsource, - dosummary=True - ) - - - return id,message def workout_strava_upload(user,w, quick=False,asynchron=True): try: diff --git a/rowers/templatetags/rowerfilters.py b/rowers/templatetags/rowerfilters.py index e63f34ec..ee91bdb0 100644 --- a/rowers/templatetags/rowerfilters.py +++ b/rowers/templatetags/rowerfilters.py @@ -484,21 +484,6 @@ def lookuplong(dict, key): return s -@register.filter -def ualookup(dict, key): - s = dict.get(key) - - if key=='distance': - s = int(float(s)) - - if key=='duration': - s = secondstotimestring(int(s)) - - - if key=='starttime': - s = dateutil.parser.parse(s) - - return s from rowers.models import PlannedSession @register.filter diff --git a/rowers/tests/mocks.py b/rowers/tests/mocks.py index 10e2e1d9..cdcef88e 100644 --- a/rowers/tests/mocks.py +++ b/rowers/tests/mocks.py @@ -340,13 +340,13 @@ def mocked_getsmallrowdata_db_updatecp(*args, **kwargs): return df def mocked_getsmallrowdata_db_setcp(*args, **kwargs): - df = pd.read_csv('rowers/tests/testdata/colsfromdb.csv') + df = pd.read_csv('rowers/tests/testdata/colsfromdb2.csv') return df def mocked_getsmallrowdata_db_water(*args, **kwargs): - df = pd.read_csv('rowers/tests/testdata/colsfromdb.csv') + df = pd.read_csv('rowers/tests/testdata/colsfromdb3.csv') return df diff --git a/rowers/tests/test_async_tasks.py b/rowers/tests/test_async_tasks.py index a327a1c6..23f5fac1 100644 --- a/rowers/tests/test_async_tasks.py +++ b/rowers/tests/test_async_tasks.py @@ -502,15 +502,15 @@ class AsyncTaskTests(TestCase): self.assertEqual(res,1) - @patch('rowers.dataprepnodjango.getsmallrowdata_db_updatecp') - def test_handle_updatecp(self,mocked_getsmallrowdata_db): + @patch('rowers.dataprepnodjango.getsmallrowdata_db') + def test_handle_updatecp(self,mocked_getsmallrowdata_db_updatecp): rower_id = 1 workoutids = [1] res = tasks.handle_updatecp(rower_id,workoutids) self.assertEqual(res,1) - @patch('rowers.dataprepnodjango.getsmallrowdata_db_setcp') - def test_handle_setcp(self,mocked_getsmallrowdata_db): + @patch('rowers.dataprepnodjango.getsmallrowdata_db') + def test_handle_setcp(self,mocked_getsmallrowdata_db_db_setcp): strokesdf = pd.read_csv('rowers/tests/testdata/uhfull.csv') filename = 'rowers/tests/testdata/temp/pq.gz' workoutids = 1 diff --git a/rowers/tests/test_imports.py b/rowers/tests/test_imports.py index e3e863f8..a7ff7f6d 100644 --- a/rowers/tests/test_imports.py +++ b/rowers/tests/test_imports.py @@ -385,39 +385,6 @@ class C2Objects(DjangoTestCase): - @patch('rowers.dataprep.create_engine') - def test_strokedata(self, mocked_sqlalchemy): - with open('rowers/tests/testdata/c2stroketestdata.txt','r') as infile: - res = json.load(infile) - - strokedata = pd.DataFrame.from_dict(res['data']) - - with open('rowers/tests/testdata/c2testdata.txt','r') as infile: - res = json.load(infile) - - data = res['data'] - - from rowers.views import add_workout_from_strokedata - - res = add_workout_from_strokedata(self.u,1,data,strokedata,source='c2') - - @patch('rowers.dataprep.create_engine') - def test_strokedatanohr(self, mocked_sqlalchemy): - with open('rowers/tests/testdata/c2strokedatanohr.txt','r') as infile: - res = json.load(infile) - - strokedata = pd.DataFrame.from_dict(res['data']) - - with open('rowers/tests/testdata/c2testdata.txt','r') as infile: - res = json.load(infile) - - data = res['data'] - - from rowers.views import add_workout_from_strokedata - - - res = add_workout_from_strokedata(self.u,1,data,strokedata,source='c2') - @patch('rowers.tasks.requests.get',side_effect=mocked_requests) @patch('rowers.tasks.requests.post',side_effect=mocked_requests) @patch('rowers.tasks.requests.session', side_effect=mocked_requests) diff --git a/rowers/tests/testdata/colsfromdb2.csv b/rowers/tests/testdata/colsfromdb2.csv new file mode 100644 index 00000000..e87e0ee6 --- /dev/null +++ b/rowers/tests/testdata/colsfromdb2.csv @@ -0,0 +1,1399 @@ +,distance,fpace,workoutid,hr,pace,ftime,spm,time,workoutstate +3,80,03:30.6,1,127.2857143,210600,01:02.5,18.89142857,62500,4 +4,100,03:25.9,1,132.5142857,205900,01:10.8,18.57714286,70799.99995,4 +5,120,03:00.5,1,135.2571429,180500,01:18.0,21.22571429,78000,4 +6,140,02:32.0,1,140,152000,01:24.1,24.74857143,84099.9999,4 +7,160,02:13.2,1,146.0857143,133200,01:29.4,27.41714286,89400.0001,4 +8,180,02:15.6,1,151.9142857,135600,01:34.8,27.46857143,94799.99995,4 +9,200,02:16.0,1,155.6571429,136000,01:40.3,27.24857143,100300,4 +10,220,02:23.8,1,157.1714286,143800,01:46.0,27.2,106000,4 +11,240,02:15.6,1,158.2571429,135600,01:51.4,27.46285714,111400.0001,4 +12,260,02:24.2,1,159.7428571,144200,01:57.2,27.71428571,117200,4 +13,280,02:11.7,1,161.1714286,131700,02:02.5,27.48285714,122500,4 +14,300,02:22.6,1,161.7428571,142600,02:08.2,27.20857143,128200,4 +15,320,02:18.7,1,162.2571429,138700,02:13.7,26.65142857,133700,4 +16,340,02:28.5,1,162.9142857,148500,02:19.6,26.58285714,139599.9999,4 +17,360,02:32.7,1,164,152700,02:25.8,26.19142857,145800,4 +18,380,02:26.9,1,165.0857143,146900,02:31.6,25.69428571,151599.9999,4 +19,400,02:31.6,1,165.8285714,151600,02:37.7,25.55714286,157700,4 +20,420,02:21.0,1,166.0857143,141000,02:43.3,25.83142857,163300,4 +21,440,02:33.5,1,166,153500,02:49.5,26.14857143,169500,4 +22,460,02:35.1,1,165.9142857,155100,02:55.7,26.13714286,175700,4 +23,480,02:25.3,1,166.2571429,145300,03:01.5,26.7,181500,4 +24,500,02:34.7,1,166.7428571,154700,03:07.7,26.58571429,187700,4 +25,520,02:34.7,1,167,154700,03:13.9,26.28857143,193900.0001,4 +26,540,02:32.0,1,167.2571429,152000,03:19.9,25.54,199900.0001,4 +27,560,02:41.0,1,167.6571429,161000,03:26.4,25.30571429,206400.0001,4 +28,580,02:35.1,1,168.3428571,155100,03:32.6,25.35142857,212599.9999,4 +29,600,02:29.2,1,168.8285714,149200,03:38.6,25.90571429,218599.9999,4 +30,620,02:33.1,1,168.7428571,153100,03:44.7,25.97142857,224700,4 +31,640,02:30.4,1,168.6,150400,03:50.7,25.86571429,230700,4 +32,660,02:29.6,1,168.4,149600,03:56.7,25.81142857,236700,4 +33,680,02:28.1,1,168.3428571,148100,04:02.6,25.72571429,242599.9999,4 +34,700,02:27.7,1,167.8285714,147700,04:08.5,25.31714286,248500,4 +35,720,02:30.0,1,168.2571429,150000,04:14.5,25.11714286,254500,4 +36,740,02:28.1,1,168.7428571,148100,04:20.4,25.24285714,260400.0001,4 +37,760,02:34.3,1,169.0857143,154300,04:26.6,25.32857143,266599.9999,4 +38,780,02:23.0,1,169,143000,04:32.3,25.67428571,272300,4 +39,800,02:26.1,1,169,146100,04:38.2,26.05142857,278200,4 +40,820,02:23.4,1,168.9142857,143400,04:43.9,26.58,283900.0001,4 +41,840,02:31.2,1,169.2571429,151200,04:49.9,26.56,289900.0001,4 +42,860,02:23.0,1,169.7428571,143000,04:55.7,26.81714286,295700,4 +43,880,02:30.0,1,170.0857143,150000,05:01.7,27.07714286,301700,4 +44,900,02:26.5,1,170,146500,05:07.5,27.39428571,307500,4 +45,920,02:20.6,1,170,140600,05:13.1,27.06285714,313099.9999,4 +46,940,02:24.2,1,170,144200,05:18.9,26.73714286,318900.0001,4 +47,960,02:18.3,1,170,138300,05:24.4,26.76,324400.0001,4 +48,980,02:19.9,1,170,139900,05:30.0,26.83428571,330000,4 +49,1000,02:16.7,1,169.9142857,136700,05:35.5,27.01714286,335500,4 +50,1020,02:22.2,1,170.2571429,142200,05:41.2,27.38857143,341200,4 +51,1040,02:23.4,1,170.7428571,143400,05:46.9,27.62857143,346900.0001,4 +52,1060,02:15.6,1,171,135600,05:52.3,27.37142857,352300,4 +53,1080,02:18.3,1,171.2571429,138300,05:57.9,27.40285714,357900.0001,4 +54,1100,02:16.7,1,171.7428571,136700,06:03.3,27.36571429,363300,4 +55,1120,02:24.9,1,172.0857143,144900,06:09.1,27.08285714,369099.9999,4 +56,1140,02:18.7,1,172,138700,06:14.7,26.83142857,374700,4 +57,1160,02:21.8,1,172.0857143,141800,06:20.4,26.92285714,380400.0001,4 +58,1180,02:14.4,1,171.7428571,134400,06:25.7,27.00285714,385700,4 +59,1200,02:18.7,1,171.2571429,138700,06:31.3,27.36857143,391300,4 +60,1220,02:10.5,1,170.9142857,130500,06:36.5,27.42571429,396500,4 +61,1240,02:10.9,1,170.9142857,130900,06:41.7,26.94571429,401700,4 +62,1260,02:15.6,1,171.2571429,135600,06:47.2,26.62857143,407200,4 +63,1280,02:12.4,1,171.7428571,132400,06:52.5,26.80285714,412500,4 +64,1300,02:13.2,1,172.0857143,133200,06:57.8,27.13714286,417800,4 +65,1320,02:09.3,1,172,129300,07:03.0,27.50857143,423000,4 +66,1340,02:06.2,1,171.9142857,126200,07:08.0,27.71142857,428000,4 +67,1360,02:16.0,1,172.2571429,136000,07:13.4,27.73142857,433400.0001,4 +68,1380,02:10.9,1,172.7428571,130900,07:18.7,27.68857143,438700,4 +69,1400,02:20.2,1,173.0857143,140200,07:24.3,27.54857143,444300,4 +70,1420,02:09.3,1,173,129300,07:29.5,27.03428571,449500,4 +71,1440,02:06.2,1,172.9142857,126200,07:34.5,26.83714286,454500,4 +72,1460,02:16.0,1,173.2571429,136000,07:39.9,26.74285714,459900.0001,4 +73,1480,02:10.9,1,173.7428571,130900,07:45.2,26.92571429,465200,4 +74,1500,02:10.5,1,174.0857143,130500,07:50.4,26.86571429,470400.0001,4 +75,1520,02:15.6,1,173.9142857,135600,07:55.8,26.92285714,475800,4 +76,1540,02:16.0,1,174.2571429,136000,08:01.3,26.84857143,481300,4 +77,1560,02:20.2,1,174.7428571,140200,08:06.9,26.97428571,486900.0001,4 +78,1580,02:18.3,1,175.0857143,138300,08:12.4,26.74857143,492400.0001,4 +79,1600,02:25.3,1,175.0857143,145300,08:18.2,26.52857143,498200,4 +80,1620,02:28.1,1,174.7428571,148100,08:24.1,26.40571429,504099.9999,4 +81,1640,02:19.9,1,174.2571429,139900,08:29.7,26.29142857,509700,4 +82,1660,02:12.0,1,173.9142857,132000,08:35.0,26.10857143,515000,4 +83,1680,02:20.2,1,174,140200,08:40.6,26.52285714,520599.9999,4 +84,1700,02:18.3,1,174,138300,08:46.1,26.82285714,526099.9999,4 +85,1720,02:24.9,1,174,144900,08:51.9,26.70571429,531900.0001,4 +86,1740,02:17.9,1,174,137900,08:57.5,26.29142857,537500,4 +87,1760,02:26.9,1,174,146900,09:03.3,26.23142857,543300,4 +88,1780,02:23.4,1,173.9142857,143400,09:09.1,26.46285714,549099.9999,4 +89,1800,02:26.9,1,174.2571429,146900,09:14.9,26.78,554900.0001,4 +90,1820,02:28.1,1,174.7428571,148100,09:20.9,26.66285714,560900.0001,4 +91,1840,02:20.2,1,175.0857143,140200,09:26.5,26.38285714,566500,4 +92,1860,02:15.2,1,175,135200,09:31.9,26.30285714,571900.0001,4 +93,1880,02:20.6,1,174.9142857,140600,09:37.5,26.46,577500,4 +94,1900,02:13.2,1,175.3428571,133200,09:42.8,26.49142857,582800,4 +95,1920,02:19.1,1,175.4,139100,09:48.4,26.88571429,588400.0001,4 +96,1940,02:10.5,1,175.6,130500,09:53.6,27.38285714,593599.9999,4 +97,1960,02:14.8,1,175.6571429,134800,09:59.0,27.04,599000,4 +98,1980,02:16.7,1,176.0857143,136700,10:04.5,26.7,604500,4 +99,2000,02:16.7,1,176,136700,10:09.9,26.51142857,609900.0001,4 +100,2020,02:18.3,1,176,138300,10:15.5,26.86571429,615500,4 +101,2040,02:13.2,1,176,133200,10:20.8,27.09142857,620800,4 +102,2060,02:21.0,1,175.9142857,141000,10:26.4,27.39428571,626400.0001,4 +103,2080,02:18.7,1,176.3428571,138700,10:32.0,27.6,632000,4 +104,2100,02:22.2,1,176.4,142200,10:37.7,27.51714286,637700,4 +105,2120,02:15.6,1,176.6,135600,10:43.1,27.26857143,643099.9999,4 +106,2140,02:19.5,1,176.6571429,139500,10:48.7,27.10571429,648700,4 +107,2160,02:14.0,1,177.0857143,134000,10:54.0,27.24285714,654000,4 +108,2180,02:16.3,1,177,136300,10:59.5,27.28571429,659500,4 +109,2200,02:07.7,1,177,127700,11:04.6,27.29428571,664599.9999,4 +110,2220,02:14.0,1,177,134000,11:10.0,27.52857143,670000,4 +111,2240,02:09.7,1,176.9142857,129700,11:15.1,28.00571429,675099.9999,4 +112,2260,02:15.2,1,177.2571429,135200,11:20.6,28.47142857,680599.9999,4 +113,2280,02:09.7,1,177.7428571,129700,11:25.7,28.77428571,685700,4 +114,2300,02:20.6,1,178.0857143,140600,11:31.4,28.68571429,691400.0001,4 +115,2320,02:20.2,1,177.9142857,140200,11:37.0,28.40571429,697000,4 +116,2340,02:19.9,1,178.2571429,139900,11:42.6,28.06857143,702599.9999,4 +117,2360,02:26.1,1,178.7428571,146100,11:48.4,27.66571429,708400.0001,4 +118,2380,02:15.2,1,179.0857143,135200,11:53.8,27.4,713800,4 +119,2400,02:16.3,1,179,136300,11:59.3,27.36857143,719300,4 +120,2420,02:09.7,1,179,129700,12:04.5,27.51428571,724500,4 +121,2440,02:14.4,1,179,134400,12:09.8,27.82857143,729800,4 +122,2460,02:13.6,1,179,133600,12:15.2,27.65714286,735200,4 +123,2480,02:28.5,1,178.9142857,148500,12:21.1,28.05142857,741099.9999,4 +124,2500,02:25.7,1,179.3428571,145700,12:26.9,28.2,746900.0001,4 +125,2520,02:18.7,1,179.4857143,138700,12:32.5,27.49142857,752500,4 +126,2540,02:30.8,1,179.4285714,150800,12:38.5,26.26285714,758500,4 +127,2560,02:25.7,1,178.5714286,145700,12:44.4,25.65428571,764400.0001,4 +128,2580,02:35.9,1,178.6,155900,12:50.6,25.76,770599.9999,4 +129,2600,02:29.2,1,178.4,149200,12:56.6,25.66857143,776599.9999,4 +130,2620,02:26.5,1,178.3428571,146500,13:02.4,25.59142857,782400.0001,4 +131,2640,02:24.9,1,177.9142857,144900,13:08.2,25.26,788200,4 +132,2660,02:30.0,1,178,150000,13:14.2,25.70571429,794200,4 +133,2680,02:25.3,1,178,145300,13:20.0,26.26571429,800000,4 +134,2700,02:22.6,1,178,142600,13:25.7,26.32,805700,4 +135,2720,02:32.0,1,178,152000,13:31.8,25.91714286,811800,4 +136,2740,02:26.1,1,178,146100,13:37.6,25.96857143,817599.9999,4 +137,2760,02:29.2,1,178,149200,13:43.6,26.02,823599.9999,4 +138,2780,02:23.4,1,178.0857143,143400,13:49.4,26.26571429,829400.0001,4 +139,2800,02:26.5,1,177.6571429,146500,13:55.2,26.35142857,835200,4 +140,2820,02:19.1,1,177.5142857,139100,14:00.8,26.14857143,840800,4 +141,2840,02:25.7,1,177.6571429,145700,14:06.6,26.26857143,846599.9999,4 +142,2860,02:18.7,1,178.0857143,138700,14:12.1,27.1,852099.9999,4 +143,2880,02:19.5,1,178,139500,14:17.7,28.33142857,857700,4 +144,2900,02:28.8,1,178,148800,14:23.7,28.55714286,863700,4 +145,2920,02:32.4,1,178,152400,14:29.8,28.26571429,869800,4 +146,2940,02:21.0,1,178,141000,14:35.4,27.36,875400.0001,4 +147,2960,02:23.0,1,178,143000,14:41.1,27.18571429,881099.9999,4 +148,2980,02:30.8,1,177.9142857,150800,14:47.2,27.18285714,887200,4 +149,3000,02:27.7,1,178.3428571,147700,14:53.1,27.18571429,893099.9999,4 +150,3020,02:25.7,1,178.4,145700,14:58.9,26.68285714,898900.0001,4 +151,3040,02:23.0,1,178.6857143,143000,15:04.6,26.50285714,904599.9999,4 +152,3060,02:23.8,1,178.4,143800,15:10.4,26.31142857,910400.0001,4 +153,3080,02:17.1,1,178.3428571,137100,15:15.9,26.28,915900.0001,4 +154,3100,02:23.8,1,177.9142857,143800,15:21.6,26.49142857,921599.9999,4 +155,3120,02:17.1,1,178,137100,15:27.1,26.78857143,927099.9999,4 +156,3140,02:21.4,1,178,141400,15:32.7,26.59142857,932700,4 +157,3160,02:19.5,1,178,139500,15:38.3,26.32857143,938300,4 +158,3180,02:24.2,1,178,144200,15:44.1,26.28,944099.9999,4 +159,3200,02:17.9,1,177.9142857,137900,15:49.6,26.52857143,949599.9999,4 +160,3220,02:23.0,1,178.3428571,143000,15:55.3,26.70571429,955300,4 +161,3240,02:23.8,1,178.4857143,143800,16:01.1,26.63142857,961099.9999,4 +162,3260,02:31.6,1,178.4285714,151600,16:07.1,26.42857143,967099.9999,4 +163,3280,02:28.8,1,177.6571429,148800,16:13.1,26.63428571,973099.9999,4 +164,3300,02:23.4,1,177.2571429,143400,16:18.8,26.91142857,978800,4 +165,3320,02:29.6,1,176.8285714,149600,16:24.8,27.17428571,984800,4 +166,3340,02:19.9,1,177.2571429,139900,16:30.4,26.91428571,990400.0001,4 +167,3360,02:19.1,1,177.7428571,139100,16:36.0,26.72571429,996000,4 +168,3380,02:20.2,1,178.0857143,140200,16:41.6,26.74857143,1001600,4 +169,3400,02:22.6,1,177.9142857,142600,16:47.3,27.23142857,1007300,4 +170,3420,02:24.5,1,178.3428571,144500,16:53.1,27.3,1013100,4 +171,3440,02:19.5,1,178.4857143,139500,16:58.6,27,1018600,4 +172,3460,02:25.7,1,178.3428571,145700,17:04.5,26.54,1024500,4 +173,3480,02:13.6,1,177.9142857,133600,17:09.8,26.55714286,1029800,4 +174,3500,02:18.3,1,178,138300,17:15.3,26.65714286,1035300,4 +175,3520,02:16.0,1,178,136000,17:20.8,26.85714286,1040800,4 +176,3540,02:16.0,1,178,136000,17:26.2,26.88,1046200,4 +177,3560,02:22.6,1,178,142600,17:31.9,27.08285714,1051900,4 +178,3580,02:21.8,1,177.9142857,141800,17:37.6,27.36285714,1057600,4 +179,3600,02:17.1,1,178.2571429,137100,17:43.1,27.56,1063100,4 +180,3620,02:20.2,1,178.7428571,140200,17:48.7,27.68,1068700,4 +181,3640,02:16.3,1,179.0857143,136300,17:54.1,27.63142857,1074100,4 +182,3660,02:20.6,1,179,140600,17:59.8,27.75142857,1079800,4 +183,3680,02:17.9,1,179,137900,18:05.3,27.38571429,1085300,4 +184,3700,02:21.0,1,179,141000,18:10.9,27.30285714,1090900,4 +185,3720,02:16.3,1,179,136300,18:16.4,27.20571429,1096400,4 +186,3740,02:26.9,1,179,146900,18:22.2,27.24,1102200,4 +187,3760,02:32.4,1,179,152400,18:28.3,26.96571429,1108300,4 +188,3780,02:27.7,1,179,147700,18:34.2,26.4,1114200,4 +189,3800,02:33.5,1,178.9142857,153500,18:40.4,26.11428571,1120400,4 +190,3820,02:22.2,1,179.2571429,142200,18:46.1,26.40857143,1126100,4 +191,3840,02:22.2,1,179.7428571,142200,18:51.8,26.98285714,1131800,4 +192,3860,02:30.4,1,180.1714286,150400,18:57.8,27.06285714,1137800,4 +193,3880,02:22.6,1,179.7428571,142600,19:03.5,26.66571429,1143500,4 +194,3900,02:33.5,1,179.2571429,153500,19:09.6,26.30857143,1149600,4 +195,3920,02:29.2,1,178.8285714,149200,19:15.6,26.57714286,1155600,4 +196,3940,02:24.5,1,179.2571429,144500,19:21.4,27.16571429,1161400,4 +197,3960,02:23.4,1,179.7428571,143400,19:27.1,27.26285714,1167100,4 +198,3980,02:17.5,1,180.0857143,137500,19:32.6,27.38571429,1172600,4 +199,4000,02:18.7,1,179.9142857,138700,19:38.2,28.15714286,1178200,4 +200,4020,02:21.4,1,180.2571429,141400,19:43.8,28.81428571,1183800,4 +201,4040,02:18.7,1,180.7428571,138700,19:49.4,29.13714286,1189400,4 +202,4060,02:23.0,1,181.0857143,143000,19:55.1,28.86857143,1195100,4 +203,4080,02:19.5,1,181,139500,20:00.7,28.32857143,1200700,4 +204,4100,02:12.0,1,181,132000,20:05.9,28.18857143,1205900,4 +205,4120,02:14.4,1,181,134400,20:11.3,28.54571429,1211300,4 +206,4140,02:10.1,1,181,130100,20:16.5,27.95714286,1216500,4 +207,4160,02:17.9,1,181,137900,20:22.0,27.20857143,1222000,4 +208,4180,02:10.9,1,180.9142857,130900,20:27.3,27.03142857,1227300,4 +209,4200,02:16.7,1,182.2,136700,20:32.7,27.56285714,1232700,4 +210,4220,02:15.2,1,177.9714286,135200,20:38.1,27.39428571,1238100,4 +211,4240,02:23.4,1,176.7428571,143400,20:43.9,27.29714286,1243900,4 +212,4260,02:14.0,1,178.2285714,134000,20:49.2,27.35714286,1249200,4 +213,4280,02:20.6,1,182.9428571,140600,20:54.9,27.64,1254900,4 +214,4300,02:16.0,1,182,136000,21:00.3,27.76857143,1260300,4 +215,4320,02:19.1,1,182,139100,21:05.9,27.76571429,1265900,4 +216,4340,02:16.0,1,182,136000,21:11.3,27.46285714,1271300,4 +217,4360,02:18.3,1,182,138300,21:16.8,27.41714286,1276800,4 +218,4380,02:12.0,1,182,132000,21:22.1,27.64285714,1282100,4 +219,4400,02:17.5,1,182,137500,21:27.6,28.02857143,1287600,4 +220,4420,02:12.8,1,182,132800,21:32.9,27.86285714,1292900,4 +221,4440,02:19.5,1,182,139500,21:38.5,27.75428571,1298500,4 +222,4460,02:17.9,1,182,137900,21:44.0,27.56285714,1304000,4 +223,4480,02:13.6,1,182,133600,21:49.4,27.65428571,1309400,4 +224,4500,02:17.1,1,182,137100,21:54.8,27.64571429,1314800,4 +225,4520,02:16.3,1,181.9142857,136300,22:00.3,27.66857143,1320300,4 +226,4540,02:20.2,1,182.2571429,140200,22:05.9,27.82,1300.0001,4 +227,4560,02:14.4,1,182.7428571,134400,22:11.3,27.80857143,1331300,4 +228,4580,02:18.7,1,183.0857143,138700,22:16.8,27.68285714,1336800,4 +229,4600,02:12.4,1,183,132400,22:22.1,27.39428571,1342100,4 +230,4620,02:19.1,1,183,139100,22:27.7,27.61428571,1347700,4 +231,4640,02:11.7,1,183,131700,22:32.9,27.66,1352900,4 +232,4660,02:15.2,1,183,135200,22:38.4,27.98285714,1358400,4 +233,4680,02:10.9,1,183,130900,22:43.6,27.84,1363600,4 +234,4700,02:12.8,1,182.9142857,132800,22:48.9,27.81714286,1368900,4 +235,4720,02:13.6,1,183.2571429,133600,22:54.2,27.81428571,1374200,4 +236,4740,02:13.6,1,183.7428571,133600,22:59.6,27.78571429,1379600,4 +237,4760,02:18.7,1,184.0857143,138700,23:05.1,27.76,1385100,4 +238,4780,02:18.3,1,184,138300,23:10.7,27.95142857,1390700,4 +239,4800,02:07.7,1,184,127700,23:15.8,28.25714286,1395800,4 +240,4820,02:11.3,1,184,131300,23:21.0,28.85142857,1401000,4 +241,4840,02:09.3,1,183.9142857,129300,23:26.2,29.72285714,1406200,4 +242,4860,02:09.3,1,184.2571429,129300,23:31.4,30.53142857,1411400,4 +243,4880,02:03.1,1,184.8285714,123100,23:36.3,31.17142857,1416300,4 +244,4900,02:12.8,1,185.1714286,132800,23:41.6,28.64857143,1421600,4 +245,4920,03:32.5,1,183.5714286,212500,23:50.1,23.55428571,1430100,4 +246,4940,04:06.5,1,181.4571429,246500,24:00.0,17.26571429,1440000,4 +247,4960,04:53.0,1,172.3142857,293000,24:11.7,14.90285714,1451700,4 +249,5000,03:50.9,1,152.7714286,230900,24:33.6,18.27714286,1473600,4 +250,5020,03:38.8,1,150.2857143,218800,24:42.3,20.19142857,1482300,4 +251,5040,02:58.5,1,146.8,178500,24:49.5,18.47142857,1489500,4 +252,5060,03:29.0,1,146.4571429,209000,24:57.8,18.4,1497800,4 +253,5080,02:51.1,1,145.5428571,171100,25:04.7,17.55714286,1504700,4 +254,5100,03:15.7,1,144.6,195700,25:12.5,19.71714286,1512500,4 +255,5120,02:49.2,1,143.3428571,169200,25:19.3,20.26571429,1519300,4 +256,5140,02:45.2,1,143.4857143,165200,25:25.9,21.81714286,1525900,4 +257,5160,03:00.5,1,143.1714286,180500,25:33.1,21.63714286,1533100,4 +258,5180,02:47.2,1,141.9142857,167200,25:39.8,21.34,1539800,4 +259,5200,02:57.7,1,141.1714286,177700,25:46.9,21.07714286,1546900,4 +260,5220,02:53.5,1,141.3428571,173500,25:53.8,21.40285714,1553800,4 +261,5240,03:00.9,1,139.5428571,180900,26:01.1,20.84571429,1561100,4 +263,5280,04:33.1,1,136.4571429,273100,26:25.6,21.45714286,1585600,4 +264,5300,03:21.6,1,135.3428571,201600,26:33.7,20.42857143,1593700,4 +265,5320,03:02.0,1,133.3428571,182000,26:41.0,18.96857143,1601000,4 +266,5340,02:43.7,1,134.0857143,163700,26:47.5,20.21428571,1607500,4 +267,5360,02:39.0,1,135.5714286,159000,26:53.9,20.88857143,1613900,4 +268,5380,02:36.3,1,136.0857143,156300,27:00.1,20.68285714,1620100,4 +269,5400,02:37.8,1,136.2571429,157800,27:06.4,20.77142857,1626400,4 +270,5420,02:33.1,1,136.6571429,153100,27:12.6,20.93714286,1639.9999,4 +271,5440,02:36.7,1,137.2571429,156700,27:18.8,20.66,1638800,4 +272,5460,02:44.9,1,138,164900,27:25.4,20.41714286,1645400,4 +273,5480,02:42.1,1,138.7428571,162100,27:31.9,20.78,1651900,4 +274,5500,02:43.7,1,139.1714286,163700,27:38.5,21.37714286,1658500,4 +275,5520,02:36.7,1,140.1714286,156700,27:44.7,20.03142857,1664700,4 +276,5540,02:49.5,1,141.8285714,169500,27:51.5,19.53142857,1671500,4 +277,5560,02:52.7,1,142.9142857,172700,27:58.4,19.91142857,1678400,4 +278,5580,02:44.1,1,143.0857143,164100,28:05.0,21.20571429,1685000,4 +279,5600,02:44.5,1,143,164500,28:11.5,20.60857143,1691500,4 +280,5620,02:53.1,1,143.0857143,173100,28:18.5,20.82,1698500,4 +281,5640,02:40.6,1,142.8285714,160600,28:24.9,20.61714286,1704900,4 +282,5660,03:00.1,1,142.0857143,180100,28:32.1,19.02285714,1712100,4 +283,5680,03:15.3,1,141,195300,28:39.9,17.61714286,1719900,4 +284,5700,03:25.5,1,140.0857143,205500,28:48.1,18.15714286,1728100,4 +285,5720,03:13.0,1,138.7428571,193000,28:55.8,19.87142857,1735800,4 +286,5740,03:05.2,1,137.2571429,185200,29:03.2,19.95142857,1743200,4 +287,5760,02:55.0,1,135.8285714,175000,29:10.2,19.34,1750200,4 +288,5780,03:13.8,1,135.1714286,193800,29:18.0,19.10857143,1758000,4 +289,5800,03:05.2,1,135,185200,29:25.4,19.75428571,1765400,4 +290,5820,02:47.6,1,134.7428571,167600,29:32.1,19.80857143,1772100,4 +291,5840,02:57.7,1,134.1714286,177700,29:39.2,19.02285714,1779200,4 +292,5860,03:04.8,1,134.2571429,184800,29:46.6,17.70571429,1786600,4 +293,5880,03:01.7,1,134.4857143,181700,29:53.9,16.57714286,1793900,4 +294,5900,03:25.5,1,134.1714286,205500,30:02.1,17.24857143,1802100,4 +295,5920,02:58.9,1,134.4285714,178900,30:09.2,17.98857143,1809200,4 +296,5940,02:35.1,1,135.4857143,155100,30:15.5,19.07714286,1815500,4 +297,5960,02:29.6,1,136.0857143,149600,30:21.4,17.96285714,1821400,4 +298,5980,02:36.7,1,136.2571429,156700,30:27.7,18.49714286,1827700,4 +299,6000,03:03.6,1,136.7428571,183600,30:35.0,15.02857143,1835000,4 +300,6020,03:22.7,1,137.1714286,202700,30:43.2,13.74285714,1843200,4 +301,6040,03:20.4,1,136.7428571,200400,30:51.2,15.00571429,1851200,4 +302,6060,02:53.8,1,136.1714286,173800,30:58.1,19.22285714,1858100,4 +303,6080,02:38.2,1,136,158200,31:04.5,20.82,1864500,4 +304,6100,02:30.0,1,137.1714286,150000,31:10.5,20.95428571,1870500,4 +305,6120,02:29.6,1,138.6571429,149600,31:16.4,21.24857143,1876400,4 +306,6140,02:28.5,1,140.3428571,148500,31:22.4,21.18857143,1882400,4 +307,6160,02:27.3,1,141.9142857,147300,31:28.3,21.90857143,1888300,4 +308,6180,02:41.3,1,142.5714286,161300,31:34.7,17.56571429,1894700,4 +309,6200,03:59.9,1,142.6,239900,31:44.3,15.94,1904300,4 +310,6220,03:55.2,1,142.7428571,235200,31:53.7,17.42285714,1913700,4 +311,6240,02:41.7,1,142.8285714,161700,32:00.2,22.17142857,1920200,4 +312,6260,02:26.9,1,143.6285714,146900,32:06.1,22.28571429,1926100,4 +313,6280,03:09.1,1,138.0571429,189100,32:13.6,19.39714286,1933600,4 +315,6320,04:54.2,1,122.2285714,294200,32:51.5,14.22,1971500,4 +316,6340,04:40.1,1,123.2571429,280100,33:02.7,16.01428571,1982700,4 +317,6360,03:45.4,1,124.2285714,225400,33:11.7,16.48,1991700,4 +318,6380,03:25.9,1,125.8571429,205900,33:19.9,16.66571429,1999900,4 +319,6400,03:41.5,1,127.6571429,221500,33:28.8,16.66285714,2008800,4 +320,6420,03:34.5,1,128.4,214500,33:37.3,17.29142857,2017300,4 +321,6440,03:30.2,1,127.6857143,210200,33:45.8,16.38285714,2025800,4 +322,6460,03:04.8,1,128,184800,33:53.1,16.24,2033100,4 +323,6480,02:45.2,1,130,165200,33:59.8,17.13142857,2039800,4 +324,6500,04:58.8,1,130.7428571,298800,34:11.7,17.76857143,2051700,4 +325,6520,04:37.0,1,128.6571429,277000,34:22.8,17.44857143,2062800,4 +326,6540,04:17.0,1,125.6,257000,34:33.1,15.90571429,2073100,4 +327,6560,03:42.3,1,123.6571429,222300,34:42.0,17.48,2082000,4 +328,6580,03:22.4,1,124.4285714,202400,34:50.0,19.24285714,2090000,4 +329,6600,02:48.4,1,126.8285714,168400,34:56.8,20.73428571,2096800,4 +330,6620,02:51.5,1,129.7428571,171500,35:03.6,21.06,2103600,4 +331,6640,02:35.9,1,132.6857143,155900,35:09.9,24.12,2109900,4 +332,6660,02:42.5,1,133.7142857,162500,35:16.4,15.77428571,2116400,4 +334,6700,04:07.3,1,134.2285714,247300,35:34.6,11.19142857,2134600,4 +335,6720,03:03.6,1,134.0857143,183600,35:42.0,20.16,2142000,4 +336,6740,03:04.8,1,131.8285714,184800,35:49.4,19.37714286,2149400,4 +337,6760,03:04.8,1,130.7714286,184800,35:56.8,18.00571429,2156800,4 +338,6780,03:08.7,1,130.0571429,188700,36:04.3,17.85428571,2164300,4 +339,6800,03:06.0,1,129.5142857,186000,36:11.7,18.40571429,2171700,4 +340,6820,03:01.7,1,129.0857143,181700,36:19.0,19.38285714,2179000,4 +341,6840,02:51.5,1,129.7428571,171500,36:25.9,18.68571429,2185900,4 +342,6860,02:54.2,1,130.1714286,174200,36:32.8,18.47142857,2192800,4 +343,6880,02:55.0,1,129.7428571,175000,36:39.8,18.82285714,2199800,4 +344,6900,03:43.8,1,129.1714286,223800,36:48.8,17.32285714,2208800,4 +345,6920,03:35.6,1,129.3428571,215600,36:57.4,16.45428571,2217400,4 +346,6940,03:09.9,1,129.3142857,189900,37:05.0,16.78571429,2225000,4 +347,6960,03:14.2,1,128.2571429,194200,37:12.8,18.57428571,2232800,4 +348,6980,03:18.8,1,127.3428571,198800,37:20.7,18.82,2240700,4 +349,7000,03:27.4,1,127.7428571,207400,37:29.0,18.33428571,2249000,4 +350,7020,03:06.0,1,127.9142857,186000,37:36.5,16.97142857,2256500,4 +351,7040,03:07.5,1,127,187500,37:44.0,17.31428571,2264000,4 +352,7060,03:05.2,1,126.0857143,185200,37:51.4,15.52857143,2271400,4 +353,7080,03:42.7,1,126.1714286,222700,38:00.3,15.28285714,2280300,4 +354,7100,03:29.4,1,126.8285714,209400,38:08.6,16.79714286,2288600,4 +355,7120,03:10.2,1,126.5714286,190200,38:16.3,18.70571429,2296300,4 +356,7140,03:19.2,1,126.9428571,199200,38:24.2,17.78285714,2304200,4 +357,7160,02:56.2,1,128.4857143,176200,38:31.3,18.33142857,2311300,4 +358,7180,02:53.8,1,129.7428571,173800,38:38.2,20.31714286,2318200,4 +359,7200,02:55.8,1,129.1714286,175800,38:45.3,20.25714286,2325300,4 +360,7220,02:43.7,1,129.3428571,163700,38:51.8,20.09714286,2331800,4 +361,7240,02:42.9,1,130.6571429,162900,38:58.3,20.16571429,2338300,4 +362,7260,02:39.4,1,132.1714286,159400,39:04.7,20.67142857,2344700,4 +363,7280,02:35.9,1,132.5714286,155900,39:10.9,21.14857143,2350900,4 +364,7300,02:41.3,1,133.6857143,161300,39:17.4,20.89142857,2357400,4 +365,7320,02:35.9,1,135.6571429,155900,39:23.6,20.22285714,2363600,4 +366,7340,02:37.8,1,137.9142857,157800,39:29.9,20.23428571,2369900,4 +367,7360,02:37.0,1,139.0857143,157000,39:36.2,20.97142857,2376200,4 +368,7380,02:36.7,1,140,156700,39:42.5,20.93714286,2382500,4 +369,7400,02:35.1,1,141.1714286,155100,39:48.7,20.72571429,2388700,4 +370,7420,02:43.3,1,141.5714286,163300,39:55.2,19.34571429,2395200,4 +371,7440,02:59.3,1,141.3428571,179300,40:02.4,19.09714286,2402400,4 +372,7460,03:03.6,1,140.9142857,183600,40:09.7,19.59142857,2409700,4 +373,7480,02:40.6,1,140.9142857,160600,40:16.1,21.23142857,2416100,4 +374,7500,02:48.8,1,141.2571429,168800,40:22.9,21.16571429,2422900,4 +375,7520,02:39.0,1,141.8285714,159000,40:29.3,21.35428571,2429300,4 +376,7540,02:33.9,1,141.9142857,153900,40:35.4,21.19142857,2435400,4 +377,7560,02:47.6,1,141.0857143,167600,40:42.1,20.27428571,2442100,4 +378,7580,03:02.0,1,140.1714286,182000,40:49.4,19.01714286,2449400,4 +379,7600,03:09.5,1,138.4857143,189500,40:57.0,16.88,2457000,4 +380,7620,03:34.9,1,136.6,214900,41:05.6,14.68,2465600,4 +381,7640,03:27.4,1,134.5714286,207400,41:13.9,15.78285714,2473900,4 +382,7660,03:04.8,1,133.3428571,184800,41:21.3,18.14857143,2481300,4 +383,7680,03:11.8,1,131.8285714,191800,41:28.9,18.93428571,2488900,4 +384,7700,03:24.3,1,129.8285714,204300,41:37.1,20.09714286,2497100,4 +385,7720,03:25.9,1,127.2571429,205900,41:45.3,22.05428571,2505300,4 +386,7740,03:39.2,1,124.7428571,219200,41:54.1,20.40571429,2514100,4 +387,7760,04:09.6,1,123.3428571,249600,42:04.1,17.76,2524100,4 +388,7780,03:13.8,1,122.8285714,193800,42:11.8,17.50857143,2531800,4 +389,7800,03:03.2,1,122.7428571,183200,42:19.2,18.88571429,2539200,4 +390,7820,02:44.5,1,123.6857143,164500,42:25.7,19.37142857,2545700,4 +391,7840,02:35.5,1,125.5714286,155500,42:32.0,19.36,2552000,4 +392,7860,02:46.4,1,126.6571429,166400,42:38.6,18.94571429,2558600,4 +393,7880,02:53.1,1,126.5142857,173100,42:45.5,18.05714286,2565500,4 +394,7900,02:58.5,1,127,178500,42:52.7,18.42571429,2572700,4 +395,7920,02:50.7,1,127.5714286,170700,42:59.5,19.13428571,2579500,4 +396,7940,03:16.1,1,127.4285714,196100,43:07.3,18.88857143,2587300,4 +397,7960,03:12.6,1,126.6571429,192600,43:15.0,17.72285714,2595000,4 +398,7980,03:09.9,1,127.4571429,189900,43:22.6,17.56571429,2602600,4 +399,8000,03:21.2,1,120.9428571,201200,43:30.7,17.82571429,2610700,4 +400,8020,03:07.1,1,119.8,187100,43:38.2,17.67142857,2618200,4 +401,8040,02:55.0,1,122.6,175000,43:45.2,17.52571429,2625200,4 +402,8060,03:00.5,1,128.0285714,180500,43:52.4,19.36571429,2632400,4 +404,8100,03:02.8,1,125.4,182800,44:11.9,19.29714286,2651900,4 +405,8120,02:57.0,1,125,177000,44:19.0,18.31428571,2659000,4 +406,8140,03:05.6,1,124.5142857,185600,44:26.4,18.44285714,2666400,4 +407,8160,03:12.6,1,124.5714286,192600,44:34.1,18.39142857,2674100,4 +408,8180,03:02.0,1,123.8285714,182000,44:41.4,15.79714286,2681400,4 +409,8200,03:57.5,1,122.3428571,237500,44:50.9,15.76,2690900,4 +410,8220,03:24.3,1,122.0857143,204300,44:59.1,17.60571429,2699100,4 +411,8240,03:09.9,1,122.5714286,189900,45:06.7,19.90857143,2706700,4 +412,8260,02:55.4,1,123.3428571,175400,45:13.7,19.60857143,2713700,4 +413,8280,02:48.8,1,125.1714286,168800,45:20.5,20.53428571,2720500,4 +414,8300,02:45.6,1,127.5714286,165600,45:27.1,21.03714286,2727100,4 +415,8320,02:48.8,1,129.0857143,168800,45:33.8,20.94,2733800,4 +416,8340,02:45.2,1,130.3428571,165200,45:40.4,20.74285714,2740400,4 +417,8360,02:44.5,1,131.4857143,164500,45:47.0,21.22285714,2747000,4 +418,8380,02:44.1,1,132.4285714,164100,45:53.6,20.41428571,2753600,4 +419,8400,02:46.8,1,132.5714286,166800,46:00.3,20.10857143,2760300,4 +420,8420,02:39.4,1,133.6857143,159400,46:06.6,20.84,2766600,4 +421,8440,02:49.9,1,134.2285714,169900,46:13.4,19.14857143,2773400,4 +422,8460,03:00.9,1,134.4285714,180900,46:20.7,18.04285714,2780700,4 +423,8480,02:56.6,1,134.0857143,176600,46:27.7,17.96285714,2787700,4 +424,8500,02:55.0,1,133.4857143,175000,46:34.7,19.39428571,2794700,4 +425,8520,02:56.2,1,132.5142857,176200,46:41.8,19.5,2801800,4 +426,8540,02:53.8,1,131.7428571,173800,46:48.7,19.76285714,2808700,4 +427,8560,02:46.4,1,132.4285714,166400,46:55.4,19.37714286,2815400,4 +428,8580,02:42.5,1,132.3142857,162500,47:01.9,19.22571429,2821900,4 +429,8600,02:57.0,1,131.3428571,177000,47:09.0,19.37428571,2829000,4 +430,8620,03:09.9,1,130,189900,47:16.5,19.66571429,2836500,4 +431,8640,02:49.9,1,130.3428571,169900,47:23.3,18.85714286,2843300,4 +432,8660,02:46.4,1,130.4,166400,47:30.0,19.05714286,2850000,4 +433,8680,02:50.3,1,129.0857143,170300,47:36.8,17.12285714,2856800,4 +434,8700,02:58.1,1,127.4285714,178100,47:43.9,17.06571429,2863900,4 +435,8720,03:07.9,1,126.4857143,187900,47:51.5,17.68,2871500,4 +436,8740,02:58.1,1,126.4285714,178100,47:58.6,20.31428571,2878600,4 +437,8760,02:55.4,1,127,175400,48:05.6,18.96857143,2885600,4 +438,8780,03:12.6,1,127.4857143,192600,48:13.3,18.59714286,2893300,4 +439,8800,03:05.2,1,127.2571429,185200,48:20.7,19.44,2900700,4 +440,8820,02:58.9,1,128.8571429,178900,48:27.9,21.48857143,2907900,4 +441,8840,02:45.6,1,130.6285714,165600,48:34.5,18.81714286,2914500,4 +442,8860,03:02.4,1,130.7714286,182400,48:41.8,16.06,2921800,4 +443,8880,03:28.6,1,128.5714286,208600,48:50.1,15.00857143,2930100,4 +444,8900,03:20.8,1,127.4285714,200800,48:58.2,17.34571429,2938200,4 +445,8920,02:52.7,1,126.8285714,172700,49:05.1,18.52571429,2945100,4 +446,8940,02:50.3,1,127,170300,49:11.9,19.74857143,2951900,4 +447,8960,02:54.6,1,127,174600,49:18.9,20.26571429,2958900,4 +448,8980,02:47.6,1,126.8285714,167600,49:25.6,20.20571429,2965600,4 +449,9000,02:43.7,1,127.2571429,163700,49:32.1,19.37142857,2972100,4 +450,9020,02:46.0,1,129.0857143,166000,49:38.8,19.47142857,2978800,4 +451,9040,02:57.0,1,131.8285714,177000,49:45.8,20.43714286,2985800,4 +452,9060,02:35.5,1,133.8285714,155500,49:52.1,20.92857143,2992100,4 +453,9080,02:28.8,1,135.3428571,148800,49:58.0,20.89714286,2998000,4 +454,9100,02:30.4,1,136.7428571,150400,50:04.0,21.40285714,3004000,4 +455,9120,02:26.5,1,138.0857143,146500,50:09.9,22.31142857,3009900,4 +456,9140,02:26.9,1,138.9142857,146900,50:15.8,22.7,3015800,4 +457,9160,02:36.7,1,140.2571429,156700,50:22.0,22.59428571,3022000,4 +458,9180,02:30.0,1,141.7428571,150000,50:28.0,22.43142857,3028000,4 +459,9200,02:29.2,1,143.0857143,149200,50:34.0,22.20857143,3034000,4 +460,9220,02:27.3,1,144.2571429,147300,50:39.9,21.71142857,3039900,4 +461,9240,02:35.5,1,146.0285714,155500,50:46.1,23.12857143,3046100,4 +462,9260,03:08.3,1,138.9714286,188300,50:53.6,22.98857143,3053600,4 +463,9280,04:01.4,1,126.3428571,241400,51:03.3,13.11142857,3063300,4 +465,9320,03:36.4,1,117.5714286,216400,51:25.0,11.70571429,3085000,4 +466,9340,03:51.3,1,119.9142857,231300,51:34.3,19.73714286,3094300,4 +467,9360,03:22.0,1,122.0857143,202000,51:42.3,18.46857143,3102300,4 +468,9380,03:16.1,1,125.7142857,196100,51:50.2,15.80285714,3110200,4 +469,9400,03:25.9,1,118.5714286,205900,51:58.4,16.25428571,3118400,4 +471,9440,03:14.2,1,110.0285714,194200,52:23.5,20.32285714,3143500,4 +472,9460,02:58.9,1,118.1428571,178900,52:30.7,19.28285714,3150700,4 +473,9480,02:50.3,1,122.3142857,170300,52:37.5,17.68,3157500,4 +474,9500,04:10.0,1,127.4571429,250000,52:47.5,17.38,3167500,4 +475,9520,03:45.0,1,126.8857143,225000,52:56.5,16.28,3176500,4 +479,80,03:30.6,2,127.2857143,210600,01:02.5,18.89142857,62500,4 +480,100,03:25.9,2,132.5142857,205900,01:10.8,18.57714286,70799.99995,4 +481,120,03:00.5,2,135.2571429,180500,01:18.0,21.22571429,78000,4 +482,140,02:32.0,2,140,152000,01:24.1,24.74857143,84099.9999,4 +483,160,02:13.2,2,146.0857143,133200,01:29.4,27.41714286,89400.0001,4 +484,180,02:15.6,2,151.9142857,135600,01:34.8,27.46857143,94799.99995,4 +485,200,02:16.0,2,155.6571429,136000,01:40.3,27.24857143,100300,4 +486,220,02:23.8,2,157.1714286,143800,01:46.0,27.2,106000,4 +487,240,02:15.6,2,158.2571429,135600,01:51.4,27.46285714,111400.0001,4 +488,260,02:24.2,2,159.7428571,144200,01:57.2,27.71428571,117200,4 +489,280,02:11.7,2,161.1714286,131700,02:02.5,27.48285714,122500,4 +490,300,02:22.6,2,161.7428571,142600,02:08.2,27.20857143,128200,4 +491,320,02:18.7,2,162.2571429,138700,02:13.7,26.65142857,133700,4 +492,340,02:28.5,2,162.9142857,148500,02:19.6,26.58285714,139599.9999,4 +493,360,02:32.7,2,164,152700,02:25.8,26.19142857,145800,4 +494,380,02:26.9,2,165.0857143,146900,02:31.6,25.69428571,151599.9999,4 +495,400,02:31.6,2,165.8285714,151600,02:37.7,25.55714286,157700,4 +496,420,02:21.0,2,166.0857143,141000,02:43.3,25.83142857,163300,4 +497,440,02:33.5,2,166,153500,02:49.5,26.14857143,169500,4 +498,460,02:35.1,2,165.9142857,155100,02:55.7,26.13714286,175700,4 +499,480,02:25.3,2,166.2571429,145300,03:01.5,26.7,181500,4 +500,500,02:34.7,2,166.7428571,154700,03:07.7,26.58571429,187700,4 +501,520,02:34.7,2,167,154700,03:13.9,26.28857143,193900.0001,4 +502,540,02:32.0,2,167.2571429,152000,03:19.9,25.54,199900.0001,4 +503,560,02:41.0,2,167.6571429,161000,03:26.4,25.30571429,206400.0001,4 +504,580,02:35.1,2,168.3428571,155100,03:32.6,25.35142857,212599.9999,4 +505,600,02:29.2,2,168.8285714,149200,03:38.6,25.90571429,218599.9999,4 +506,620,02:33.1,2,168.7428571,153100,03:44.7,25.97142857,224700,4 +507,640,02:30.4,2,168.6,150400,03:50.7,25.86571429,230700,4 +508,660,02:29.6,2,168.4,149600,03:56.7,25.81142857,236700,4 +509,680,02:28.1,2,168.3428571,148100,04:02.6,25.72571429,242599.9999,4 +510,700,02:27.7,2,167.8285714,147700,04:08.5,25.31714286,248500,4 +511,720,02:30.0,2,168.2571429,150000,04:14.5,25.11714286,254500,4 +512,740,02:28.1,2,168.7428571,148100,04:20.4,25.24285714,260400.0001,4 +513,760,02:34.3,2,169.0857143,154300,04:26.6,25.32857143,266599.9999,4 +514,780,02:23.0,2,169,143000,04:32.3,25.67428571,272300,4 +515,800,02:26.1,2,169,146100,04:38.2,26.05142857,278200,4 +516,820,02:23.4,2,168.9142857,143400,04:43.9,26.58,283900.0001,4 +517,840,02:31.2,2,169.2571429,151200,04:49.9,26.56,289900.0001,4 +518,860,02:23.0,2,169.7428571,143000,04:55.7,26.81714286,295700,4 +519,880,02:30.0,2,170.0857143,150000,05:01.7,27.07714286,301700,4 +520,900,02:26.5,2,170,146500,05:07.5,27.39428571,307500,4 +521,920,02:20.6,2,170,140600,05:13.1,27.06285714,313099.9999,4 +522,940,02:24.2,2,170,144200,05:18.9,26.73714286,318900.0001,4 +523,960,02:18.3,2,170,138300,05:24.4,26.76,324400.0001,4 +524,980,02:19.9,2,170,139900,05:30.0,26.83428571,330000,4 +525,1000,02:16.7,2,169.9142857,136700,05:35.5,27.01714286,335500,4 +526,1020,02:22.2,2,170.2571429,142200,05:41.2,27.38857143,341200,4 +527,1040,02:23.4,2,170.7428571,143400,05:46.9,27.62857143,346900.0001,4 +528,1060,02:15.6,2,171,135600,05:52.3,27.37142857,352300,4 +529,1080,02:18.3,2,171.2571429,138300,05:57.9,27.40285714,357900.0001,4 +530,1100,02:16.7,2,171.7428571,136700,06:03.3,27.36571429,363300,4 +531,1120,02:24.9,2,172.0857143,144900,06:09.1,27.08285714,369099.9999,4 +532,1140,02:18.7,2,172,138700,06:14.7,26.83142857,374700,4 +533,1160,02:21.8,2,172.0857143,141800,06:20.4,26.92285714,380400.0001,4 +534,1180,02:14.4,2,171.7428571,134400,06:25.7,27.00285714,385700,4 +535,1200,02:18.7,2,171.2571429,138700,06:31.3,27.36857143,391300,4 +536,1220,02:10.5,2,170.9142857,130500,06:36.5,27.42571429,396500,4 +537,1240,02:10.9,2,170.9142857,130900,06:41.7,26.94571429,401700,4 +538,1260,02:15.6,2,171.2571429,135600,06:47.2,26.62857143,407200,4 +539,1280,02:12.4,2,171.7428571,132400,06:52.5,26.80285714,412500,4 +540,1300,02:13.2,2,172.0857143,133200,06:57.8,27.13714286,417800,4 +541,1320,02:09.3,2,172,129300,07:03.0,27.50857143,423000,4 +542,1340,02:06.2,2,171.9142857,126200,07:08.0,27.71142857,428000,4 +543,1360,02:16.0,2,172.2571429,136000,07:13.4,27.73142857,433400.0001,4 +544,1380,02:10.9,2,172.7428571,130900,07:18.7,27.68857143,438700,4 +545,1400,02:20.2,2,173.0857143,140200,07:24.3,27.54857143,444300,4 +546,1420,02:09.3,2,173,129300,07:29.5,27.03428571,449500,4 +547,1440,02:06.2,2,172.9142857,126200,07:34.5,26.83714286,454500,4 +548,1460,02:16.0,2,173.2571429,136000,07:39.9,26.74285714,459900.0001,4 +549,1480,02:10.9,2,173.7428571,130900,07:45.2,26.92571429,465200,4 +550,1500,02:10.5,2,174.0857143,130500,07:50.4,26.86571429,470400.0001,4 +551,1520,02:15.6,2,173.9142857,135600,07:55.8,26.92285714,475800,4 +552,1540,02:16.0,2,174.2571429,136000,08:01.3,26.84857143,481300,4 +553,1560,02:20.2,2,174.7428571,140200,08:06.9,26.97428571,486900.0001,4 +554,1580,02:18.3,2,175.0857143,138300,08:12.4,26.74857143,492400.0001,4 +555,1600,02:25.3,2,175.0857143,145300,08:18.2,26.52857143,498200,4 +556,1620,02:28.1,2,174.7428571,148100,08:24.1,26.40571429,504099.9999,4 +557,1640,02:19.9,2,174.2571429,139900,08:29.7,26.29142857,509700,4 +558,1660,02:12.0,2,173.9142857,132000,08:35.0,26.10857143,515000,4 +559,1680,02:20.2,2,174,140200,08:40.6,26.52285714,520599.9999,4 +560,1700,02:18.3,2,174,138300,08:46.1,26.82285714,526099.9999,4 +561,1720,02:24.9,2,174,144900,08:51.9,26.70571429,531900.0001,4 +562,1740,02:17.9,2,174,137900,08:57.5,26.29142857,537500,4 +563,1760,02:26.9,2,174,146900,09:03.3,26.23142857,543300,4 +564,1780,02:23.4,2,173.9142857,143400,09:09.1,26.46285714,549099.9999,4 +565,1800,02:26.9,2,174.2571429,146900,09:14.9,26.78,554900.0001,4 +566,1820,02:28.1,2,174.7428571,148100,09:20.9,26.66285714,560900.0001,4 +567,1840,02:20.2,2,175.0857143,140200,09:26.5,26.38285714,566500,4 +568,1860,02:15.2,2,175,135200,09:31.9,26.30285714,571900.0001,4 +569,1880,02:20.6,2,174.9142857,140600,09:37.5,26.46,577500,4 +570,1900,02:13.2,2,175.3428571,133200,09:42.8,26.49142857,582800,4 +571,1920,02:19.1,2,175.4,139100,09:48.4,26.88571429,588400.0001,4 +572,1940,02:10.5,2,175.6,130500,09:53.6,27.38285714,593599.9999,4 +573,1960,02:14.8,2,175.6571429,134800,09:59.0,27.04,599000,4 +574,1980,02:16.7,2,176.0857143,136700,10:04.5,26.7,604500,4 +575,2000,02:16.7,2,176,136700,10:09.9,26.51142857,609900.0001,4 +576,2020,02:18.3,2,176,138300,10:15.5,26.86571429,615500,4 +577,2040,02:13.2,2,176,133200,10:20.8,27.09142857,620800,4 +578,2060,02:21.0,2,175.9142857,141000,10:26.4,27.39428571,626400.0001,4 +579,2080,02:18.7,2,176.3428571,138700,10:32.0,27.6,632000,4 +580,2100,02:22.2,2,176.4,142200,10:37.7,27.51714286,637700,4 +581,2120,02:15.6,2,176.6,135600,10:43.1,27.26857143,643099.9999,4 +582,2140,02:19.5,2,176.6571429,139500,10:48.7,27.10571429,648700,4 +583,2160,02:14.0,2,177.0857143,134000,10:54.0,27.24285714,654000,4 +584,2180,02:16.3,2,177,136300,10:59.5,27.28571429,659500,4 +585,2200,02:07.7,2,177,127700,11:04.6,27.29428571,664599.9999,4 +586,2220,02:14.0,2,177,134000,11:10.0,27.52857143,670000,4 +587,2240,02:09.7,2,176.9142857,129700,11:15.1,28.00571429,675099.9999,4 +588,2260,02:15.2,2,177.2571429,135200,11:20.6,28.47142857,680599.9999,4 +589,2280,02:09.7,2,177.7428571,129700,11:25.7,28.77428571,685700,4 +590,2300,02:20.6,2,178.0857143,140600,11:31.4,28.68571429,691400.0001,4 +591,2320,02:20.2,2,177.9142857,140200,11:37.0,28.40571429,697000,4 +592,2340,02:19.9,2,178.2571429,139900,11:42.6,28.06857143,702599.9999,4 +593,2360,02:26.1,2,178.7428571,146100,11:48.4,27.66571429,708400.0001,4 +594,2380,02:15.2,2,179.0857143,135200,11:53.8,27.4,713800,4 +595,2400,02:16.3,2,179,136300,11:59.3,27.36857143,719300,4 +596,2420,02:09.7,2,179,129700,12:04.5,27.51428571,724500,4 +597,2440,02:14.4,2,179,134400,12:09.8,27.82857143,729800,4 +598,2460,02:13.6,2,179,133600,12:15.2,27.65714286,735200,4 +599,2480,02:28.5,2,178.9142857,148500,12:21.1,28.05142857,741099.9999,4 +600,2500,02:25.7,2,179.3428571,145700,12:26.9,28.2,746900.0001,4 +601,2520,02:18.7,2,179.4857143,138700,12:32.5,27.49142857,752500,4 +602,2540,02:30.8,2,179.4285714,150800,12:38.5,26.26285714,758500,4 +603,2560,02:25.7,2,178.5714286,145700,12:44.4,25.65428571,764400.0001,4 +604,2580,02:35.9,2,178.6,155900,12:50.6,25.76,770599.9999,4 +605,2600,02:29.2,2,178.4,149200,12:56.6,25.66857143,776599.9999,4 +606,2620,02:26.5,2,178.3428571,146500,13:02.4,25.59142857,782400.0001,4 +607,2640,02:24.9,2,177.9142857,144900,13:08.2,25.26,788200,4 +608,2660,02:30.0,2,178,150000,13:14.2,25.70571429,794200,4 +609,2680,02:25.3,2,178,145300,13:20.0,26.26571429,800000,4 +610,2700,02:22.6,2,178,142600,13:25.7,26.32,805700,4 +611,2720,02:32.0,2,178,152000,13:31.8,25.91714286,811800,4 +612,2740,02:26.1,2,178,146100,13:37.6,25.96857143,817599.9999,4 +613,2760,02:29.2,2,178,149200,13:43.6,26.02,823599.9999,4 +614,2780,02:23.4,2,178.0857143,143400,13:49.4,26.26571429,829400.0001,4 +615,2800,02:26.5,2,177.6571429,146500,13:55.2,26.35142857,835200,4 +616,2820,02:19.1,2,177.5142857,139100,14:00.8,26.14857143,840800,4 +617,2840,02:25.7,2,177.6571429,145700,14:06.6,26.26857143,846599.9999,4 +618,2860,02:18.7,2,178.0857143,138700,14:12.1,27.1,852099.9999,4 +619,2880,02:19.5,2,178,139500,14:17.7,28.33142857,857700,4 +620,2900,02:28.8,2,178,148800,14:23.7,28.55714286,863700,4 +621,2920,02:32.4,2,178,152400,14:29.8,28.26571429,869800,4 +622,2940,02:21.0,2,178,141000,14:35.4,27.36,875400.0001,4 +623,2960,02:23.0,2,178,143000,14:41.1,27.18571429,881099.9999,4 +624,2980,02:30.8,2,177.9142857,150800,14:47.2,27.18285714,887200,4 +625,3000,02:27.7,2,178.3428571,147700,14:53.1,27.18571429,893099.9999,4 +626,3020,02:25.7,2,178.4,145700,14:58.9,26.68285714,898900.0001,4 +627,3040,02:23.0,2,178.6857143,143000,15:04.6,26.50285714,904599.9999,4 +628,3060,02:23.8,2,178.4,143800,15:10.4,26.31142857,910400.0001,4 +629,3080,02:17.1,2,178.3428571,137100,15:15.9,26.28,915900.0001,4 +630,3100,02:23.8,2,177.9142857,143800,15:21.6,26.49142857,921599.9999,4 +631,3120,02:17.1,2,178,137100,15:27.1,26.78857143,927099.9999,4 +632,3140,02:21.4,2,178,141400,15:32.7,26.59142857,932700,4 +633,3160,02:19.5,2,178,139500,15:38.3,26.32857143,938300,4 +634,3180,02:24.2,2,178,144200,15:44.1,26.28,944099.9999,4 +635,3200,02:17.9,2,177.9142857,137900,15:49.6,26.52857143,949599.9999,4 +636,3220,02:23.0,2,178.3428571,143000,15:55.3,26.70571429,955300,4 +637,3240,02:23.8,2,178.4857143,143800,16:01.1,26.63142857,961099.9999,4 +638,3260,02:31.6,2,178.4285714,151600,16:07.1,26.42857143,967099.9999,4 +639,3280,02:28.8,2,177.6571429,148800,16:13.1,26.63428571,973099.9999,4 +640,3300,02:23.4,2,177.2571429,143400,16:18.8,26.91142857,978800,4 +641,3320,02:29.6,2,176.8285714,149600,16:24.8,27.17428571,984800,4 +642,3340,02:19.9,2,177.2571429,139900,16:30.4,26.91428571,990400.0001,4 +643,3360,02:19.1,2,177.7428571,139100,16:36.0,26.72571429,996000,4 +644,3380,02:20.2,2,178.0857143,140200,16:41.6,26.74857143,1001600,4 +645,3400,02:22.6,2,177.9142857,142600,16:47.3,27.23142857,1007300,4 +646,3420,02:24.5,2,178.3428571,144500,16:53.1,27.3,1013100,4 +647,3440,02:19.5,2,178.4857143,139500,16:58.6,27,1018600,4 +648,3460,02:25.7,2,178.3428571,145700,17:04.5,26.54,1024500,4 +649,3480,02:13.6,2,177.9142857,133600,17:09.8,26.55714286,1029800,4 +650,3500,02:18.3,2,178,138300,17:15.3,26.65714286,1035300,4 +651,3520,02:16.0,2,178,136000,17:20.8,26.85714286,1040800,4 +652,3540,02:16.0,2,178,136000,17:26.2,26.88,1046200,4 +653,3560,02:22.6,2,178,142600,17:31.9,27.08285714,1051900,4 +654,3580,02:21.8,2,177.9142857,141800,17:37.6,27.36285714,1057600,4 +655,3600,02:17.1,2,178.2571429,137100,17:43.1,27.56,1063100,4 +656,3620,02:20.2,2,178.7428571,140200,17:48.7,27.68,1068700,4 +657,3640,02:16.3,2,179.0857143,136300,17:54.1,27.63142857,1074100,4 +658,3660,02:20.6,2,179,140600,17:59.8,27.75142857,1079800,4 +659,3680,02:17.9,2,179,137900,18:05.3,27.38571429,1085300,4 +660,3700,02:21.0,2,179,141000,18:10.9,27.30285714,1090900,4 +661,3720,02:16.3,2,179,136300,18:16.4,27.20571429,1096400,4 +662,3740,02:26.9,2,179,146900,18:22.2,27.24,1102200,4 +663,3760,02:32.4,2,179,152400,18:28.3,26.96571429,1108300,4 +664,3780,02:27.7,2,179,147700,18:34.2,26.4,1114200,4 +665,3800,02:33.5,2,178.9142857,153500,18:40.4,26.11428571,1120400,4 +666,3820,02:22.2,2,179.2571429,142200,18:46.1,26.40857143,1126100,4 +667,3840,02:22.2,2,179.7428571,142200,18:51.8,26.98285714,1131800,4 +668,3860,02:30.4,2,180.1714286,150400,18:57.8,27.06285714,1137800,4 +669,3880,02:22.6,2,179.7428571,142600,19:03.5,26.66571429,1143500,4 +670,3900,02:33.5,2,179.2571429,153500,19:09.6,26.30857143,1149600,4 +671,3920,02:29.2,2,178.8285714,149200,19:15.6,26.57714286,1155600,4 +672,3940,02:24.5,2,179.2571429,144500,19:21.4,27.16571429,1161400,4 +673,3960,02:23.4,2,179.7428571,143400,19:27.1,27.26285714,1167100,4 +674,3980,02:17.5,2,180.0857143,137500,19:32.6,27.38571429,1172600,4 +675,4000,02:18.7,2,179.9142857,138700,19:38.2,28.15714286,1178200,4 +676,4020,02:21.4,2,180.2571429,141400,19:43.8,28.81428571,1183800,4 +677,4040,02:18.7,2,180.7428571,138700,19:49.4,29.13714286,1189400,4 +678,4060,02:23.0,2,181.0857143,143000,19:55.1,28.86857143,1195100,4 +679,4080,02:19.5,2,181,139500,20:00.7,28.32857143,1200700,4 +680,4100,02:12.0,2,181,132000,20:05.9,28.18857143,1205900,4 +681,4120,02:14.4,2,181,134400,20:11.3,28.54571429,1211300,4 +682,4140,02:10.1,2,181,130100,20:16.5,27.95714286,1216500,4 +683,4160,02:17.9,2,181,137900,20:22.0,27.20857143,1222000,4 +684,4180,02:10.9,2,180.9142857,130900,20:27.3,27.03142857,1227300,4 +685,4200,02:16.7,2,182.2,136700,20:32.7,27.56285714,1232700,4 +686,4220,02:15.2,2,177.9714286,135200,20:38.1,27.39428571,1238100,4 +687,4240,02:23.4,2,176.7428571,143400,20:43.9,27.29714286,1243900,4 +688,4260,02:14.0,2,178.2285714,134000,20:49.2,27.35714286,1249200,4 +689,4280,02:20.6,2,182.9428571,140600,20:54.9,27.64,1254900,4 +690,4300,02:16.0,2,182,136000,21:00.3,27.76857143,1260300,4 +691,4320,02:19.1,2,182,139100,21:05.9,27.76571429,1265900,4 +692,4340,02:16.0,2,182,136000,21:11.3,27.46285714,1271300,4 +693,4360,02:18.3,2,182,138300,21:16.8,27.41714286,1276800,4 +694,4380,02:12.0,2,182,132000,21:22.1,27.64285714,1282100,4 +695,4400,02:17.5,2,182,137500,21:27.6,28.02857143,1287600,4 +696,4420,02:12.8,2,182,132800,21:32.9,27.86285714,1292900,4 +697,4440,02:19.5,2,182,139500,21:38.5,27.75428571,1298500,4 +698,4460,02:17.9,2,182,137900,21:44.0,27.56285714,1304000,4 +699,4480,02:13.6,2,182,133600,21:49.4,27.65428571,1309400,4 +700,4500,02:17.1,2,182,137100,21:54.8,27.64571429,1314800,4 +701,4520,02:16.3,2,181.9142857,136300,22:00.3,27.66857143,1320300,4 +702,4540,02:20.2,2,182.2571429,140200,22:05.9,27.82,1300.0001,4 +703,4560,02:14.4,2,182.7428571,134400,22:11.3,27.80857143,1331300,4 +704,4580,02:18.7,2,183.0857143,138700,22:16.8,27.68285714,1336800,4 +705,4600,02:12.4,2,183,132400,22:22.1,27.39428571,1342100,4 +706,4620,02:19.1,2,183,139100,22:27.7,27.61428571,1347700,4 +707,4640,02:11.7,2,183,131700,22:32.9,27.66,1352900,4 +708,4660,02:15.2,2,183,135200,22:38.4,27.98285714,1358400,4 +709,4680,02:10.9,2,183,130900,22:43.6,27.84,1363600,4 +710,4700,02:12.8,2,182.9142857,132800,22:48.9,27.81714286,1368900,4 +711,4720,02:13.6,2,183.2571429,133600,22:54.2,27.81428571,1374200,4 +712,4740,02:13.6,2,183.7428571,133600,22:59.6,27.78571429,1379600,4 +713,4760,02:18.7,2,184.0857143,138700,23:05.1,27.76,1385100,4 +714,4780,02:18.3,2,184,138300,23:10.7,27.95142857,1390700,4 +715,4800,02:07.7,2,184,127700,23:15.8,28.25714286,1395800,4 +716,4820,02:11.3,2,184,131300,23:21.0,28.85142857,1401000,4 +717,4840,02:09.3,2,183.9142857,129300,23:26.2,29.72285714,1406200,4 +718,4860,02:09.3,2,184.2571429,129300,23:31.4,30.53142857,1411400,4 +719,4880,02:03.1,2,184.8285714,123100,23:36.3,31.17142857,1416300,4 +720,4900,02:12.8,2,185.1714286,132800,23:41.6,28.64857143,1421600,4 +721,4920,03:32.5,2,183.5714286,212500,23:50.1,23.55428571,1430100,4 +722,4940,04:06.5,2,181.4571429,246500,24:00.0,17.26571429,1440000,4 +723,4960,04:53.0,2,172.3142857,293000,24:11.7,14.90285714,1451700,4 +725,5000,03:50.9,2,152.7714286,230900,24:33.6,18.27714286,1473600,4 +726,5020,03:38.8,2,150.2857143,218800,24:42.3,20.19142857,1482300,4 +727,5040,02:58.5,2,146.8,178500,24:49.5,18.47142857,1489500,4 +728,5060,03:29.0,2,146.4571429,209000,24:57.8,18.4,1497800,4 +729,5080,02:51.1,2,145.5428571,171100,25:04.7,17.55714286,1504700,4 +730,5100,03:15.7,2,144.6,195700,25:12.5,19.71714286,1512500,4 +731,5120,02:49.2,2,143.3428571,169200,25:19.3,20.26571429,1519300,4 +732,5140,02:45.2,2,143.4857143,165200,25:25.9,21.81714286,1525900,4 +733,5160,03:00.5,2,143.1714286,180500,25:33.1,21.63714286,1533100,4 +734,5180,02:47.2,2,141.9142857,167200,25:39.8,21.34,1539800,4 +735,5200,02:57.7,2,141.1714286,177700,25:46.9,21.07714286,1546900,4 +736,5220,02:53.5,2,141.3428571,173500,25:53.8,21.40285714,1553800,4 +737,5240,03:00.9,2,139.5428571,180900,26:01.1,20.84571429,1561100,4 +739,5280,04:33.1,2,136.4571429,273100,26:25.6,21.45714286,1585600,4 +740,5300,03:21.6,2,135.3428571,201600,26:33.7,20.42857143,1593700,4 +741,5320,03:02.0,2,133.3428571,182000,26:41.0,18.96857143,1601000,4 +742,5340,02:43.7,2,134.0857143,163700,26:47.5,20.21428571,1607500,4 +743,5360,02:39.0,2,135.5714286,159000,26:53.9,20.88857143,1613900,4 +744,5380,02:36.3,2,136.0857143,156300,27:00.1,20.68285714,1620100,4 +745,5400,02:37.8,2,136.2571429,157800,27:06.4,20.77142857,1626400,4 +746,5420,02:33.1,2,136.6571429,153100,27:12.6,20.93714286,1639.9999,4 +747,5440,02:36.7,2,137.2571429,156700,27:18.8,20.66,1638800,4 +748,5460,02:44.9,2,138,164900,27:25.4,20.41714286,1645400,4 +749,5480,02:42.1,2,138.7428571,162100,27:31.9,20.78,1651900,4 +750,5500,02:43.7,2,139.1714286,163700,27:38.5,21.37714286,1658500,4 +751,5520,02:36.7,2,140.1714286,156700,27:44.7,20.03142857,1664700,4 +752,5540,02:49.5,2,141.8285714,169500,27:51.5,19.53142857,1671500,4 +753,5560,02:52.7,2,142.9142857,172700,27:58.4,19.91142857,1678400,4 +754,5580,02:44.1,2,143.0857143,164100,28:05.0,21.20571429,1685000,4 +755,5600,02:44.5,2,143,164500,28:11.5,20.60857143,1691500,4 +756,5620,02:53.1,2,143.0857143,173100,28:18.5,20.82,1698500,4 +757,5640,02:40.6,2,142.8285714,160600,28:24.9,20.61714286,1704900,4 +758,5660,03:00.1,2,142.0857143,180100,28:32.1,19.02285714,1712100,4 +759,5680,03:15.3,2,141,195300,28:39.9,17.61714286,1719900,4 +760,5700,03:25.5,2,140.0857143,205500,28:48.1,18.15714286,1728100,4 +761,5720,03:13.0,2,138.7428571,193000,28:55.8,19.87142857,1735800,4 +762,5740,03:05.2,2,137.2571429,185200,29:03.2,19.95142857,1743200,4 +763,5760,02:55.0,2,135.8285714,175000,29:10.2,19.34,1750200,4 +764,5780,03:13.8,2,135.1714286,193800,29:18.0,19.10857143,1758000,4 +765,5800,03:05.2,2,135,185200,29:25.4,19.75428571,1765400,4 +766,5820,02:47.6,2,134.7428571,167600,29:32.1,19.80857143,1772100,4 +767,5840,02:57.7,2,134.1714286,177700,29:39.2,19.02285714,1779200,4 +768,5860,03:04.8,2,134.2571429,184800,29:46.6,17.70571429,1786600,4 +769,5880,03:01.7,2,134.4857143,181700,29:53.9,16.57714286,1793900,4 +770,5900,03:25.5,2,134.1714286,205500,30:02.1,17.24857143,1802100,4 +771,5920,02:58.9,2,134.4285714,178900,30:09.2,17.98857143,1809200,4 +772,5940,02:35.1,2,135.4857143,155100,30:15.5,19.07714286,1815500,4 +773,5960,02:29.6,2,136.0857143,149600,30:21.4,17.96285714,1821400,4 +774,5980,02:36.7,2,136.2571429,156700,30:27.7,18.49714286,1827700,4 +775,6000,03:03.6,2,136.7428571,183600,30:35.0,15.02857143,1835000,4 +776,6020,03:22.7,2,137.1714286,202700,30:43.2,13.74285714,1843200,4 +777,6040,03:20.4,2,136.7428571,200400,30:51.2,15.00571429,1851200,4 +778,6060,02:53.8,2,136.1714286,173800,30:58.1,19.22285714,1858100,4 +779,6080,02:38.2,2,136,158200,31:04.5,20.82,1864500,4 +780,6100,02:30.0,2,137.1714286,150000,31:10.5,20.95428571,1870500,4 +781,6120,02:29.6,2,138.6571429,149600,31:16.4,21.24857143,1876400,4 +782,6140,02:28.5,2,140.3428571,148500,31:22.4,21.18857143,1882400,4 +783,6160,02:27.3,2,141.9142857,147300,31:28.3,21.90857143,1888300,4 +784,6180,02:41.3,2,142.5714286,161300,31:34.7,17.56571429,1894700,4 +785,6200,03:59.9,2,142.6,239900,31:44.3,15.94,1904300,4 +786,6220,03:55.2,2,142.7428571,235200,31:53.7,17.42285714,1913700,4 +787,6240,02:41.7,2,142.8285714,161700,32:00.2,22.17142857,1920200,4 +788,6260,02:26.9,2,143.6285714,146900,32:06.1,22.28571429,1926100,4 +789,6280,03:09.1,2,138.0571429,189100,32:13.6,19.39714286,1933600,4 +791,6320,04:54.2,2,122.2285714,294200,32:51.5,14.22,1971500,4 +792,6340,04:40.1,2,123.2571429,280100,33:02.7,16.01428571,1982700,4 +793,6360,03:45.4,2,124.2285714,225400,33:11.7,16.48,1991700,4 +794,6380,03:25.9,2,125.8571429,205900,33:19.9,16.66571429,1999900,4 +795,6400,03:41.5,2,127.6571429,221500,33:28.8,16.66285714,2008800,4 +796,6420,03:34.5,2,128.4,214500,33:37.3,17.29142857,2017300,4 +797,6440,03:30.2,2,127.6857143,210200,33:45.8,16.38285714,2025800,4 +798,6460,03:04.8,2,128,184800,33:53.1,16.24,2033100,4 +799,6480,02:45.2,2,130,165200,33:59.8,17.13142857,2039800,4 +800,6500,04:58.8,2,130.7428571,298800,34:11.7,17.76857143,2051700,4 +801,6520,04:37.0,2,128.6571429,277000,34:22.8,17.44857143,2062800,4 +802,6540,04:17.0,2,125.6,257000,34:33.1,15.90571429,2073100,4 +803,6560,03:42.3,2,123.6571429,222300,34:42.0,17.48,2082000,4 +804,6580,03:22.4,2,124.4285714,202400,34:50.0,19.24285714,2090000,4 +805,6600,02:48.4,2,126.8285714,168400,34:56.8,20.73428571,2096800,4 +806,6620,02:51.5,2,129.7428571,171500,35:03.6,21.06,2103600,4 +807,6640,02:35.9,2,132.6857143,155900,35:09.9,24.12,2109900,4 +808,6660,02:42.5,2,133.7142857,162500,35:16.4,15.77428571,2116400,4 +810,6700,04:07.3,2,134.2285714,247300,35:34.6,11.19142857,2134600,4 +811,6720,03:03.6,2,134.0857143,183600,35:42.0,20.16,2142000,4 +812,6740,03:04.8,2,131.8285714,184800,35:49.4,19.37714286,2149400,4 +813,6760,03:04.8,2,130.7714286,184800,35:56.8,18.00571429,2156800,4 +814,6780,03:08.7,2,130.0571429,188700,36:04.3,17.85428571,2164300,4 +815,6800,03:06.0,2,129.5142857,186000,36:11.7,18.40571429,2171700,4 +816,6820,03:01.7,2,129.0857143,181700,36:19.0,19.38285714,2179000,4 +817,6840,02:51.5,2,129.7428571,171500,36:25.9,18.68571429,2185900,4 +818,6860,02:54.2,2,130.1714286,174200,36:32.8,18.47142857,2192800,4 +819,6880,02:55.0,2,129.7428571,175000,36:39.8,18.82285714,2199800,4 +820,6900,03:43.8,2,129.1714286,223800,36:48.8,17.32285714,2208800,4 +821,6920,03:35.6,2,129.3428571,215600,36:57.4,16.45428571,2217400,4 +822,6940,03:09.9,2,129.3142857,189900,37:05.0,16.78571429,2225000,4 +823,6960,03:14.2,2,128.2571429,194200,37:12.8,18.57428571,2232800,4 +824,6980,03:18.8,2,127.3428571,198800,37:20.7,18.82,2240700,4 +825,7000,03:27.4,2,127.7428571,207400,37:29.0,18.33428571,2249000,4 +826,7020,03:06.0,2,127.9142857,186000,37:36.5,16.97142857,2256500,4 +827,7040,03:07.5,2,127,187500,37:44.0,17.31428571,2264000,4 +828,7060,03:05.2,2,126.0857143,185200,37:51.4,15.52857143,2271400,4 +829,7080,03:42.7,2,126.1714286,222700,38:00.3,15.28285714,2280300,4 +830,7100,03:29.4,2,126.8285714,209400,38:08.6,16.79714286,2288600,4 +831,7120,03:10.2,2,126.5714286,190200,38:16.3,18.70571429,2296300,4 +832,7140,03:19.2,2,126.9428571,199200,38:24.2,17.78285714,2304200,4 +833,7160,02:56.2,2,128.4857143,176200,38:31.3,18.33142857,2311300,4 +834,7180,02:53.8,2,129.7428571,173800,38:38.2,20.31714286,2318200,4 +835,7200,02:55.8,2,129.1714286,175800,38:45.3,20.25714286,2325300,4 +836,7220,02:43.7,2,129.3428571,163700,38:51.8,20.09714286,2331800,4 +837,7240,02:42.9,2,130.6571429,162900,38:58.3,20.16571429,2338300,4 +838,7260,02:39.4,2,132.1714286,159400,39:04.7,20.67142857,2344700,4 +839,7280,02:35.9,2,132.5714286,155900,39:10.9,21.14857143,2350900,4 +840,7300,02:41.3,2,133.6857143,161300,39:17.4,20.89142857,2357400,4 +841,7320,02:35.9,2,135.6571429,155900,39:23.6,20.22285714,2363600,4 +842,7340,02:37.8,2,137.9142857,157800,39:29.9,20.23428571,2369900,4 +843,7360,02:37.0,2,139.0857143,157000,39:36.2,20.97142857,2376200,4 +844,7380,02:36.7,2,140,156700,39:42.5,20.93714286,2382500,4 +845,7400,02:35.1,2,141.1714286,155100,39:48.7,20.72571429,2388700,4 +846,7420,02:43.3,2,141.5714286,163300,39:55.2,19.34571429,2395200,4 +847,7440,02:59.3,2,141.3428571,179300,40:02.4,19.09714286,2402400,4 +848,7460,03:03.6,2,140.9142857,183600,40:09.7,19.59142857,2409700,4 +849,7480,02:40.6,2,140.9142857,160600,40:16.1,21.23142857,2416100,4 +850,7500,02:48.8,2,141.2571429,168800,40:22.9,21.16571429,2422900,4 +851,7520,02:39.0,2,141.8285714,159000,40:29.3,21.35428571,2429300,4 +852,7540,02:33.9,2,141.9142857,153900,40:35.4,21.19142857,2435400,4 +853,7560,02:47.6,2,141.0857143,167600,40:42.1,20.27428571,2442100,4 +854,7580,03:02.0,2,140.1714286,182000,40:49.4,19.01714286,2449400,4 +855,7600,03:09.5,2,138.4857143,189500,40:57.0,16.88,2457000,4 +856,7620,03:34.9,2,136.6,214900,41:05.6,14.68,2465600,4 +857,7640,03:27.4,2,134.5714286,207400,41:13.9,15.78285714,2473900,4 +858,7660,03:04.8,2,133.3428571,184800,41:21.3,18.14857143,2481300,4 +859,7680,03:11.8,2,131.8285714,191800,41:28.9,18.93428571,2488900,4 +860,7700,03:24.3,2,129.8285714,204300,41:37.1,20.09714286,2497100,4 +861,7720,03:25.9,2,127.2571429,205900,41:45.3,22.05428571,2505300,4 +862,7740,03:39.2,2,124.7428571,219200,41:54.1,20.40571429,2514100,4 +863,7760,04:09.6,2,123.3428571,249600,42:04.1,17.76,2524100,4 +864,7780,03:13.8,2,122.8285714,193800,42:11.8,17.50857143,2531800,4 +865,7800,03:03.2,2,122.7428571,183200,42:19.2,18.88571429,2539200,4 +866,7820,02:44.5,2,123.6857143,164500,42:25.7,19.37142857,2545700,4 +867,7840,02:35.5,2,125.5714286,155500,42:32.0,19.36,2552000,4 +868,7860,02:46.4,2,126.6571429,166400,42:38.6,18.94571429,2558600,4 +869,7880,02:53.1,2,126.5142857,173100,42:45.5,18.05714286,2565500,4 +870,7900,02:58.5,2,127,178500,42:52.7,18.42571429,2572700,4 +871,7920,02:50.7,2,127.5714286,170700,42:59.5,19.13428571,2579500,4 +872,7940,03:16.1,2,127.4285714,196100,43:07.3,18.88857143,2587300,4 +873,7960,03:12.6,2,126.6571429,192600,43:15.0,17.72285714,2595000,4 +874,7980,03:09.9,2,127.4571429,189900,43:22.6,17.56571429,2602600,4 +875,8000,03:21.2,2,120.9428571,201200,43:30.7,17.82571429,2610700,4 +876,8020,03:07.1,2,119.8,187100,43:38.2,17.67142857,2618200,4 +877,8040,02:55.0,2,122.6,175000,43:45.2,17.52571429,2625200,4 +878,8060,03:00.5,2,128.0285714,180500,43:52.4,19.36571429,2632400,4 +880,8100,03:02.8,2,125.4,182800,44:11.9,19.29714286,2651900,4 +881,8120,02:57.0,2,125,177000,44:19.0,18.31428571,2659000,4 +882,8140,03:05.6,2,124.5142857,185600,44:26.4,18.44285714,2666400,4 +883,8160,03:12.6,2,124.5714286,192600,44:34.1,18.39142857,2674100,4 +884,8180,03:02.0,2,123.8285714,182000,44:41.4,15.79714286,2681400,4 +885,8200,03:57.5,2,122.3428571,237500,44:50.9,15.76,2690900,4 +886,8220,03:24.3,2,122.0857143,204300,44:59.1,17.60571429,2699100,4 +887,8240,03:09.9,2,122.5714286,189900,45:06.7,19.90857143,2706700,4 +888,8260,02:55.4,2,123.3428571,175400,45:13.7,19.60857143,2713700,4 +889,8280,02:48.8,2,125.1714286,168800,45:20.5,20.53428571,2720500,4 +890,8300,02:45.6,2,127.5714286,165600,45:27.1,21.03714286,2727100,4 +891,8320,02:48.8,2,129.0857143,168800,45:33.8,20.94,2733800,4 +892,8340,02:45.2,2,130.3428571,165200,45:40.4,20.74285714,2740400,4 +893,8360,02:44.5,2,131.4857143,164500,45:47.0,21.22285714,2747000,4 +894,8380,02:44.1,2,132.4285714,164100,45:53.6,20.41428571,2753600,4 +895,8400,02:46.8,2,132.5714286,166800,46:00.3,20.10857143,2760300,4 +896,8420,02:39.4,2,133.6857143,159400,46:06.6,20.84,2766600,4 +897,8440,02:49.9,2,134.2285714,169900,46:13.4,19.14857143,2773400,4 +898,8460,03:00.9,2,134.4285714,180900,46:20.7,18.04285714,2780700,4 +899,8480,02:56.6,2,134.0857143,176600,46:27.7,17.96285714,2787700,4 +900,8500,02:55.0,2,133.4857143,175000,46:34.7,19.39428571,2794700,4 +901,8520,02:56.2,2,132.5142857,176200,46:41.8,19.5,2801800,4 +902,8540,02:53.8,2,131.7428571,173800,46:48.7,19.76285714,2808700,4 +903,8560,02:46.4,2,132.4285714,166400,46:55.4,19.37714286,2815400,4 +904,8580,02:42.5,2,132.3142857,162500,47:01.9,19.22571429,2821900,4 +905,8600,02:57.0,2,131.3428571,177000,47:09.0,19.37428571,2829000,4 +906,8620,03:09.9,2,130,189900,47:16.5,19.66571429,2836500,4 +907,8640,02:49.9,2,130.3428571,169900,47:23.3,18.85714286,2843300,4 +908,8660,02:46.4,2,130.4,166400,47:30.0,19.05714286,2850000,4 +909,8680,02:50.3,2,129.0857143,170300,47:36.8,17.12285714,2856800,4 +910,8700,02:58.1,2,127.4285714,178100,47:43.9,17.06571429,2863900,4 +911,8720,03:07.9,2,126.4857143,187900,47:51.5,17.68,2871500,4 +912,8740,02:58.1,2,126.4285714,178100,47:58.6,20.31428571,2878600,4 +913,8760,02:55.4,2,127,175400,48:05.6,18.96857143,2885600,4 +914,8780,03:12.6,2,127.4857143,192600,48:13.3,18.59714286,2893300,4 +915,8800,03:05.2,2,127.2571429,185200,48:20.7,19.44,2900700,4 +916,8820,02:58.9,2,128.8571429,178900,48:27.9,21.48857143,2907900,4 +917,8840,02:45.6,2,130.6285714,165600,48:34.5,18.81714286,2914500,4 +918,8860,03:02.4,2,130.7714286,182400,48:41.8,16.06,2921800,4 +919,8880,03:28.6,2,128.5714286,208600,48:50.1,15.00857143,2930100,4 +920,8900,03:20.8,2,127.4285714,200800,48:58.2,17.34571429,2938200,4 +921,8920,02:52.7,2,126.8285714,172700,49:05.1,18.52571429,2945100,4 +922,8940,02:50.3,2,127,170300,49:11.9,19.74857143,2951900,4 +923,8960,02:54.6,2,127,174600,49:18.9,20.26571429,2958900,4 +924,8980,02:47.6,2,126.8285714,167600,49:25.6,20.20571429,2965600,4 +925,9000,02:43.7,2,127.2571429,163700,49:32.1,19.37142857,2972100,4 +926,9020,02:46.0,2,129.0857143,166000,49:38.8,19.47142857,2978800,4 +927,9040,02:57.0,2,131.8285714,177000,49:45.8,20.43714286,2985800,4 +928,9060,02:35.5,2,133.8285714,155500,49:52.1,20.92857143,2992100,4 +929,9080,02:28.8,2,135.3428571,148800,49:58.0,20.89714286,2998000,4 +930,9100,02:30.4,2,136.7428571,150400,50:04.0,21.40285714,3004000,4 +931,9120,02:26.5,2,138.0857143,146500,50:09.9,22.31142857,3009900,4 +932,9140,02:26.9,2,138.9142857,146900,50:15.8,22.7,3015800,4 +933,9160,02:36.7,2,140.2571429,156700,50:22.0,22.59428571,3022000,4 +934,9180,02:30.0,2,141.7428571,150000,50:28.0,22.43142857,3028000,4 +935,9200,02:29.2,2,143.0857143,149200,50:34.0,22.20857143,3034000,4 +936,9220,02:27.3,2,144.2571429,147300,50:39.9,21.71142857,3039900,4 +937,9240,02:35.5,2,146.0285714,155500,50:46.1,23.12857143,3046100,4 +938,9260,03:08.3,2,138.9714286,188300,50:53.6,22.98857143,3053600,4 +939,9280,04:01.4,2,126.3428571,241400,51:03.3,13.11142857,3063300,4 +941,9320,03:36.4,2,117.5714286,216400,51:25.0,11.70571429,3085000,4 +942,9340,03:51.3,2,119.9142857,231300,51:34.3,19.73714286,3094300,4 +943,9360,03:22.0,2,122.0857143,202000,51:42.3,18.46857143,3102300,4 +944,9380,03:16.1,2,125.7142857,196100,51:50.2,15.80285714,3110200,4 +945,9400,03:25.9,2,118.5714286,205900,51:58.4,16.25428571,3118400,4 +947,9440,03:14.2,2,110.0285714,194200,52:23.5,20.32285714,3143500,4 +948,9460,02:58.9,2,118.1428571,178900,52:30.7,19.28285714,3150700,4 +949,9480,02:50.3,2,122.3142857,170300,52:37.5,17.68,3157500,4 +950,9500,04:10.0,2,127.4571429,250000,52:47.5,17.38,3167500,4 +951,9520,03:45.0,2,126.8857143,225000,52:56.5,16.28,3176500,4 +955,80,03:30.6,3,127.2857143,210600,01:02.5,18.89142857,62500,4 +956,100,03:25.9,3,132.5142857,205900,01:10.8,18.57714286,70799.99995,4 +957,120,03:00.5,3,135.2571429,180500,01:18.0,21.22571429,78000,4 +958,140,02:32.0,3,140,152000,01:24.1,24.74857143,84099.9999,4 +959,160,02:13.2,3,146.0857143,133200,01:29.4,27.41714286,89400.0001,4 +960,180,02:15.6,3,151.9142857,135600,01:34.8,27.46857143,94799.99995,4 +961,200,02:16.0,3,155.6571429,136000,01:40.3,27.24857143,100300,4 +962,220,02:23.8,3,157.1714286,143800,01:46.0,27.2,106000,4 +963,240,02:15.6,3,158.2571429,135600,01:51.4,27.46285714,111400.0001,4 +964,260,02:24.2,3,159.7428571,144200,01:57.2,27.71428571,117200,4 +965,280,02:11.7,3,161.1714286,131700,02:02.5,27.48285714,122500,4 +966,300,02:22.6,3,161.7428571,142600,02:08.2,27.20857143,128200,4 +967,320,02:18.7,3,162.2571429,138700,02:13.7,26.65142857,133700,4 +968,340,02:28.5,3,162.9142857,148500,02:19.6,26.58285714,139599.9999,4 +969,360,02:32.7,3,164,152700,02:25.8,26.19142857,145800,4 +970,380,02:26.9,3,165.0857143,146900,02:31.6,25.69428571,151599.9999,4 +971,400,02:31.6,3,165.8285714,151600,02:37.7,25.55714286,157700,4 +972,420,02:21.0,3,166.0857143,141000,02:43.3,25.83142857,163300,4 +973,440,02:33.5,3,166,153500,02:49.5,26.14857143,169500,4 +974,460,02:35.1,3,165.9142857,155100,02:55.7,26.13714286,175700,4 +975,480,02:25.3,3,166.2571429,145300,03:01.5,26.7,181500,4 +976,500,02:34.7,3,166.7428571,154700,03:07.7,26.58571429,187700,4 +977,520,02:34.7,3,167,154700,03:13.9,26.28857143,193900.0001,4 +978,540,02:32.0,3,167.2571429,152000,03:19.9,25.54,199900.0001,4 +979,560,02:41.0,3,167.6571429,161000,03:26.4,25.30571429,206400.0001,4 +980,580,02:35.1,3,168.3428571,155100,03:32.6,25.35142857,212599.9999,4 +981,600,02:29.2,3,168.8285714,149200,03:38.6,25.90571429,218599.9999,4 +982,620,02:33.1,3,168.7428571,153100,03:44.7,25.97142857,224700,4 +983,640,02:30.4,3,168.6,150400,03:50.7,25.86571429,230700,4 +984,660,02:29.6,3,168.4,149600,03:56.7,25.81142857,236700,4 +985,680,02:28.1,3,168.3428571,148100,04:02.6,25.72571429,242599.9999,4 +986,700,02:27.7,3,167.8285714,147700,04:08.5,25.31714286,248500,4 +987,720,02:30.0,3,168.2571429,150000,04:14.5,25.11714286,254500,4 +988,740,02:28.1,3,168.7428571,148100,04:20.4,25.24285714,260400.0001,4 +989,760,02:34.3,3,169.0857143,154300,04:26.6,25.32857143,266599.9999,4 +990,780,02:23.0,3,169,143000,04:32.3,25.67428571,272300,4 +991,800,02:26.1,3,169,146100,04:38.2,26.05142857,278200,4 +992,820,02:23.4,3,168.9142857,143400,04:43.9,26.58,283900.0001,4 +993,840,02:31.2,3,169.2571429,151200,04:49.9,26.56,289900.0001,4 +994,860,02:23.0,3,169.7428571,143000,04:55.7,26.81714286,295700,4 +995,880,02:30.0,3,170.0857143,150000,05:01.7,27.07714286,301700,4 +996,900,02:26.5,3,170,146500,05:07.5,27.39428571,307500,4 +997,920,02:20.6,3,170,140600,05:13.1,27.06285714,313099.9999,4 +998,940,02:24.2,3,170,144200,05:18.9,26.73714286,318900.0001,4 +999,960,02:18.3,3,170,138300,05:24.4,26.76,324400.0001,4 +1000,980,02:19.9,3,170,139900,05:30.0,26.83428571,330000,4 +1001,1000,02:16.7,3,169.9142857,136700,05:35.5,27.01714286,335500,4 +1002,1020,02:22.2,3,170.2571429,142200,05:41.2,27.38857143,341200,4 +1003,1040,02:23.4,3,170.7428571,143400,05:46.9,27.62857143,346900.0001,4 +1004,1060,02:15.6,3,171,135600,05:52.3,27.37142857,352300,4 +1005,1080,02:18.3,3,171.2571429,138300,05:57.9,27.40285714,357900.0001,4 +1006,1100,02:16.7,3,171.7428571,136700,06:03.3,27.36571429,363300,4 +1007,1120,02:24.9,3,172.0857143,144900,06:09.1,27.08285714,369099.9999,4 +1008,1140,02:18.7,3,172,138700,06:14.7,26.83142857,374700,4 +1009,1160,02:21.8,3,172.0857143,141800,06:20.4,26.92285714,380400.0001,4 +1010,1180,02:14.4,3,171.7428571,134400,06:25.7,27.00285714,385700,4 +1011,1200,02:18.7,3,171.2571429,138700,06:31.3,27.36857143,391300,4 +1012,1220,02:10.5,3,170.9142857,130500,06:36.5,27.42571429,396500,4 +1013,1240,02:10.9,3,170.9142857,130900,06:41.7,26.94571429,401700,4 +1014,1260,02:15.6,3,171.2571429,135600,06:47.2,26.62857143,407200,4 +1015,1280,02:12.4,3,171.7428571,132400,06:52.5,26.80285714,412500,4 +1016,1300,02:13.2,3,172.0857143,133200,06:57.8,27.13714286,417800,4 +1017,1320,02:09.3,3,172,129300,07:03.0,27.50857143,423000,4 +1018,1340,02:06.2,3,171.9142857,126200,07:08.0,27.71142857,428000,4 +1019,1360,02:16.0,3,172.2571429,136000,07:13.4,27.73142857,433400.0001,4 +1020,1380,02:10.9,3,172.7428571,130900,07:18.7,27.68857143,438700,4 +1021,1400,02:20.2,3,173.0857143,140200,07:24.3,27.54857143,444300,4 +1022,1420,02:09.3,3,173,129300,07:29.5,27.03428571,449500,4 +1023,1440,02:06.2,3,172.9142857,126200,07:34.5,26.83714286,454500,4 +1024,1460,02:16.0,3,173.2571429,136000,07:39.9,26.74285714,459900.0001,4 +1025,1480,02:10.9,3,173.7428571,130900,07:45.2,26.92571429,465200,4 +1026,1500,02:10.5,3,174.0857143,130500,07:50.4,26.86571429,470400.0001,4 +1027,1520,02:15.6,3,173.9142857,135600,07:55.8,26.92285714,475800,4 +1028,1540,02:16.0,3,174.2571429,136000,08:01.3,26.84857143,481300,4 +1029,1560,02:20.2,3,174.7428571,140200,08:06.9,26.97428571,486900.0001,4 +1030,1580,02:18.3,3,175.0857143,138300,08:12.4,26.74857143,492400.0001,4 +1031,1600,02:25.3,3,175.0857143,145300,08:18.2,26.52857143,498200,4 +1032,1620,02:28.1,3,174.7428571,148100,08:24.1,26.40571429,504099.9999,4 +1033,1640,02:19.9,3,174.2571429,139900,08:29.7,26.29142857,509700,4 +1034,1660,02:12.0,3,173.9142857,132000,08:35.0,26.10857143,515000,4 +1035,1680,02:20.2,3,174,140200,08:40.6,26.52285714,520599.9999,4 +1036,1700,02:18.3,3,174,138300,08:46.1,26.82285714,526099.9999,4 +1037,1720,02:24.9,3,174,144900,08:51.9,26.70571429,531900.0001,4 +1038,1740,02:17.9,3,174,137900,08:57.5,26.29142857,537500,4 +1039,1760,02:26.9,3,174,146900,09:03.3,26.23142857,543300,4 +1040,1780,02:23.4,3,173.9142857,143400,09:09.1,26.46285714,549099.9999,4 +1041,1800,02:26.9,3,174.2571429,146900,09:14.9,26.78,554900.0001,4 +1042,1820,02:28.1,3,174.7428571,148100,09:20.9,26.66285714,560900.0001,4 +1043,1840,02:20.2,3,175.0857143,140200,09:26.5,26.38285714,566500,4 +1044,1860,02:15.2,3,175,135200,09:31.9,26.30285714,571900.0001,4 +1045,1880,02:20.6,3,174.9142857,140600,09:37.5,26.46,577500,4 +1046,1900,02:13.2,3,175.3428571,133200,09:42.8,26.49142857,582800,4 +1047,1920,02:19.1,3,175.4,139100,09:48.4,26.88571429,588400.0001,4 +1048,1940,02:10.5,3,175.6,130500,09:53.6,27.38285714,593599.9999,4 +1049,1960,02:14.8,3,175.6571429,134800,09:59.0,27.04,599000,4 +1050,1980,02:16.7,3,176.0857143,136700,10:04.5,26.7,604500,4 +1051,2000,02:16.7,3,176,136700,10:09.9,26.51142857,609900.0001,4 +1052,2020,02:18.3,3,176,138300,10:15.5,26.86571429,615500,4 +1053,2040,02:13.2,3,176,133200,10:20.8,27.09142857,620800,4 +1054,2060,02:21.0,3,175.9142857,141000,10:26.4,27.39428571,626400.0001,4 +1055,2080,02:18.7,3,176.3428571,138700,10:32.0,27.6,632000,4 +1056,2100,02:22.2,3,176.4,142200,10:37.7,27.51714286,637700,4 +1057,2120,02:15.6,3,176.6,135600,10:43.1,27.26857143,643099.9999,4 +1058,2140,02:19.5,3,176.6571429,139500,10:48.7,27.10571429,648700,4 +1059,2160,02:14.0,3,177.0857143,134000,10:54.0,27.24285714,654000,4 +1060,2180,02:16.3,3,177,136300,10:59.5,27.28571429,659500,4 +1061,2200,02:07.7,3,177,127700,11:04.6,27.29428571,664599.9999,4 +1062,2220,02:14.0,3,177,134000,11:10.0,27.52857143,670000,4 +1063,2240,02:09.7,3,176.9142857,129700,11:15.1,28.00571429,675099.9999,4 +1064,2260,02:15.2,3,177.2571429,135200,11:20.6,28.47142857,680599.9999,4 +1065,2280,02:09.7,3,177.7428571,129700,11:25.7,28.77428571,685700,4 +1066,2300,02:20.6,3,178.0857143,140600,11:31.4,28.68571429,691400.0001,4 +1067,2320,02:20.2,3,177.9142857,140200,11:37.0,28.40571429,697000,4 +1068,2340,02:19.9,3,178.2571429,139900,11:42.6,28.06857143,702599.9999,4 +1069,2360,02:26.1,3,178.7428571,146100,11:48.4,27.66571429,708400.0001,4 +1070,2380,02:15.2,3,179.0857143,135200,11:53.8,27.4,713800,4 +1071,2400,02:16.3,3,179,136300,11:59.3,27.36857143,719300,4 +1072,2420,02:09.7,3,179,129700,12:04.5,27.51428571,724500,4 +1073,2440,02:14.4,3,179,134400,12:09.8,27.82857143,729800,4 +1074,2460,02:13.6,3,179,133600,12:15.2,27.65714286,735200,4 +1075,2480,02:28.5,3,178.9142857,148500,12:21.1,28.05142857,741099.9999,4 +1076,2500,02:25.7,3,179.3428571,145700,12:26.9,28.2,746900.0001,4 +1077,2520,02:18.7,3,179.4857143,138700,12:32.5,27.49142857,752500,4 +1078,2540,02:30.8,3,179.4285714,150800,12:38.5,26.26285714,758500,4 +1079,2560,02:25.7,3,178.5714286,145700,12:44.4,25.65428571,764400.0001,4 +1080,2580,02:35.9,3,178.6,155900,12:50.6,25.76,770599.9999,4 +1081,2600,02:29.2,3,178.4,149200,12:56.6,25.66857143,776599.9999,4 +1082,2620,02:26.5,3,178.3428571,146500,13:02.4,25.59142857,782400.0001,4 +1083,2640,02:24.9,3,177.9142857,144900,13:08.2,25.26,788200,4 +1084,2660,02:30.0,3,178,150000,13:14.2,25.70571429,794200,4 +1085,2680,02:25.3,3,178,145300,13:20.0,26.26571429,800000,4 +1086,2700,02:22.6,3,178,142600,13:25.7,26.32,805700,4 +1087,2720,02:32.0,3,178,152000,13:31.8,25.91714286,811800,4 +1088,2740,02:26.1,3,178,146100,13:37.6,25.96857143,817599.9999,4 +1089,2760,02:29.2,3,178,149200,13:43.6,26.02,823599.9999,4 +1090,2780,02:23.4,3,178.0857143,143400,13:49.4,26.26571429,829400.0001,4 +1091,2800,02:26.5,3,177.6571429,146500,13:55.2,26.35142857,835200,4 +1092,2820,02:19.1,3,177.5142857,139100,14:00.8,26.14857143,840800,4 +1093,2840,02:25.7,3,177.6571429,145700,14:06.6,26.26857143,846599.9999,4 +1094,2860,02:18.7,3,178.0857143,138700,14:12.1,27.1,852099.9999,4 +1095,2880,02:19.5,3,178,139500,14:17.7,28.33142857,857700,4 +1096,2900,02:28.8,3,178,148800,14:23.7,28.55714286,863700,4 +1097,2920,02:32.4,3,178,152400,14:29.8,28.26571429,869800,4 +1098,2940,02:21.0,3,178,141000,14:35.4,27.36,875400.0001,4 +1099,2960,02:23.0,3,178,143000,14:41.1,27.18571429,881099.9999,4 +1100,2980,02:30.8,3,177.9142857,150800,14:47.2,27.18285714,887200,4 +1101,3000,02:27.7,3,178.3428571,147700,14:53.1,27.18571429,893099.9999,4 +1102,3020,02:25.7,3,178.4,145700,14:58.9,26.68285714,898900.0001,4 +1103,3040,02:23.0,3,178.6857143,143000,15:04.6,26.50285714,904599.9999,4 +1104,3060,02:23.8,3,178.4,143800,15:10.4,26.31142857,910400.0001,4 +1105,3080,02:17.1,3,178.3428571,137100,15:15.9,26.28,915900.0001,4 +1106,3100,02:23.8,3,177.9142857,143800,15:21.6,26.49142857,921599.9999,4 +1107,3120,02:17.1,3,178,137100,15:27.1,26.78857143,927099.9999,4 +1108,3140,02:21.4,3,178,141400,15:32.7,26.59142857,932700,4 +1109,3160,02:19.5,3,178,139500,15:38.3,26.32857143,938300,4 +1110,3180,02:24.2,3,178,144200,15:44.1,26.28,944099.9999,4 +1111,3200,02:17.9,3,177.9142857,137900,15:49.6,26.52857143,949599.9999,4 +1112,3220,02:23.0,3,178.3428571,143000,15:55.3,26.70571429,955300,4 +1113,3240,02:23.8,3,178.4857143,143800,16:01.1,26.63142857,961099.9999,4 +1114,3260,02:31.6,3,178.4285714,151600,16:07.1,26.42857143,967099.9999,4 +1115,3280,02:28.8,3,177.6571429,148800,16:13.1,26.63428571,973099.9999,4 +1116,3300,02:23.4,3,177.2571429,143400,16:18.8,26.91142857,978800,4 +1117,3320,02:29.6,3,176.8285714,149600,16:24.8,27.17428571,984800,4 +1118,3340,02:19.9,3,177.2571429,139900,16:30.4,26.91428571,990400.0001,4 +1119,3360,02:19.1,3,177.7428571,139100,16:36.0,26.72571429,996000,4 +1120,3380,02:20.2,3,178.0857143,140200,16:41.6,26.74857143,1001600,4 +1121,3400,02:22.6,3,177.9142857,142600,16:47.3,27.23142857,1007300,4 +1122,3420,02:24.5,3,178.3428571,144500,16:53.1,27.3,1013100,4 +1123,3440,02:19.5,3,178.4857143,139500,16:58.6,27,1018600,4 +1124,3460,02:25.7,3,178.3428571,145700,17:04.5,26.54,1024500,4 +1125,3480,02:13.6,3,177.9142857,133600,17:09.8,26.55714286,1029800,4 +1126,3500,02:18.3,3,178,138300,17:15.3,26.65714286,1035300,4 +1127,3520,02:16.0,3,178,136000,17:20.8,26.85714286,1040800,4 +1128,3540,02:16.0,3,178,136000,17:26.2,26.88,1046200,4 +1129,3560,02:22.6,3,178,142600,17:31.9,27.08285714,1051900,4 +1130,3580,02:21.8,3,177.9142857,141800,17:37.6,27.36285714,1057600,4 +1131,3600,02:17.1,3,178.2571429,137100,17:43.1,27.56,1063100,4 +1132,3620,02:20.2,3,178.7428571,140200,17:48.7,27.68,1068700,4 +1133,3640,02:16.3,3,179.0857143,136300,17:54.1,27.63142857,1074100,4 +1134,3660,02:20.6,3,179,140600,17:59.8,27.75142857,1079800,4 +1135,3680,02:17.9,3,179,137900,18:05.3,27.38571429,1085300,4 +1136,3700,02:21.0,3,179,141000,18:10.9,27.30285714,1090900,4 +1137,3720,02:16.3,3,179,136300,18:16.4,27.20571429,1096400,4 +1138,3740,02:26.9,3,179,146900,18:22.2,27.24,1102200,4 +1139,3760,02:32.4,3,179,152400,18:28.3,26.96571429,1108300,4 +1140,3780,02:27.7,3,179,147700,18:34.2,26.4,1114200,4 +1141,3800,02:33.5,3,178.9142857,153500,18:40.4,26.11428571,1120400,4 +1142,3820,02:22.2,3,179.2571429,142200,18:46.1,26.40857143,1126100,4 +1143,3840,02:22.2,3,179.7428571,142200,18:51.8,26.98285714,1131800,4 +1144,3860,02:30.4,3,180.1714286,150400,18:57.8,27.06285714,1137800,4 +1145,3880,02:22.6,3,179.7428571,142600,19:03.5,26.66571429,1143500,4 +1146,3900,02:33.5,3,179.2571429,153500,19:09.6,26.30857143,1149600,4 +1147,3920,02:29.2,3,178.8285714,149200,19:15.6,26.57714286,1155600,4 +1148,3940,02:24.5,3,179.2571429,144500,19:21.4,27.16571429,1161400,4 +1149,3960,02:23.4,3,179.7428571,143400,19:27.1,27.26285714,1167100,4 +1150,3980,02:17.5,3,180.0857143,137500,19:32.6,27.38571429,1172600,4 +1151,4000,02:18.7,3,179.9142857,138700,19:38.2,28.15714286,1178200,4 +1152,4020,02:21.4,3,180.2571429,141400,19:43.8,28.81428571,1183800,4 +1153,4040,02:18.7,3,180.7428571,138700,19:49.4,29.13714286,1189400,4 +1154,4060,02:23.0,3,181.0857143,143000,19:55.1,28.86857143,1195100,4 +1155,4080,02:19.5,3,181,139500,20:00.7,28.32857143,1200700,4 +1156,4100,02:12.0,3,181,132000,20:05.9,28.18857143,1205900,4 +1157,4120,02:14.4,3,181,134400,20:11.3,28.54571429,1211300,4 +1158,4140,02:10.1,3,181,130100,20:16.5,27.95714286,1216500,4 +1159,4160,02:17.9,3,181,137900,20:22.0,27.20857143,1222000,4 +1160,4180,02:10.9,3,180.9142857,130900,20:27.3,27.03142857,1227300,4 +1161,4200,02:16.7,3,182.2,136700,20:32.7,27.56285714,1232700,4 +1162,4220,02:15.2,3,177.9714286,135200,20:38.1,27.39428571,1238100,4 +1163,4240,02:23.4,3,176.7428571,143400,20:43.9,27.29714286,1243900,4 +1164,4260,02:14.0,3,178.2285714,134000,20:49.2,27.35714286,1249200,4 +1165,4280,02:20.6,3,182.9428571,140600,20:54.9,27.64,1254900,4 +1166,4300,02:16.0,3,182,136000,21:00.3,27.76857143,1260300,4 +1167,4320,02:19.1,3,182,139100,21:05.9,27.76571429,1265900,4 +1168,4340,02:16.0,3,182,136000,21:11.3,27.46285714,1271300,4 +1169,4360,02:18.3,3,182,138300,21:16.8,27.41714286,1276800,4 +1170,4380,02:12.0,3,182,132000,21:22.1,27.64285714,1282100,4 +1171,4400,02:17.5,3,182,137500,21:27.6,28.02857143,1287600,4 +1172,4420,02:12.8,3,182,132800,21:32.9,27.86285714,1292900,4 +1173,4440,02:19.5,3,182,139500,21:38.5,27.75428571,1298500,4 +1174,4460,02:17.9,3,182,137900,21:44.0,27.56285714,1304000,4 +1175,4480,02:13.6,3,182,133600,21:49.4,27.65428571,1309400,4 +1176,4500,02:17.1,3,182,137100,21:54.8,27.64571429,1314800,4 +1177,4520,02:16.3,3,181.9142857,136300,22:00.3,27.66857143,1320300,4 +1178,4540,02:20.2,3,182.2571429,140200,22:05.9,27.82,1300.0001,4 +1179,4560,02:14.4,3,182.7428571,134400,22:11.3,27.80857143,1331300,4 +1180,4580,02:18.7,3,183.0857143,138700,22:16.8,27.68285714,1336800,4 +1181,4600,02:12.4,3,183,132400,22:22.1,27.39428571,1342100,4 +1182,4620,02:19.1,3,183,139100,22:27.7,27.61428571,1347700,4 +1183,4640,02:11.7,3,183,131700,22:32.9,27.66,1352900,4 +1184,4660,02:15.2,3,183,135200,22:38.4,27.98285714,1358400,4 +1185,4680,02:10.9,3,183,130900,22:43.6,27.84,1363600,4 +1186,4700,02:12.8,3,182.9142857,132800,22:48.9,27.81714286,1368900,4 +1187,4720,02:13.6,3,183.2571429,133600,22:54.2,27.81428571,1374200,4 +1188,4740,02:13.6,3,183.7428571,133600,22:59.6,27.78571429,1379600,4 +1189,4760,02:18.7,3,184.0857143,138700,23:05.1,27.76,1385100,4 +1190,4780,02:18.3,3,184,138300,23:10.7,27.95142857,1390700,4 +1191,4800,02:07.7,3,184,127700,23:15.8,28.25714286,1395800,4 +1192,4820,02:11.3,3,184,131300,23:21.0,28.85142857,1401000,4 +1193,4840,02:09.3,3,183.9142857,129300,23:26.2,29.72285714,1406200,4 +1194,4860,02:09.3,3,184.2571429,129300,23:31.4,30.53142857,1411400,4 +1195,4880,02:03.1,3,184.8285714,123100,23:36.3,31.17142857,1416300,4 +1196,4900,02:12.8,3,185.1714286,132800,23:41.6,28.64857143,1421600,4 +1197,4920,03:32.5,3,183.5714286,212500,23:50.1,23.55428571,1430100,4 +1198,4940,04:06.5,3,181.4571429,246500,24:00.0,17.26571429,1440000,4 +1199,4960,04:53.0,3,172.3142857,293000,24:11.7,14.90285714,1451700,4 +1201,5000,03:50.9,3,152.7714286,230900,24:33.6,18.27714286,1473600,4 +1202,5020,03:38.8,3,150.2857143,218800,24:42.3,20.19142857,1482300,4 +1203,5040,02:58.5,3,146.8,178500,24:49.5,18.47142857,1489500,4 +1204,5060,03:29.0,3,146.4571429,209000,24:57.8,18.4,1497800,4 +1205,5080,02:51.1,3,145.5428571,171100,25:04.7,17.55714286,1504700,4 +1206,5100,03:15.7,3,144.6,195700,25:12.5,19.71714286,1512500,4 +1207,5120,02:49.2,3,143.3428571,169200,25:19.3,20.26571429,1519300,4 +1208,5140,02:45.2,3,143.4857143,165200,25:25.9,21.81714286,1525900,4 +1209,5160,03:00.5,3,143.1714286,180500,25:33.1,21.63714286,1533100,4 +1210,5180,02:47.2,3,141.9142857,167200,25:39.8,21.34,1539800,4 +1211,5200,02:57.7,3,141.1714286,177700,25:46.9,21.07714286,1546900,4 +1212,5220,02:53.5,3,141.3428571,173500,25:53.8,21.40285714,1553800,4 +1213,5240,03:00.9,3,139.5428571,180900,26:01.1,20.84571429,1561100,4 +1215,5280,04:33.1,3,136.4571429,273100,26:25.6,21.45714286,1585600,4 +1216,5300,03:21.6,3,135.3428571,201600,26:33.7,20.42857143,1593700,4 +1217,5320,03:02.0,3,133.3428571,182000,26:41.0,18.96857143,1601000,4 +1218,5340,02:43.7,3,134.0857143,163700,26:47.5,20.21428571,1607500,4 +1219,5360,02:39.0,3,135.5714286,159000,26:53.9,20.88857143,1613900,4 +1220,5380,02:36.3,3,136.0857143,156300,27:00.1,20.68285714,1620100,4 +1221,5400,02:37.8,3,136.2571429,157800,27:06.4,20.77142857,1626400,4 +1222,5420,02:33.1,3,136.6571429,153100,27:12.6,20.93714286,1639.9999,4 +1223,5440,02:36.7,3,137.2571429,156700,27:18.8,20.66,1638800,4 +1224,5460,02:44.9,3,138,164900,27:25.4,20.41714286,1645400,4 +1225,5480,02:42.1,3,138.7428571,162100,27:31.9,20.78,1651900,4 +1226,5500,02:43.7,3,139.1714286,163700,27:38.5,21.37714286,1658500,4 +1227,5520,02:36.7,3,140.1714286,156700,27:44.7,20.03142857,1664700,4 +1228,5540,02:49.5,3,141.8285714,169500,27:51.5,19.53142857,1671500,4 +1229,5560,02:52.7,3,142.9142857,172700,27:58.4,19.91142857,1678400,4 +1230,5580,02:44.1,3,143.0857143,164100,28:05.0,21.20571429,1685000,4 +1231,5600,02:44.5,3,143,164500,28:11.5,20.60857143,1691500,4 +1232,5620,02:53.1,3,143.0857143,173100,28:18.5,20.82,1698500,4 +1233,5640,02:40.6,3,142.8285714,160600,28:24.9,20.61714286,1704900,4 +1234,5660,03:00.1,3,142.0857143,180100,28:32.1,19.02285714,1712100,4 +1235,5680,03:15.3,3,141,195300,28:39.9,17.61714286,1719900,4 +1236,5700,03:25.5,3,140.0857143,205500,28:48.1,18.15714286,1728100,4 +1237,5720,03:13.0,3,138.7428571,193000,28:55.8,19.87142857,1735800,4 +1238,5740,03:05.2,3,137.2571429,185200,29:03.2,19.95142857,1743200,4 +1239,5760,02:55.0,3,135.8285714,175000,29:10.2,19.34,1750200,4 +1240,5780,03:13.8,3,135.1714286,193800,29:18.0,19.10857143,1758000,4 +1241,5800,03:05.2,3,135,185200,29:25.4,19.75428571,1765400,4 +1242,5820,02:47.6,3,134.7428571,167600,29:32.1,19.80857143,1772100,4 +1243,5840,02:57.7,3,134.1714286,177700,29:39.2,19.02285714,1779200,4 +1244,5860,03:04.8,3,134.2571429,184800,29:46.6,17.70571429,1786600,4 +1245,5880,03:01.7,3,134.4857143,181700,29:53.9,16.57714286,1793900,4 +1246,5900,03:25.5,3,134.1714286,205500,30:02.1,17.24857143,1802100,4 +1247,5920,02:58.9,3,134.4285714,178900,30:09.2,17.98857143,1809200,4 +1248,5940,02:35.1,3,135.4857143,155100,30:15.5,19.07714286,1815500,4 +1249,5960,02:29.6,3,136.0857143,149600,30:21.4,17.96285714,1821400,4 +1250,5980,02:36.7,3,136.2571429,156700,30:27.7,18.49714286,1827700,4 +1251,6000,03:03.6,3,136.7428571,183600,30:35.0,15.02857143,1835000,4 +1252,6020,03:22.7,3,137.1714286,202700,30:43.2,13.74285714,1843200,4 +1253,6040,03:20.4,3,136.7428571,200400,30:51.2,15.00571429,1851200,4 +1254,6060,02:53.8,3,136.1714286,173800,30:58.1,19.22285714,1858100,4 +1255,6080,02:38.2,3,136,158200,31:04.5,20.82,1864500,4 +1256,6100,02:30.0,3,137.1714286,150000,31:10.5,20.95428571,1870500,4 +1257,6120,02:29.6,3,138.6571429,149600,31:16.4,21.24857143,1876400,4 +1258,6140,02:28.5,3,140.3428571,148500,31:22.4,21.18857143,1882400,4 +1259,6160,02:27.3,3,141.9142857,147300,31:28.3,21.90857143,1888300,4 +1260,6180,02:41.3,3,142.5714286,161300,31:34.7,17.56571429,1894700,4 +1261,6200,03:59.9,3,142.6,239900,31:44.3,15.94,1904300,4 +1262,6220,03:55.2,3,142.7428571,235200,31:53.7,17.42285714,1913700,4 +1263,6240,02:41.7,3,142.8285714,161700,32:00.2,22.17142857,1920200,4 +1264,6260,02:26.9,3,143.6285714,146900,32:06.1,22.28571429,1926100,4 +1265,6280,03:09.1,3,138.0571429,189100,32:13.6,19.39714286,1933600,4 +1267,6320,04:54.2,3,122.2285714,294200,32:51.5,14.22,1971500,4 +1268,6340,04:40.1,3,123.2571429,280100,33:02.7,16.01428571,1982700,4 +1269,6360,03:45.4,3,124.2285714,225400,33:11.7,16.48,1991700,4 +1270,6380,03:25.9,3,125.8571429,205900,33:19.9,16.66571429,1999900,4 +1271,6400,03:41.5,3,127.6571429,221500,33:28.8,16.66285714,2008800,4 +1272,6420,03:34.5,3,128.4,214500,33:37.3,17.29142857,2017300,4 +1273,6440,03:30.2,3,127.6857143,210200,33:45.8,16.38285714,2025800,4 +1274,6460,03:04.8,3,128,184800,33:53.1,16.24,2033100,4 +1275,6480,02:45.2,3,130,165200,33:59.8,17.13142857,2039800,4 +1276,6500,04:58.8,3,130.7428571,298800,34:11.7,17.76857143,2051700,4 +1277,6520,04:37.0,3,128.6571429,277000,34:22.8,17.44857143,2062800,4 +1278,6540,04:17.0,3,125.6,257000,34:33.1,15.90571429,2073100,4 +1279,6560,03:42.3,3,123.6571429,222300,34:42.0,17.48,2082000,4 +1280,6580,03:22.4,3,124.4285714,202400,34:50.0,19.24285714,2090000,4 +1281,6600,02:48.4,3,126.8285714,168400,34:56.8,20.73428571,2096800,4 +1282,6620,02:51.5,3,129.7428571,171500,35:03.6,21.06,2103600,4 +1283,6640,02:35.9,3,132.6857143,155900,35:09.9,24.12,2109900,4 +1284,6660,02:42.5,3,133.7142857,162500,35:16.4,15.77428571,2116400,4 +1286,6700,04:07.3,3,134.2285714,247300,35:34.6,11.19142857,2134600,4 +1287,6720,03:03.6,3,134.0857143,183600,35:42.0,20.16,2142000,4 +1288,6740,03:04.8,3,131.8285714,184800,35:49.4,19.37714286,2149400,4 +1289,6760,03:04.8,3,130.7714286,184800,35:56.8,18.00571429,2156800,4 +1290,6780,03:08.7,3,130.0571429,188700,36:04.3,17.85428571,2164300,4 +1291,6800,03:06.0,3,129.5142857,186000,36:11.7,18.40571429,2171700,4 +1292,6820,03:01.7,3,129.0857143,181700,36:19.0,19.38285714,2179000,4 +1293,6840,02:51.5,3,129.7428571,171500,36:25.9,18.68571429,2185900,4 +1294,6860,02:54.2,3,130.1714286,174200,36:32.8,18.47142857,2192800,4 +1295,6880,02:55.0,3,129.7428571,175000,36:39.8,18.82285714,2199800,4 +1296,6900,03:43.8,3,129.1714286,223800,36:48.8,17.32285714,2208800,4 +1297,6920,03:35.6,3,129.3428571,215600,36:57.4,16.45428571,2217400,4 +1298,6940,03:09.9,3,129.3142857,189900,37:05.0,16.78571429,2225000,4 +1299,6960,03:14.2,3,128.2571429,194200,37:12.8,18.57428571,2232800,4 +1300,6980,03:18.8,3,127.3428571,198800,37:20.7,18.82,2240700,4 +1301,7000,03:27.4,3,127.7428571,207400,37:29.0,18.33428571,2249000,4 +1302,7020,03:06.0,3,127.9142857,186000,37:36.5,16.97142857,2256500,4 +1303,7040,03:07.5,3,127,187500,37:44.0,17.31428571,2264000,4 +1304,7060,03:05.2,3,126.0857143,185200,37:51.4,15.52857143,2271400,4 +1305,7080,03:42.7,3,126.1714286,222700,38:00.3,15.28285714,2280300,4 +1306,7100,03:29.4,3,126.8285714,209400,38:08.6,16.79714286,2288600,4 +1307,7120,03:10.2,3,126.5714286,190200,38:16.3,18.70571429,2296300,4 +1308,7140,03:19.2,3,126.9428571,199200,38:24.2,17.78285714,2304200,4 +1309,7160,02:56.2,3,128.4857143,176200,38:31.3,18.33142857,2311300,4 +1310,7180,02:53.8,3,129.7428571,173800,38:38.2,20.31714286,2318200,4 +1311,7200,02:55.8,3,129.1714286,175800,38:45.3,20.25714286,2325300,4 +1312,7220,02:43.7,3,129.3428571,163700,38:51.8,20.09714286,2331800,4 +1313,7240,02:42.9,3,130.6571429,162900,38:58.3,20.16571429,2338300,4 +1314,7260,02:39.4,3,132.1714286,159400,39:04.7,20.67142857,2344700,4 +1315,7280,02:35.9,3,132.5714286,155900,39:10.9,21.14857143,2350900,4 +1316,7300,02:41.3,3,133.6857143,161300,39:17.4,20.89142857,2357400,4 +1317,7320,02:35.9,3,135.6571429,155900,39:23.6,20.22285714,2363600,4 +1318,7340,02:37.8,3,137.9142857,157800,39:29.9,20.23428571,2369900,4 +1319,7360,02:37.0,3,139.0857143,157000,39:36.2,20.97142857,2376200,4 +1320,7380,02:36.7,3,140,156700,39:42.5,20.93714286,2382500,4 +1321,7400,02:35.1,3,141.1714286,155100,39:48.7,20.72571429,2388700,4 +1322,7420,02:43.3,3,141.5714286,163300,39:55.2,19.34571429,2395200,4 +1323,7440,02:59.3,3,141.3428571,179300,40:02.4,19.09714286,2402400,4 +1324,7460,03:03.6,3,140.9142857,183600,40:09.7,19.59142857,2409700,4 +1325,7480,02:40.6,3,140.9142857,160600,40:16.1,21.23142857,2416100,4 +1326,7500,02:48.8,3,141.2571429,168800,40:22.9,21.16571429,2422900,4 +1327,7520,02:39.0,3,141.8285714,159000,40:29.3,21.35428571,2429300,4 +1328,7540,02:33.9,3,141.9142857,153900,40:35.4,21.19142857,2435400,4 +1329,7560,02:47.6,3,141.0857143,167600,40:42.1,20.27428571,2442100,4 +1330,7580,03:02.0,3,140.1714286,182000,40:49.4,19.01714286,2449400,4 +1331,7600,03:09.5,3,138.4857143,189500,40:57.0,16.88,2457000,4 +1332,7620,03:34.9,3,136.6,214900,41:05.6,14.68,2465600,4 +1333,7640,03:27.4,3,134.5714286,207400,41:13.9,15.78285714,2473900,4 +1334,7660,03:04.8,3,133.3428571,184800,41:21.3,18.14857143,2481300,4 +1335,7680,03:11.8,3,131.8285714,191800,41:28.9,18.93428571,2488900,4 +1336,7700,03:24.3,3,129.8285714,204300,41:37.1,20.09714286,2497100,4 +1337,7720,03:25.9,3,127.2571429,205900,41:45.3,22.05428571,2505300,4 +1338,7740,03:39.2,3,124.7428571,219200,41:54.1,20.40571429,2514100,4 +1339,7760,04:09.6,3,123.3428571,249600,42:04.1,17.76,2524100,4 +1340,7780,03:13.8,3,122.8285714,193800,42:11.8,17.50857143,2531800,4 +1341,7800,03:03.2,3,122.7428571,183200,42:19.2,18.88571429,2539200,4 +1342,7820,02:44.5,3,123.6857143,164500,42:25.7,19.37142857,2545700,4 +1343,7840,02:35.5,3,125.5714286,155500,42:32.0,19.36,2552000,4 +1344,7860,02:46.4,3,126.6571429,166400,42:38.6,18.94571429,2558600,4 +1345,7880,02:53.1,3,126.5142857,173100,42:45.5,18.05714286,2565500,4 +1346,7900,02:58.5,3,127,178500,42:52.7,18.42571429,2572700,4 +1347,7920,02:50.7,3,127.5714286,170700,42:59.5,19.13428571,2579500,4 +1348,7940,03:16.1,3,127.4285714,196100,43:07.3,18.88857143,2587300,4 +1349,7960,03:12.6,3,126.6571429,192600,43:15.0,17.72285714,2595000,4 +1350,7980,03:09.9,3,127.4571429,189900,43:22.6,17.56571429,2602600,4 +1351,8000,03:21.2,3,120.9428571,201200,43:30.7,17.82571429,2610700,4 +1352,8020,03:07.1,3,119.8,187100,43:38.2,17.67142857,2618200,4 +1353,8040,02:55.0,3,122.6,175000,43:45.2,17.52571429,2625200,4 +1354,8060,03:00.5,3,128.0285714,180500,43:52.4,19.36571429,2632400,4 +1356,8100,03:02.8,3,125.4,182800,44:11.9,19.29714286,2651900,4 +1357,8120,02:57.0,3,125,177000,44:19.0,18.31428571,2659000,4 +1358,8140,03:05.6,3,124.5142857,185600,44:26.4,18.44285714,2666400,4 +1359,8160,03:12.6,3,124.5714286,192600,44:34.1,18.39142857,2674100,4 +1360,8180,03:02.0,3,123.8285714,182000,44:41.4,15.79714286,2681400,4 +1361,8200,03:57.5,3,122.3428571,237500,44:50.9,15.76,2690900,4 +1362,8220,03:24.3,3,122.0857143,204300,44:59.1,17.60571429,2699100,4 +1363,8240,03:09.9,3,122.5714286,189900,45:06.7,19.90857143,2706700,4 +1364,8260,02:55.4,3,123.3428571,175400,45:13.7,19.60857143,2713700,4 +1365,8280,02:48.8,3,125.1714286,168800,45:20.5,20.53428571,2720500,4 +1366,8300,02:45.6,3,127.5714286,165600,45:27.1,21.03714286,2727100,4 +1367,8320,02:48.8,3,129.0857143,168800,45:33.8,20.94,2733800,4 +1368,8340,02:45.2,3,130.3428571,165200,45:40.4,20.74285714,2740400,4 +1369,8360,02:44.5,3,131.4857143,164500,45:47.0,21.22285714,2747000,4 +1370,8380,02:44.1,3,132.4285714,164100,45:53.6,20.41428571,2753600,4 +1371,8400,02:46.8,3,132.5714286,166800,46:00.3,20.10857143,2760300,4 +1372,8420,02:39.4,3,133.6857143,159400,46:06.6,20.84,2766600,4 +1373,8440,02:49.9,3,134.2285714,169900,46:13.4,19.14857143,2773400,4 +1374,8460,03:00.9,3,134.4285714,180900,46:20.7,18.04285714,2780700,4 +1375,8480,02:56.6,3,134.0857143,176600,46:27.7,17.96285714,2787700,4 +1376,8500,02:55.0,3,133.4857143,175000,46:34.7,19.39428571,2794700,4 +1377,8520,02:56.2,3,132.5142857,176200,46:41.8,19.5,2801800,4 +1378,8540,02:53.8,3,131.7428571,173800,46:48.7,19.76285714,2808700,4 +1379,8560,02:46.4,3,132.4285714,166400,46:55.4,19.37714286,2815400,4 +1380,8580,02:42.5,3,132.3142857,162500,47:01.9,19.22571429,2821900,4 +1381,8600,02:57.0,3,131.3428571,177000,47:09.0,19.37428571,2829000,4 +1382,8620,03:09.9,3,130,189900,47:16.5,19.66571429,2836500,4 +1383,8640,02:49.9,3,130.3428571,169900,47:23.3,18.85714286,2843300,4 +1384,8660,02:46.4,3,130.4,166400,47:30.0,19.05714286,2850000,4 +1385,8680,02:50.3,3,129.0857143,170300,47:36.8,17.12285714,2856800,4 +1386,8700,02:58.1,3,127.4285714,178100,47:43.9,17.06571429,2863900,4 +1387,8720,03:07.9,3,126.4857143,187900,47:51.5,17.68,2871500,4 +1388,8740,02:58.1,3,126.4285714,178100,47:58.6,20.31428571,2878600,4 +1389,8760,02:55.4,3,127,175400,48:05.6,18.96857143,2885600,4 +1390,8780,03:12.6,3,127.4857143,192600,48:13.3,18.59714286,2893300,4 +1391,8800,03:05.2,3,127.2571429,185200,48:20.7,19.44,2900700,4 +1392,8820,02:58.9,3,128.8571429,178900,48:27.9,21.48857143,2907900,4 +1393,8840,02:45.6,3,130.6285714,165600,48:34.5,18.81714286,2914500,4 +1394,8860,03:02.4,3,130.7714286,182400,48:41.8,16.06,2921800,4 +1395,8880,03:28.6,3,128.5714286,208600,48:50.1,15.00857143,2930100,4 +1396,8900,03:20.8,3,127.4285714,200800,48:58.2,17.34571429,2938200,4 +1397,8920,02:52.7,3,126.8285714,172700,49:05.1,18.52571429,2945100,4 +1398,8940,02:50.3,3,127,170300,49:11.9,19.74857143,2951900,4 +1399,8960,02:54.6,3,127,174600,49:18.9,20.26571429,2958900,4 +1400,8980,02:47.6,3,126.8285714,167600,49:25.6,20.20571429,2965600,4 +1401,9000,02:43.7,3,127.2571429,163700,49:32.1,19.37142857,2972100,4 +1402,9020,02:46.0,3,129.0857143,166000,49:38.8,19.47142857,2978800,4 +1403,9040,02:57.0,3,131.8285714,177000,49:45.8,20.43714286,2985800,4 +1404,9060,02:35.5,3,133.8285714,155500,49:52.1,20.92857143,2992100,4 +1405,9080,02:28.8,3,135.3428571,148800,49:58.0,20.89714286,2998000,4 +1406,9100,02:30.4,3,136.7428571,150400,50:04.0,21.40285714,3004000,4 +1407,9120,02:26.5,3,138.0857143,146500,50:09.9,22.31142857,3009900,4 +1408,9140,02:26.9,3,138.9142857,146900,50:15.8,22.7,3015800,4 +1409,9160,02:36.7,3,140.2571429,156700,50:22.0,22.59428571,3022000,4 +1410,9180,02:30.0,3,141.7428571,150000,50:28.0,22.43142857,3028000,4 +1411,9200,02:29.2,3,143.0857143,149200,50:34.0,22.20857143,3034000,4 +1412,9220,02:27.3,3,144.2571429,147300,50:39.9,21.71142857,3039900,4 +1413,9240,02:35.5,3,146.0285714,155500,50:46.1,23.12857143,3046100,4 +1414,9260,03:08.3,3,138.9714286,188300,50:53.6,22.98857143,3053600,4 +1415,9280,04:01.4,3,126.3428571,241400,51:03.3,13.11142857,3063300,4 +1417,9320,03:36.4,3,117.5714286,216400,51:25.0,11.70571429,3085000,4 +1418,9340,03:51.3,3,119.9142857,231300,51:34.3,19.73714286,3094300,4 +1419,9360,03:22.0,3,122.0857143,202000,51:42.3,18.46857143,3102300,4 +1420,9380,03:16.1,3,125.7142857,196100,51:50.2,15.80285714,3110200,4 +1421,9400,03:25.9,3,118.5714286,205900,51:58.4,16.25428571,3118400,4 +1423,9440,03:14.2,3,110.0285714,194200,52:23.5,20.32285714,3143500,4 +1424,9460,02:58.9,3,118.1428571,178900,52:30.7,19.28285714,3150700,4 +1425,9480,02:50.3,3,122.3142857,170300,52:37.5,17.68,3157500,4 +1426,9500,04:10.0,3,127.4571429,250000,52:47.5,17.38,3167500,4 +1427,9520,03:45.0,3,126.8857143,225000,52:56.5,16.28,3176500,4 diff --git a/rowers/tests/testdata/colsfromdb3.csv b/rowers/tests/testdata/colsfromdb3.csv new file mode 100644 index 00000000..e87e0ee6 --- /dev/null +++ b/rowers/tests/testdata/colsfromdb3.csv @@ -0,0 +1,1399 @@ +,distance,fpace,workoutid,hr,pace,ftime,spm,time,workoutstate +3,80,03:30.6,1,127.2857143,210600,01:02.5,18.89142857,62500,4 +4,100,03:25.9,1,132.5142857,205900,01:10.8,18.57714286,70799.99995,4 +5,120,03:00.5,1,135.2571429,180500,01:18.0,21.22571429,78000,4 +6,140,02:32.0,1,140,152000,01:24.1,24.74857143,84099.9999,4 +7,160,02:13.2,1,146.0857143,133200,01:29.4,27.41714286,89400.0001,4 +8,180,02:15.6,1,151.9142857,135600,01:34.8,27.46857143,94799.99995,4 +9,200,02:16.0,1,155.6571429,136000,01:40.3,27.24857143,100300,4 +10,220,02:23.8,1,157.1714286,143800,01:46.0,27.2,106000,4 +11,240,02:15.6,1,158.2571429,135600,01:51.4,27.46285714,111400.0001,4 +12,260,02:24.2,1,159.7428571,144200,01:57.2,27.71428571,117200,4 +13,280,02:11.7,1,161.1714286,131700,02:02.5,27.48285714,122500,4 +14,300,02:22.6,1,161.7428571,142600,02:08.2,27.20857143,128200,4 +15,320,02:18.7,1,162.2571429,138700,02:13.7,26.65142857,133700,4 +16,340,02:28.5,1,162.9142857,148500,02:19.6,26.58285714,139599.9999,4 +17,360,02:32.7,1,164,152700,02:25.8,26.19142857,145800,4 +18,380,02:26.9,1,165.0857143,146900,02:31.6,25.69428571,151599.9999,4 +19,400,02:31.6,1,165.8285714,151600,02:37.7,25.55714286,157700,4 +20,420,02:21.0,1,166.0857143,141000,02:43.3,25.83142857,163300,4 +21,440,02:33.5,1,166,153500,02:49.5,26.14857143,169500,4 +22,460,02:35.1,1,165.9142857,155100,02:55.7,26.13714286,175700,4 +23,480,02:25.3,1,166.2571429,145300,03:01.5,26.7,181500,4 +24,500,02:34.7,1,166.7428571,154700,03:07.7,26.58571429,187700,4 +25,520,02:34.7,1,167,154700,03:13.9,26.28857143,193900.0001,4 +26,540,02:32.0,1,167.2571429,152000,03:19.9,25.54,199900.0001,4 +27,560,02:41.0,1,167.6571429,161000,03:26.4,25.30571429,206400.0001,4 +28,580,02:35.1,1,168.3428571,155100,03:32.6,25.35142857,212599.9999,4 +29,600,02:29.2,1,168.8285714,149200,03:38.6,25.90571429,218599.9999,4 +30,620,02:33.1,1,168.7428571,153100,03:44.7,25.97142857,224700,4 +31,640,02:30.4,1,168.6,150400,03:50.7,25.86571429,230700,4 +32,660,02:29.6,1,168.4,149600,03:56.7,25.81142857,236700,4 +33,680,02:28.1,1,168.3428571,148100,04:02.6,25.72571429,242599.9999,4 +34,700,02:27.7,1,167.8285714,147700,04:08.5,25.31714286,248500,4 +35,720,02:30.0,1,168.2571429,150000,04:14.5,25.11714286,254500,4 +36,740,02:28.1,1,168.7428571,148100,04:20.4,25.24285714,260400.0001,4 +37,760,02:34.3,1,169.0857143,154300,04:26.6,25.32857143,266599.9999,4 +38,780,02:23.0,1,169,143000,04:32.3,25.67428571,272300,4 +39,800,02:26.1,1,169,146100,04:38.2,26.05142857,278200,4 +40,820,02:23.4,1,168.9142857,143400,04:43.9,26.58,283900.0001,4 +41,840,02:31.2,1,169.2571429,151200,04:49.9,26.56,289900.0001,4 +42,860,02:23.0,1,169.7428571,143000,04:55.7,26.81714286,295700,4 +43,880,02:30.0,1,170.0857143,150000,05:01.7,27.07714286,301700,4 +44,900,02:26.5,1,170,146500,05:07.5,27.39428571,307500,4 +45,920,02:20.6,1,170,140600,05:13.1,27.06285714,313099.9999,4 +46,940,02:24.2,1,170,144200,05:18.9,26.73714286,318900.0001,4 +47,960,02:18.3,1,170,138300,05:24.4,26.76,324400.0001,4 +48,980,02:19.9,1,170,139900,05:30.0,26.83428571,330000,4 +49,1000,02:16.7,1,169.9142857,136700,05:35.5,27.01714286,335500,4 +50,1020,02:22.2,1,170.2571429,142200,05:41.2,27.38857143,341200,4 +51,1040,02:23.4,1,170.7428571,143400,05:46.9,27.62857143,346900.0001,4 +52,1060,02:15.6,1,171,135600,05:52.3,27.37142857,352300,4 +53,1080,02:18.3,1,171.2571429,138300,05:57.9,27.40285714,357900.0001,4 +54,1100,02:16.7,1,171.7428571,136700,06:03.3,27.36571429,363300,4 +55,1120,02:24.9,1,172.0857143,144900,06:09.1,27.08285714,369099.9999,4 +56,1140,02:18.7,1,172,138700,06:14.7,26.83142857,374700,4 +57,1160,02:21.8,1,172.0857143,141800,06:20.4,26.92285714,380400.0001,4 +58,1180,02:14.4,1,171.7428571,134400,06:25.7,27.00285714,385700,4 +59,1200,02:18.7,1,171.2571429,138700,06:31.3,27.36857143,391300,4 +60,1220,02:10.5,1,170.9142857,130500,06:36.5,27.42571429,396500,4 +61,1240,02:10.9,1,170.9142857,130900,06:41.7,26.94571429,401700,4 +62,1260,02:15.6,1,171.2571429,135600,06:47.2,26.62857143,407200,4 +63,1280,02:12.4,1,171.7428571,132400,06:52.5,26.80285714,412500,4 +64,1300,02:13.2,1,172.0857143,133200,06:57.8,27.13714286,417800,4 +65,1320,02:09.3,1,172,129300,07:03.0,27.50857143,423000,4 +66,1340,02:06.2,1,171.9142857,126200,07:08.0,27.71142857,428000,4 +67,1360,02:16.0,1,172.2571429,136000,07:13.4,27.73142857,433400.0001,4 +68,1380,02:10.9,1,172.7428571,130900,07:18.7,27.68857143,438700,4 +69,1400,02:20.2,1,173.0857143,140200,07:24.3,27.54857143,444300,4 +70,1420,02:09.3,1,173,129300,07:29.5,27.03428571,449500,4 +71,1440,02:06.2,1,172.9142857,126200,07:34.5,26.83714286,454500,4 +72,1460,02:16.0,1,173.2571429,136000,07:39.9,26.74285714,459900.0001,4 +73,1480,02:10.9,1,173.7428571,130900,07:45.2,26.92571429,465200,4 +74,1500,02:10.5,1,174.0857143,130500,07:50.4,26.86571429,470400.0001,4 +75,1520,02:15.6,1,173.9142857,135600,07:55.8,26.92285714,475800,4 +76,1540,02:16.0,1,174.2571429,136000,08:01.3,26.84857143,481300,4 +77,1560,02:20.2,1,174.7428571,140200,08:06.9,26.97428571,486900.0001,4 +78,1580,02:18.3,1,175.0857143,138300,08:12.4,26.74857143,492400.0001,4 +79,1600,02:25.3,1,175.0857143,145300,08:18.2,26.52857143,498200,4 +80,1620,02:28.1,1,174.7428571,148100,08:24.1,26.40571429,504099.9999,4 +81,1640,02:19.9,1,174.2571429,139900,08:29.7,26.29142857,509700,4 +82,1660,02:12.0,1,173.9142857,132000,08:35.0,26.10857143,515000,4 +83,1680,02:20.2,1,174,140200,08:40.6,26.52285714,520599.9999,4 +84,1700,02:18.3,1,174,138300,08:46.1,26.82285714,526099.9999,4 +85,1720,02:24.9,1,174,144900,08:51.9,26.70571429,531900.0001,4 +86,1740,02:17.9,1,174,137900,08:57.5,26.29142857,537500,4 +87,1760,02:26.9,1,174,146900,09:03.3,26.23142857,543300,4 +88,1780,02:23.4,1,173.9142857,143400,09:09.1,26.46285714,549099.9999,4 +89,1800,02:26.9,1,174.2571429,146900,09:14.9,26.78,554900.0001,4 +90,1820,02:28.1,1,174.7428571,148100,09:20.9,26.66285714,560900.0001,4 +91,1840,02:20.2,1,175.0857143,140200,09:26.5,26.38285714,566500,4 +92,1860,02:15.2,1,175,135200,09:31.9,26.30285714,571900.0001,4 +93,1880,02:20.6,1,174.9142857,140600,09:37.5,26.46,577500,4 +94,1900,02:13.2,1,175.3428571,133200,09:42.8,26.49142857,582800,4 +95,1920,02:19.1,1,175.4,139100,09:48.4,26.88571429,588400.0001,4 +96,1940,02:10.5,1,175.6,130500,09:53.6,27.38285714,593599.9999,4 +97,1960,02:14.8,1,175.6571429,134800,09:59.0,27.04,599000,4 +98,1980,02:16.7,1,176.0857143,136700,10:04.5,26.7,604500,4 +99,2000,02:16.7,1,176,136700,10:09.9,26.51142857,609900.0001,4 +100,2020,02:18.3,1,176,138300,10:15.5,26.86571429,615500,4 +101,2040,02:13.2,1,176,133200,10:20.8,27.09142857,620800,4 +102,2060,02:21.0,1,175.9142857,141000,10:26.4,27.39428571,626400.0001,4 +103,2080,02:18.7,1,176.3428571,138700,10:32.0,27.6,632000,4 +104,2100,02:22.2,1,176.4,142200,10:37.7,27.51714286,637700,4 +105,2120,02:15.6,1,176.6,135600,10:43.1,27.26857143,643099.9999,4 +106,2140,02:19.5,1,176.6571429,139500,10:48.7,27.10571429,648700,4 +107,2160,02:14.0,1,177.0857143,134000,10:54.0,27.24285714,654000,4 +108,2180,02:16.3,1,177,136300,10:59.5,27.28571429,659500,4 +109,2200,02:07.7,1,177,127700,11:04.6,27.29428571,664599.9999,4 +110,2220,02:14.0,1,177,134000,11:10.0,27.52857143,670000,4 +111,2240,02:09.7,1,176.9142857,129700,11:15.1,28.00571429,675099.9999,4 +112,2260,02:15.2,1,177.2571429,135200,11:20.6,28.47142857,680599.9999,4 +113,2280,02:09.7,1,177.7428571,129700,11:25.7,28.77428571,685700,4 +114,2300,02:20.6,1,178.0857143,140600,11:31.4,28.68571429,691400.0001,4 +115,2320,02:20.2,1,177.9142857,140200,11:37.0,28.40571429,697000,4 +116,2340,02:19.9,1,178.2571429,139900,11:42.6,28.06857143,702599.9999,4 +117,2360,02:26.1,1,178.7428571,146100,11:48.4,27.66571429,708400.0001,4 +118,2380,02:15.2,1,179.0857143,135200,11:53.8,27.4,713800,4 +119,2400,02:16.3,1,179,136300,11:59.3,27.36857143,719300,4 +120,2420,02:09.7,1,179,129700,12:04.5,27.51428571,724500,4 +121,2440,02:14.4,1,179,134400,12:09.8,27.82857143,729800,4 +122,2460,02:13.6,1,179,133600,12:15.2,27.65714286,735200,4 +123,2480,02:28.5,1,178.9142857,148500,12:21.1,28.05142857,741099.9999,4 +124,2500,02:25.7,1,179.3428571,145700,12:26.9,28.2,746900.0001,4 +125,2520,02:18.7,1,179.4857143,138700,12:32.5,27.49142857,752500,4 +126,2540,02:30.8,1,179.4285714,150800,12:38.5,26.26285714,758500,4 +127,2560,02:25.7,1,178.5714286,145700,12:44.4,25.65428571,764400.0001,4 +128,2580,02:35.9,1,178.6,155900,12:50.6,25.76,770599.9999,4 +129,2600,02:29.2,1,178.4,149200,12:56.6,25.66857143,776599.9999,4 +130,2620,02:26.5,1,178.3428571,146500,13:02.4,25.59142857,782400.0001,4 +131,2640,02:24.9,1,177.9142857,144900,13:08.2,25.26,788200,4 +132,2660,02:30.0,1,178,150000,13:14.2,25.70571429,794200,4 +133,2680,02:25.3,1,178,145300,13:20.0,26.26571429,800000,4 +134,2700,02:22.6,1,178,142600,13:25.7,26.32,805700,4 +135,2720,02:32.0,1,178,152000,13:31.8,25.91714286,811800,4 +136,2740,02:26.1,1,178,146100,13:37.6,25.96857143,817599.9999,4 +137,2760,02:29.2,1,178,149200,13:43.6,26.02,823599.9999,4 +138,2780,02:23.4,1,178.0857143,143400,13:49.4,26.26571429,829400.0001,4 +139,2800,02:26.5,1,177.6571429,146500,13:55.2,26.35142857,835200,4 +140,2820,02:19.1,1,177.5142857,139100,14:00.8,26.14857143,840800,4 +141,2840,02:25.7,1,177.6571429,145700,14:06.6,26.26857143,846599.9999,4 +142,2860,02:18.7,1,178.0857143,138700,14:12.1,27.1,852099.9999,4 +143,2880,02:19.5,1,178,139500,14:17.7,28.33142857,857700,4 +144,2900,02:28.8,1,178,148800,14:23.7,28.55714286,863700,4 +145,2920,02:32.4,1,178,152400,14:29.8,28.26571429,869800,4 +146,2940,02:21.0,1,178,141000,14:35.4,27.36,875400.0001,4 +147,2960,02:23.0,1,178,143000,14:41.1,27.18571429,881099.9999,4 +148,2980,02:30.8,1,177.9142857,150800,14:47.2,27.18285714,887200,4 +149,3000,02:27.7,1,178.3428571,147700,14:53.1,27.18571429,893099.9999,4 +150,3020,02:25.7,1,178.4,145700,14:58.9,26.68285714,898900.0001,4 +151,3040,02:23.0,1,178.6857143,143000,15:04.6,26.50285714,904599.9999,4 +152,3060,02:23.8,1,178.4,143800,15:10.4,26.31142857,910400.0001,4 +153,3080,02:17.1,1,178.3428571,137100,15:15.9,26.28,915900.0001,4 +154,3100,02:23.8,1,177.9142857,143800,15:21.6,26.49142857,921599.9999,4 +155,3120,02:17.1,1,178,137100,15:27.1,26.78857143,927099.9999,4 +156,3140,02:21.4,1,178,141400,15:32.7,26.59142857,932700,4 +157,3160,02:19.5,1,178,139500,15:38.3,26.32857143,938300,4 +158,3180,02:24.2,1,178,144200,15:44.1,26.28,944099.9999,4 +159,3200,02:17.9,1,177.9142857,137900,15:49.6,26.52857143,949599.9999,4 +160,3220,02:23.0,1,178.3428571,143000,15:55.3,26.70571429,955300,4 +161,3240,02:23.8,1,178.4857143,143800,16:01.1,26.63142857,961099.9999,4 +162,3260,02:31.6,1,178.4285714,151600,16:07.1,26.42857143,967099.9999,4 +163,3280,02:28.8,1,177.6571429,148800,16:13.1,26.63428571,973099.9999,4 +164,3300,02:23.4,1,177.2571429,143400,16:18.8,26.91142857,978800,4 +165,3320,02:29.6,1,176.8285714,149600,16:24.8,27.17428571,984800,4 +166,3340,02:19.9,1,177.2571429,139900,16:30.4,26.91428571,990400.0001,4 +167,3360,02:19.1,1,177.7428571,139100,16:36.0,26.72571429,996000,4 +168,3380,02:20.2,1,178.0857143,140200,16:41.6,26.74857143,1001600,4 +169,3400,02:22.6,1,177.9142857,142600,16:47.3,27.23142857,1007300,4 +170,3420,02:24.5,1,178.3428571,144500,16:53.1,27.3,1013100,4 +171,3440,02:19.5,1,178.4857143,139500,16:58.6,27,1018600,4 +172,3460,02:25.7,1,178.3428571,145700,17:04.5,26.54,1024500,4 +173,3480,02:13.6,1,177.9142857,133600,17:09.8,26.55714286,1029800,4 +174,3500,02:18.3,1,178,138300,17:15.3,26.65714286,1035300,4 +175,3520,02:16.0,1,178,136000,17:20.8,26.85714286,1040800,4 +176,3540,02:16.0,1,178,136000,17:26.2,26.88,1046200,4 +177,3560,02:22.6,1,178,142600,17:31.9,27.08285714,1051900,4 +178,3580,02:21.8,1,177.9142857,141800,17:37.6,27.36285714,1057600,4 +179,3600,02:17.1,1,178.2571429,137100,17:43.1,27.56,1063100,4 +180,3620,02:20.2,1,178.7428571,140200,17:48.7,27.68,1068700,4 +181,3640,02:16.3,1,179.0857143,136300,17:54.1,27.63142857,1074100,4 +182,3660,02:20.6,1,179,140600,17:59.8,27.75142857,1079800,4 +183,3680,02:17.9,1,179,137900,18:05.3,27.38571429,1085300,4 +184,3700,02:21.0,1,179,141000,18:10.9,27.30285714,1090900,4 +185,3720,02:16.3,1,179,136300,18:16.4,27.20571429,1096400,4 +186,3740,02:26.9,1,179,146900,18:22.2,27.24,1102200,4 +187,3760,02:32.4,1,179,152400,18:28.3,26.96571429,1108300,4 +188,3780,02:27.7,1,179,147700,18:34.2,26.4,1114200,4 +189,3800,02:33.5,1,178.9142857,153500,18:40.4,26.11428571,1120400,4 +190,3820,02:22.2,1,179.2571429,142200,18:46.1,26.40857143,1126100,4 +191,3840,02:22.2,1,179.7428571,142200,18:51.8,26.98285714,1131800,4 +192,3860,02:30.4,1,180.1714286,150400,18:57.8,27.06285714,1137800,4 +193,3880,02:22.6,1,179.7428571,142600,19:03.5,26.66571429,1143500,4 +194,3900,02:33.5,1,179.2571429,153500,19:09.6,26.30857143,1149600,4 +195,3920,02:29.2,1,178.8285714,149200,19:15.6,26.57714286,1155600,4 +196,3940,02:24.5,1,179.2571429,144500,19:21.4,27.16571429,1161400,4 +197,3960,02:23.4,1,179.7428571,143400,19:27.1,27.26285714,1167100,4 +198,3980,02:17.5,1,180.0857143,137500,19:32.6,27.38571429,1172600,4 +199,4000,02:18.7,1,179.9142857,138700,19:38.2,28.15714286,1178200,4 +200,4020,02:21.4,1,180.2571429,141400,19:43.8,28.81428571,1183800,4 +201,4040,02:18.7,1,180.7428571,138700,19:49.4,29.13714286,1189400,4 +202,4060,02:23.0,1,181.0857143,143000,19:55.1,28.86857143,1195100,4 +203,4080,02:19.5,1,181,139500,20:00.7,28.32857143,1200700,4 +204,4100,02:12.0,1,181,132000,20:05.9,28.18857143,1205900,4 +205,4120,02:14.4,1,181,134400,20:11.3,28.54571429,1211300,4 +206,4140,02:10.1,1,181,130100,20:16.5,27.95714286,1216500,4 +207,4160,02:17.9,1,181,137900,20:22.0,27.20857143,1222000,4 +208,4180,02:10.9,1,180.9142857,130900,20:27.3,27.03142857,1227300,4 +209,4200,02:16.7,1,182.2,136700,20:32.7,27.56285714,1232700,4 +210,4220,02:15.2,1,177.9714286,135200,20:38.1,27.39428571,1238100,4 +211,4240,02:23.4,1,176.7428571,143400,20:43.9,27.29714286,1243900,4 +212,4260,02:14.0,1,178.2285714,134000,20:49.2,27.35714286,1249200,4 +213,4280,02:20.6,1,182.9428571,140600,20:54.9,27.64,1254900,4 +214,4300,02:16.0,1,182,136000,21:00.3,27.76857143,1260300,4 +215,4320,02:19.1,1,182,139100,21:05.9,27.76571429,1265900,4 +216,4340,02:16.0,1,182,136000,21:11.3,27.46285714,1271300,4 +217,4360,02:18.3,1,182,138300,21:16.8,27.41714286,1276800,4 +218,4380,02:12.0,1,182,132000,21:22.1,27.64285714,1282100,4 +219,4400,02:17.5,1,182,137500,21:27.6,28.02857143,1287600,4 +220,4420,02:12.8,1,182,132800,21:32.9,27.86285714,1292900,4 +221,4440,02:19.5,1,182,139500,21:38.5,27.75428571,1298500,4 +222,4460,02:17.9,1,182,137900,21:44.0,27.56285714,1304000,4 +223,4480,02:13.6,1,182,133600,21:49.4,27.65428571,1309400,4 +224,4500,02:17.1,1,182,137100,21:54.8,27.64571429,1314800,4 +225,4520,02:16.3,1,181.9142857,136300,22:00.3,27.66857143,1320300,4 +226,4540,02:20.2,1,182.2571429,140200,22:05.9,27.82,1300.0001,4 +227,4560,02:14.4,1,182.7428571,134400,22:11.3,27.80857143,1331300,4 +228,4580,02:18.7,1,183.0857143,138700,22:16.8,27.68285714,1336800,4 +229,4600,02:12.4,1,183,132400,22:22.1,27.39428571,1342100,4 +230,4620,02:19.1,1,183,139100,22:27.7,27.61428571,1347700,4 +231,4640,02:11.7,1,183,131700,22:32.9,27.66,1352900,4 +232,4660,02:15.2,1,183,135200,22:38.4,27.98285714,1358400,4 +233,4680,02:10.9,1,183,130900,22:43.6,27.84,1363600,4 +234,4700,02:12.8,1,182.9142857,132800,22:48.9,27.81714286,1368900,4 +235,4720,02:13.6,1,183.2571429,133600,22:54.2,27.81428571,1374200,4 +236,4740,02:13.6,1,183.7428571,133600,22:59.6,27.78571429,1379600,4 +237,4760,02:18.7,1,184.0857143,138700,23:05.1,27.76,1385100,4 +238,4780,02:18.3,1,184,138300,23:10.7,27.95142857,1390700,4 +239,4800,02:07.7,1,184,127700,23:15.8,28.25714286,1395800,4 +240,4820,02:11.3,1,184,131300,23:21.0,28.85142857,1401000,4 +241,4840,02:09.3,1,183.9142857,129300,23:26.2,29.72285714,1406200,4 +242,4860,02:09.3,1,184.2571429,129300,23:31.4,30.53142857,1411400,4 +243,4880,02:03.1,1,184.8285714,123100,23:36.3,31.17142857,1416300,4 +244,4900,02:12.8,1,185.1714286,132800,23:41.6,28.64857143,1421600,4 +245,4920,03:32.5,1,183.5714286,212500,23:50.1,23.55428571,1430100,4 +246,4940,04:06.5,1,181.4571429,246500,24:00.0,17.26571429,1440000,4 +247,4960,04:53.0,1,172.3142857,293000,24:11.7,14.90285714,1451700,4 +249,5000,03:50.9,1,152.7714286,230900,24:33.6,18.27714286,1473600,4 +250,5020,03:38.8,1,150.2857143,218800,24:42.3,20.19142857,1482300,4 +251,5040,02:58.5,1,146.8,178500,24:49.5,18.47142857,1489500,4 +252,5060,03:29.0,1,146.4571429,209000,24:57.8,18.4,1497800,4 +253,5080,02:51.1,1,145.5428571,171100,25:04.7,17.55714286,1504700,4 +254,5100,03:15.7,1,144.6,195700,25:12.5,19.71714286,1512500,4 +255,5120,02:49.2,1,143.3428571,169200,25:19.3,20.26571429,1519300,4 +256,5140,02:45.2,1,143.4857143,165200,25:25.9,21.81714286,1525900,4 +257,5160,03:00.5,1,143.1714286,180500,25:33.1,21.63714286,1533100,4 +258,5180,02:47.2,1,141.9142857,167200,25:39.8,21.34,1539800,4 +259,5200,02:57.7,1,141.1714286,177700,25:46.9,21.07714286,1546900,4 +260,5220,02:53.5,1,141.3428571,173500,25:53.8,21.40285714,1553800,4 +261,5240,03:00.9,1,139.5428571,180900,26:01.1,20.84571429,1561100,4 +263,5280,04:33.1,1,136.4571429,273100,26:25.6,21.45714286,1585600,4 +264,5300,03:21.6,1,135.3428571,201600,26:33.7,20.42857143,1593700,4 +265,5320,03:02.0,1,133.3428571,182000,26:41.0,18.96857143,1601000,4 +266,5340,02:43.7,1,134.0857143,163700,26:47.5,20.21428571,1607500,4 +267,5360,02:39.0,1,135.5714286,159000,26:53.9,20.88857143,1613900,4 +268,5380,02:36.3,1,136.0857143,156300,27:00.1,20.68285714,1620100,4 +269,5400,02:37.8,1,136.2571429,157800,27:06.4,20.77142857,1626400,4 +270,5420,02:33.1,1,136.6571429,153100,27:12.6,20.93714286,1639.9999,4 +271,5440,02:36.7,1,137.2571429,156700,27:18.8,20.66,1638800,4 +272,5460,02:44.9,1,138,164900,27:25.4,20.41714286,1645400,4 +273,5480,02:42.1,1,138.7428571,162100,27:31.9,20.78,1651900,4 +274,5500,02:43.7,1,139.1714286,163700,27:38.5,21.37714286,1658500,4 +275,5520,02:36.7,1,140.1714286,156700,27:44.7,20.03142857,1664700,4 +276,5540,02:49.5,1,141.8285714,169500,27:51.5,19.53142857,1671500,4 +277,5560,02:52.7,1,142.9142857,172700,27:58.4,19.91142857,1678400,4 +278,5580,02:44.1,1,143.0857143,164100,28:05.0,21.20571429,1685000,4 +279,5600,02:44.5,1,143,164500,28:11.5,20.60857143,1691500,4 +280,5620,02:53.1,1,143.0857143,173100,28:18.5,20.82,1698500,4 +281,5640,02:40.6,1,142.8285714,160600,28:24.9,20.61714286,1704900,4 +282,5660,03:00.1,1,142.0857143,180100,28:32.1,19.02285714,1712100,4 +283,5680,03:15.3,1,141,195300,28:39.9,17.61714286,1719900,4 +284,5700,03:25.5,1,140.0857143,205500,28:48.1,18.15714286,1728100,4 +285,5720,03:13.0,1,138.7428571,193000,28:55.8,19.87142857,1735800,4 +286,5740,03:05.2,1,137.2571429,185200,29:03.2,19.95142857,1743200,4 +287,5760,02:55.0,1,135.8285714,175000,29:10.2,19.34,1750200,4 +288,5780,03:13.8,1,135.1714286,193800,29:18.0,19.10857143,1758000,4 +289,5800,03:05.2,1,135,185200,29:25.4,19.75428571,1765400,4 +290,5820,02:47.6,1,134.7428571,167600,29:32.1,19.80857143,1772100,4 +291,5840,02:57.7,1,134.1714286,177700,29:39.2,19.02285714,1779200,4 +292,5860,03:04.8,1,134.2571429,184800,29:46.6,17.70571429,1786600,4 +293,5880,03:01.7,1,134.4857143,181700,29:53.9,16.57714286,1793900,4 +294,5900,03:25.5,1,134.1714286,205500,30:02.1,17.24857143,1802100,4 +295,5920,02:58.9,1,134.4285714,178900,30:09.2,17.98857143,1809200,4 +296,5940,02:35.1,1,135.4857143,155100,30:15.5,19.07714286,1815500,4 +297,5960,02:29.6,1,136.0857143,149600,30:21.4,17.96285714,1821400,4 +298,5980,02:36.7,1,136.2571429,156700,30:27.7,18.49714286,1827700,4 +299,6000,03:03.6,1,136.7428571,183600,30:35.0,15.02857143,1835000,4 +300,6020,03:22.7,1,137.1714286,202700,30:43.2,13.74285714,1843200,4 +301,6040,03:20.4,1,136.7428571,200400,30:51.2,15.00571429,1851200,4 +302,6060,02:53.8,1,136.1714286,173800,30:58.1,19.22285714,1858100,4 +303,6080,02:38.2,1,136,158200,31:04.5,20.82,1864500,4 +304,6100,02:30.0,1,137.1714286,150000,31:10.5,20.95428571,1870500,4 +305,6120,02:29.6,1,138.6571429,149600,31:16.4,21.24857143,1876400,4 +306,6140,02:28.5,1,140.3428571,148500,31:22.4,21.18857143,1882400,4 +307,6160,02:27.3,1,141.9142857,147300,31:28.3,21.90857143,1888300,4 +308,6180,02:41.3,1,142.5714286,161300,31:34.7,17.56571429,1894700,4 +309,6200,03:59.9,1,142.6,239900,31:44.3,15.94,1904300,4 +310,6220,03:55.2,1,142.7428571,235200,31:53.7,17.42285714,1913700,4 +311,6240,02:41.7,1,142.8285714,161700,32:00.2,22.17142857,1920200,4 +312,6260,02:26.9,1,143.6285714,146900,32:06.1,22.28571429,1926100,4 +313,6280,03:09.1,1,138.0571429,189100,32:13.6,19.39714286,1933600,4 +315,6320,04:54.2,1,122.2285714,294200,32:51.5,14.22,1971500,4 +316,6340,04:40.1,1,123.2571429,280100,33:02.7,16.01428571,1982700,4 +317,6360,03:45.4,1,124.2285714,225400,33:11.7,16.48,1991700,4 +318,6380,03:25.9,1,125.8571429,205900,33:19.9,16.66571429,1999900,4 +319,6400,03:41.5,1,127.6571429,221500,33:28.8,16.66285714,2008800,4 +320,6420,03:34.5,1,128.4,214500,33:37.3,17.29142857,2017300,4 +321,6440,03:30.2,1,127.6857143,210200,33:45.8,16.38285714,2025800,4 +322,6460,03:04.8,1,128,184800,33:53.1,16.24,2033100,4 +323,6480,02:45.2,1,130,165200,33:59.8,17.13142857,2039800,4 +324,6500,04:58.8,1,130.7428571,298800,34:11.7,17.76857143,2051700,4 +325,6520,04:37.0,1,128.6571429,277000,34:22.8,17.44857143,2062800,4 +326,6540,04:17.0,1,125.6,257000,34:33.1,15.90571429,2073100,4 +327,6560,03:42.3,1,123.6571429,222300,34:42.0,17.48,2082000,4 +328,6580,03:22.4,1,124.4285714,202400,34:50.0,19.24285714,2090000,4 +329,6600,02:48.4,1,126.8285714,168400,34:56.8,20.73428571,2096800,4 +330,6620,02:51.5,1,129.7428571,171500,35:03.6,21.06,2103600,4 +331,6640,02:35.9,1,132.6857143,155900,35:09.9,24.12,2109900,4 +332,6660,02:42.5,1,133.7142857,162500,35:16.4,15.77428571,2116400,4 +334,6700,04:07.3,1,134.2285714,247300,35:34.6,11.19142857,2134600,4 +335,6720,03:03.6,1,134.0857143,183600,35:42.0,20.16,2142000,4 +336,6740,03:04.8,1,131.8285714,184800,35:49.4,19.37714286,2149400,4 +337,6760,03:04.8,1,130.7714286,184800,35:56.8,18.00571429,2156800,4 +338,6780,03:08.7,1,130.0571429,188700,36:04.3,17.85428571,2164300,4 +339,6800,03:06.0,1,129.5142857,186000,36:11.7,18.40571429,2171700,4 +340,6820,03:01.7,1,129.0857143,181700,36:19.0,19.38285714,2179000,4 +341,6840,02:51.5,1,129.7428571,171500,36:25.9,18.68571429,2185900,4 +342,6860,02:54.2,1,130.1714286,174200,36:32.8,18.47142857,2192800,4 +343,6880,02:55.0,1,129.7428571,175000,36:39.8,18.82285714,2199800,4 +344,6900,03:43.8,1,129.1714286,223800,36:48.8,17.32285714,2208800,4 +345,6920,03:35.6,1,129.3428571,215600,36:57.4,16.45428571,2217400,4 +346,6940,03:09.9,1,129.3142857,189900,37:05.0,16.78571429,2225000,4 +347,6960,03:14.2,1,128.2571429,194200,37:12.8,18.57428571,2232800,4 +348,6980,03:18.8,1,127.3428571,198800,37:20.7,18.82,2240700,4 +349,7000,03:27.4,1,127.7428571,207400,37:29.0,18.33428571,2249000,4 +350,7020,03:06.0,1,127.9142857,186000,37:36.5,16.97142857,2256500,4 +351,7040,03:07.5,1,127,187500,37:44.0,17.31428571,2264000,4 +352,7060,03:05.2,1,126.0857143,185200,37:51.4,15.52857143,2271400,4 +353,7080,03:42.7,1,126.1714286,222700,38:00.3,15.28285714,2280300,4 +354,7100,03:29.4,1,126.8285714,209400,38:08.6,16.79714286,2288600,4 +355,7120,03:10.2,1,126.5714286,190200,38:16.3,18.70571429,2296300,4 +356,7140,03:19.2,1,126.9428571,199200,38:24.2,17.78285714,2304200,4 +357,7160,02:56.2,1,128.4857143,176200,38:31.3,18.33142857,2311300,4 +358,7180,02:53.8,1,129.7428571,173800,38:38.2,20.31714286,2318200,4 +359,7200,02:55.8,1,129.1714286,175800,38:45.3,20.25714286,2325300,4 +360,7220,02:43.7,1,129.3428571,163700,38:51.8,20.09714286,2331800,4 +361,7240,02:42.9,1,130.6571429,162900,38:58.3,20.16571429,2338300,4 +362,7260,02:39.4,1,132.1714286,159400,39:04.7,20.67142857,2344700,4 +363,7280,02:35.9,1,132.5714286,155900,39:10.9,21.14857143,2350900,4 +364,7300,02:41.3,1,133.6857143,161300,39:17.4,20.89142857,2357400,4 +365,7320,02:35.9,1,135.6571429,155900,39:23.6,20.22285714,2363600,4 +366,7340,02:37.8,1,137.9142857,157800,39:29.9,20.23428571,2369900,4 +367,7360,02:37.0,1,139.0857143,157000,39:36.2,20.97142857,2376200,4 +368,7380,02:36.7,1,140,156700,39:42.5,20.93714286,2382500,4 +369,7400,02:35.1,1,141.1714286,155100,39:48.7,20.72571429,2388700,4 +370,7420,02:43.3,1,141.5714286,163300,39:55.2,19.34571429,2395200,4 +371,7440,02:59.3,1,141.3428571,179300,40:02.4,19.09714286,2402400,4 +372,7460,03:03.6,1,140.9142857,183600,40:09.7,19.59142857,2409700,4 +373,7480,02:40.6,1,140.9142857,160600,40:16.1,21.23142857,2416100,4 +374,7500,02:48.8,1,141.2571429,168800,40:22.9,21.16571429,2422900,4 +375,7520,02:39.0,1,141.8285714,159000,40:29.3,21.35428571,2429300,4 +376,7540,02:33.9,1,141.9142857,153900,40:35.4,21.19142857,2435400,4 +377,7560,02:47.6,1,141.0857143,167600,40:42.1,20.27428571,2442100,4 +378,7580,03:02.0,1,140.1714286,182000,40:49.4,19.01714286,2449400,4 +379,7600,03:09.5,1,138.4857143,189500,40:57.0,16.88,2457000,4 +380,7620,03:34.9,1,136.6,214900,41:05.6,14.68,2465600,4 +381,7640,03:27.4,1,134.5714286,207400,41:13.9,15.78285714,2473900,4 +382,7660,03:04.8,1,133.3428571,184800,41:21.3,18.14857143,2481300,4 +383,7680,03:11.8,1,131.8285714,191800,41:28.9,18.93428571,2488900,4 +384,7700,03:24.3,1,129.8285714,204300,41:37.1,20.09714286,2497100,4 +385,7720,03:25.9,1,127.2571429,205900,41:45.3,22.05428571,2505300,4 +386,7740,03:39.2,1,124.7428571,219200,41:54.1,20.40571429,2514100,4 +387,7760,04:09.6,1,123.3428571,249600,42:04.1,17.76,2524100,4 +388,7780,03:13.8,1,122.8285714,193800,42:11.8,17.50857143,2531800,4 +389,7800,03:03.2,1,122.7428571,183200,42:19.2,18.88571429,2539200,4 +390,7820,02:44.5,1,123.6857143,164500,42:25.7,19.37142857,2545700,4 +391,7840,02:35.5,1,125.5714286,155500,42:32.0,19.36,2552000,4 +392,7860,02:46.4,1,126.6571429,166400,42:38.6,18.94571429,2558600,4 +393,7880,02:53.1,1,126.5142857,173100,42:45.5,18.05714286,2565500,4 +394,7900,02:58.5,1,127,178500,42:52.7,18.42571429,2572700,4 +395,7920,02:50.7,1,127.5714286,170700,42:59.5,19.13428571,2579500,4 +396,7940,03:16.1,1,127.4285714,196100,43:07.3,18.88857143,2587300,4 +397,7960,03:12.6,1,126.6571429,192600,43:15.0,17.72285714,2595000,4 +398,7980,03:09.9,1,127.4571429,189900,43:22.6,17.56571429,2602600,4 +399,8000,03:21.2,1,120.9428571,201200,43:30.7,17.82571429,2610700,4 +400,8020,03:07.1,1,119.8,187100,43:38.2,17.67142857,2618200,4 +401,8040,02:55.0,1,122.6,175000,43:45.2,17.52571429,2625200,4 +402,8060,03:00.5,1,128.0285714,180500,43:52.4,19.36571429,2632400,4 +404,8100,03:02.8,1,125.4,182800,44:11.9,19.29714286,2651900,4 +405,8120,02:57.0,1,125,177000,44:19.0,18.31428571,2659000,4 +406,8140,03:05.6,1,124.5142857,185600,44:26.4,18.44285714,2666400,4 +407,8160,03:12.6,1,124.5714286,192600,44:34.1,18.39142857,2674100,4 +408,8180,03:02.0,1,123.8285714,182000,44:41.4,15.79714286,2681400,4 +409,8200,03:57.5,1,122.3428571,237500,44:50.9,15.76,2690900,4 +410,8220,03:24.3,1,122.0857143,204300,44:59.1,17.60571429,2699100,4 +411,8240,03:09.9,1,122.5714286,189900,45:06.7,19.90857143,2706700,4 +412,8260,02:55.4,1,123.3428571,175400,45:13.7,19.60857143,2713700,4 +413,8280,02:48.8,1,125.1714286,168800,45:20.5,20.53428571,2720500,4 +414,8300,02:45.6,1,127.5714286,165600,45:27.1,21.03714286,2727100,4 +415,8320,02:48.8,1,129.0857143,168800,45:33.8,20.94,2733800,4 +416,8340,02:45.2,1,130.3428571,165200,45:40.4,20.74285714,2740400,4 +417,8360,02:44.5,1,131.4857143,164500,45:47.0,21.22285714,2747000,4 +418,8380,02:44.1,1,132.4285714,164100,45:53.6,20.41428571,2753600,4 +419,8400,02:46.8,1,132.5714286,166800,46:00.3,20.10857143,2760300,4 +420,8420,02:39.4,1,133.6857143,159400,46:06.6,20.84,2766600,4 +421,8440,02:49.9,1,134.2285714,169900,46:13.4,19.14857143,2773400,4 +422,8460,03:00.9,1,134.4285714,180900,46:20.7,18.04285714,2780700,4 +423,8480,02:56.6,1,134.0857143,176600,46:27.7,17.96285714,2787700,4 +424,8500,02:55.0,1,133.4857143,175000,46:34.7,19.39428571,2794700,4 +425,8520,02:56.2,1,132.5142857,176200,46:41.8,19.5,2801800,4 +426,8540,02:53.8,1,131.7428571,173800,46:48.7,19.76285714,2808700,4 +427,8560,02:46.4,1,132.4285714,166400,46:55.4,19.37714286,2815400,4 +428,8580,02:42.5,1,132.3142857,162500,47:01.9,19.22571429,2821900,4 +429,8600,02:57.0,1,131.3428571,177000,47:09.0,19.37428571,2829000,4 +430,8620,03:09.9,1,130,189900,47:16.5,19.66571429,2836500,4 +431,8640,02:49.9,1,130.3428571,169900,47:23.3,18.85714286,2843300,4 +432,8660,02:46.4,1,130.4,166400,47:30.0,19.05714286,2850000,4 +433,8680,02:50.3,1,129.0857143,170300,47:36.8,17.12285714,2856800,4 +434,8700,02:58.1,1,127.4285714,178100,47:43.9,17.06571429,2863900,4 +435,8720,03:07.9,1,126.4857143,187900,47:51.5,17.68,2871500,4 +436,8740,02:58.1,1,126.4285714,178100,47:58.6,20.31428571,2878600,4 +437,8760,02:55.4,1,127,175400,48:05.6,18.96857143,2885600,4 +438,8780,03:12.6,1,127.4857143,192600,48:13.3,18.59714286,2893300,4 +439,8800,03:05.2,1,127.2571429,185200,48:20.7,19.44,2900700,4 +440,8820,02:58.9,1,128.8571429,178900,48:27.9,21.48857143,2907900,4 +441,8840,02:45.6,1,130.6285714,165600,48:34.5,18.81714286,2914500,4 +442,8860,03:02.4,1,130.7714286,182400,48:41.8,16.06,2921800,4 +443,8880,03:28.6,1,128.5714286,208600,48:50.1,15.00857143,2930100,4 +444,8900,03:20.8,1,127.4285714,200800,48:58.2,17.34571429,2938200,4 +445,8920,02:52.7,1,126.8285714,172700,49:05.1,18.52571429,2945100,4 +446,8940,02:50.3,1,127,170300,49:11.9,19.74857143,2951900,4 +447,8960,02:54.6,1,127,174600,49:18.9,20.26571429,2958900,4 +448,8980,02:47.6,1,126.8285714,167600,49:25.6,20.20571429,2965600,4 +449,9000,02:43.7,1,127.2571429,163700,49:32.1,19.37142857,2972100,4 +450,9020,02:46.0,1,129.0857143,166000,49:38.8,19.47142857,2978800,4 +451,9040,02:57.0,1,131.8285714,177000,49:45.8,20.43714286,2985800,4 +452,9060,02:35.5,1,133.8285714,155500,49:52.1,20.92857143,2992100,4 +453,9080,02:28.8,1,135.3428571,148800,49:58.0,20.89714286,2998000,4 +454,9100,02:30.4,1,136.7428571,150400,50:04.0,21.40285714,3004000,4 +455,9120,02:26.5,1,138.0857143,146500,50:09.9,22.31142857,3009900,4 +456,9140,02:26.9,1,138.9142857,146900,50:15.8,22.7,3015800,4 +457,9160,02:36.7,1,140.2571429,156700,50:22.0,22.59428571,3022000,4 +458,9180,02:30.0,1,141.7428571,150000,50:28.0,22.43142857,3028000,4 +459,9200,02:29.2,1,143.0857143,149200,50:34.0,22.20857143,3034000,4 +460,9220,02:27.3,1,144.2571429,147300,50:39.9,21.71142857,3039900,4 +461,9240,02:35.5,1,146.0285714,155500,50:46.1,23.12857143,3046100,4 +462,9260,03:08.3,1,138.9714286,188300,50:53.6,22.98857143,3053600,4 +463,9280,04:01.4,1,126.3428571,241400,51:03.3,13.11142857,3063300,4 +465,9320,03:36.4,1,117.5714286,216400,51:25.0,11.70571429,3085000,4 +466,9340,03:51.3,1,119.9142857,231300,51:34.3,19.73714286,3094300,4 +467,9360,03:22.0,1,122.0857143,202000,51:42.3,18.46857143,3102300,4 +468,9380,03:16.1,1,125.7142857,196100,51:50.2,15.80285714,3110200,4 +469,9400,03:25.9,1,118.5714286,205900,51:58.4,16.25428571,3118400,4 +471,9440,03:14.2,1,110.0285714,194200,52:23.5,20.32285714,3143500,4 +472,9460,02:58.9,1,118.1428571,178900,52:30.7,19.28285714,3150700,4 +473,9480,02:50.3,1,122.3142857,170300,52:37.5,17.68,3157500,4 +474,9500,04:10.0,1,127.4571429,250000,52:47.5,17.38,3167500,4 +475,9520,03:45.0,1,126.8857143,225000,52:56.5,16.28,3176500,4 +479,80,03:30.6,2,127.2857143,210600,01:02.5,18.89142857,62500,4 +480,100,03:25.9,2,132.5142857,205900,01:10.8,18.57714286,70799.99995,4 +481,120,03:00.5,2,135.2571429,180500,01:18.0,21.22571429,78000,4 +482,140,02:32.0,2,140,152000,01:24.1,24.74857143,84099.9999,4 +483,160,02:13.2,2,146.0857143,133200,01:29.4,27.41714286,89400.0001,4 +484,180,02:15.6,2,151.9142857,135600,01:34.8,27.46857143,94799.99995,4 +485,200,02:16.0,2,155.6571429,136000,01:40.3,27.24857143,100300,4 +486,220,02:23.8,2,157.1714286,143800,01:46.0,27.2,106000,4 +487,240,02:15.6,2,158.2571429,135600,01:51.4,27.46285714,111400.0001,4 +488,260,02:24.2,2,159.7428571,144200,01:57.2,27.71428571,117200,4 +489,280,02:11.7,2,161.1714286,131700,02:02.5,27.48285714,122500,4 +490,300,02:22.6,2,161.7428571,142600,02:08.2,27.20857143,128200,4 +491,320,02:18.7,2,162.2571429,138700,02:13.7,26.65142857,133700,4 +492,340,02:28.5,2,162.9142857,148500,02:19.6,26.58285714,139599.9999,4 +493,360,02:32.7,2,164,152700,02:25.8,26.19142857,145800,4 +494,380,02:26.9,2,165.0857143,146900,02:31.6,25.69428571,151599.9999,4 +495,400,02:31.6,2,165.8285714,151600,02:37.7,25.55714286,157700,4 +496,420,02:21.0,2,166.0857143,141000,02:43.3,25.83142857,163300,4 +497,440,02:33.5,2,166,153500,02:49.5,26.14857143,169500,4 +498,460,02:35.1,2,165.9142857,155100,02:55.7,26.13714286,175700,4 +499,480,02:25.3,2,166.2571429,145300,03:01.5,26.7,181500,4 +500,500,02:34.7,2,166.7428571,154700,03:07.7,26.58571429,187700,4 +501,520,02:34.7,2,167,154700,03:13.9,26.28857143,193900.0001,4 +502,540,02:32.0,2,167.2571429,152000,03:19.9,25.54,199900.0001,4 +503,560,02:41.0,2,167.6571429,161000,03:26.4,25.30571429,206400.0001,4 +504,580,02:35.1,2,168.3428571,155100,03:32.6,25.35142857,212599.9999,4 +505,600,02:29.2,2,168.8285714,149200,03:38.6,25.90571429,218599.9999,4 +506,620,02:33.1,2,168.7428571,153100,03:44.7,25.97142857,224700,4 +507,640,02:30.4,2,168.6,150400,03:50.7,25.86571429,230700,4 +508,660,02:29.6,2,168.4,149600,03:56.7,25.81142857,236700,4 +509,680,02:28.1,2,168.3428571,148100,04:02.6,25.72571429,242599.9999,4 +510,700,02:27.7,2,167.8285714,147700,04:08.5,25.31714286,248500,4 +511,720,02:30.0,2,168.2571429,150000,04:14.5,25.11714286,254500,4 +512,740,02:28.1,2,168.7428571,148100,04:20.4,25.24285714,260400.0001,4 +513,760,02:34.3,2,169.0857143,154300,04:26.6,25.32857143,266599.9999,4 +514,780,02:23.0,2,169,143000,04:32.3,25.67428571,272300,4 +515,800,02:26.1,2,169,146100,04:38.2,26.05142857,278200,4 +516,820,02:23.4,2,168.9142857,143400,04:43.9,26.58,283900.0001,4 +517,840,02:31.2,2,169.2571429,151200,04:49.9,26.56,289900.0001,4 +518,860,02:23.0,2,169.7428571,143000,04:55.7,26.81714286,295700,4 +519,880,02:30.0,2,170.0857143,150000,05:01.7,27.07714286,301700,4 +520,900,02:26.5,2,170,146500,05:07.5,27.39428571,307500,4 +521,920,02:20.6,2,170,140600,05:13.1,27.06285714,313099.9999,4 +522,940,02:24.2,2,170,144200,05:18.9,26.73714286,318900.0001,4 +523,960,02:18.3,2,170,138300,05:24.4,26.76,324400.0001,4 +524,980,02:19.9,2,170,139900,05:30.0,26.83428571,330000,4 +525,1000,02:16.7,2,169.9142857,136700,05:35.5,27.01714286,335500,4 +526,1020,02:22.2,2,170.2571429,142200,05:41.2,27.38857143,341200,4 +527,1040,02:23.4,2,170.7428571,143400,05:46.9,27.62857143,346900.0001,4 +528,1060,02:15.6,2,171,135600,05:52.3,27.37142857,352300,4 +529,1080,02:18.3,2,171.2571429,138300,05:57.9,27.40285714,357900.0001,4 +530,1100,02:16.7,2,171.7428571,136700,06:03.3,27.36571429,363300,4 +531,1120,02:24.9,2,172.0857143,144900,06:09.1,27.08285714,369099.9999,4 +532,1140,02:18.7,2,172,138700,06:14.7,26.83142857,374700,4 +533,1160,02:21.8,2,172.0857143,141800,06:20.4,26.92285714,380400.0001,4 +534,1180,02:14.4,2,171.7428571,134400,06:25.7,27.00285714,385700,4 +535,1200,02:18.7,2,171.2571429,138700,06:31.3,27.36857143,391300,4 +536,1220,02:10.5,2,170.9142857,130500,06:36.5,27.42571429,396500,4 +537,1240,02:10.9,2,170.9142857,130900,06:41.7,26.94571429,401700,4 +538,1260,02:15.6,2,171.2571429,135600,06:47.2,26.62857143,407200,4 +539,1280,02:12.4,2,171.7428571,132400,06:52.5,26.80285714,412500,4 +540,1300,02:13.2,2,172.0857143,133200,06:57.8,27.13714286,417800,4 +541,1320,02:09.3,2,172,129300,07:03.0,27.50857143,423000,4 +542,1340,02:06.2,2,171.9142857,126200,07:08.0,27.71142857,428000,4 +543,1360,02:16.0,2,172.2571429,136000,07:13.4,27.73142857,433400.0001,4 +544,1380,02:10.9,2,172.7428571,130900,07:18.7,27.68857143,438700,4 +545,1400,02:20.2,2,173.0857143,140200,07:24.3,27.54857143,444300,4 +546,1420,02:09.3,2,173,129300,07:29.5,27.03428571,449500,4 +547,1440,02:06.2,2,172.9142857,126200,07:34.5,26.83714286,454500,4 +548,1460,02:16.0,2,173.2571429,136000,07:39.9,26.74285714,459900.0001,4 +549,1480,02:10.9,2,173.7428571,130900,07:45.2,26.92571429,465200,4 +550,1500,02:10.5,2,174.0857143,130500,07:50.4,26.86571429,470400.0001,4 +551,1520,02:15.6,2,173.9142857,135600,07:55.8,26.92285714,475800,4 +552,1540,02:16.0,2,174.2571429,136000,08:01.3,26.84857143,481300,4 +553,1560,02:20.2,2,174.7428571,140200,08:06.9,26.97428571,486900.0001,4 +554,1580,02:18.3,2,175.0857143,138300,08:12.4,26.74857143,492400.0001,4 +555,1600,02:25.3,2,175.0857143,145300,08:18.2,26.52857143,498200,4 +556,1620,02:28.1,2,174.7428571,148100,08:24.1,26.40571429,504099.9999,4 +557,1640,02:19.9,2,174.2571429,139900,08:29.7,26.29142857,509700,4 +558,1660,02:12.0,2,173.9142857,132000,08:35.0,26.10857143,515000,4 +559,1680,02:20.2,2,174,140200,08:40.6,26.52285714,520599.9999,4 +560,1700,02:18.3,2,174,138300,08:46.1,26.82285714,526099.9999,4 +561,1720,02:24.9,2,174,144900,08:51.9,26.70571429,531900.0001,4 +562,1740,02:17.9,2,174,137900,08:57.5,26.29142857,537500,4 +563,1760,02:26.9,2,174,146900,09:03.3,26.23142857,543300,4 +564,1780,02:23.4,2,173.9142857,143400,09:09.1,26.46285714,549099.9999,4 +565,1800,02:26.9,2,174.2571429,146900,09:14.9,26.78,554900.0001,4 +566,1820,02:28.1,2,174.7428571,148100,09:20.9,26.66285714,560900.0001,4 +567,1840,02:20.2,2,175.0857143,140200,09:26.5,26.38285714,566500,4 +568,1860,02:15.2,2,175,135200,09:31.9,26.30285714,571900.0001,4 +569,1880,02:20.6,2,174.9142857,140600,09:37.5,26.46,577500,4 +570,1900,02:13.2,2,175.3428571,133200,09:42.8,26.49142857,582800,4 +571,1920,02:19.1,2,175.4,139100,09:48.4,26.88571429,588400.0001,4 +572,1940,02:10.5,2,175.6,130500,09:53.6,27.38285714,593599.9999,4 +573,1960,02:14.8,2,175.6571429,134800,09:59.0,27.04,599000,4 +574,1980,02:16.7,2,176.0857143,136700,10:04.5,26.7,604500,4 +575,2000,02:16.7,2,176,136700,10:09.9,26.51142857,609900.0001,4 +576,2020,02:18.3,2,176,138300,10:15.5,26.86571429,615500,4 +577,2040,02:13.2,2,176,133200,10:20.8,27.09142857,620800,4 +578,2060,02:21.0,2,175.9142857,141000,10:26.4,27.39428571,626400.0001,4 +579,2080,02:18.7,2,176.3428571,138700,10:32.0,27.6,632000,4 +580,2100,02:22.2,2,176.4,142200,10:37.7,27.51714286,637700,4 +581,2120,02:15.6,2,176.6,135600,10:43.1,27.26857143,643099.9999,4 +582,2140,02:19.5,2,176.6571429,139500,10:48.7,27.10571429,648700,4 +583,2160,02:14.0,2,177.0857143,134000,10:54.0,27.24285714,654000,4 +584,2180,02:16.3,2,177,136300,10:59.5,27.28571429,659500,4 +585,2200,02:07.7,2,177,127700,11:04.6,27.29428571,664599.9999,4 +586,2220,02:14.0,2,177,134000,11:10.0,27.52857143,670000,4 +587,2240,02:09.7,2,176.9142857,129700,11:15.1,28.00571429,675099.9999,4 +588,2260,02:15.2,2,177.2571429,135200,11:20.6,28.47142857,680599.9999,4 +589,2280,02:09.7,2,177.7428571,129700,11:25.7,28.77428571,685700,4 +590,2300,02:20.6,2,178.0857143,140600,11:31.4,28.68571429,691400.0001,4 +591,2320,02:20.2,2,177.9142857,140200,11:37.0,28.40571429,697000,4 +592,2340,02:19.9,2,178.2571429,139900,11:42.6,28.06857143,702599.9999,4 +593,2360,02:26.1,2,178.7428571,146100,11:48.4,27.66571429,708400.0001,4 +594,2380,02:15.2,2,179.0857143,135200,11:53.8,27.4,713800,4 +595,2400,02:16.3,2,179,136300,11:59.3,27.36857143,719300,4 +596,2420,02:09.7,2,179,129700,12:04.5,27.51428571,724500,4 +597,2440,02:14.4,2,179,134400,12:09.8,27.82857143,729800,4 +598,2460,02:13.6,2,179,133600,12:15.2,27.65714286,735200,4 +599,2480,02:28.5,2,178.9142857,148500,12:21.1,28.05142857,741099.9999,4 +600,2500,02:25.7,2,179.3428571,145700,12:26.9,28.2,746900.0001,4 +601,2520,02:18.7,2,179.4857143,138700,12:32.5,27.49142857,752500,4 +602,2540,02:30.8,2,179.4285714,150800,12:38.5,26.26285714,758500,4 +603,2560,02:25.7,2,178.5714286,145700,12:44.4,25.65428571,764400.0001,4 +604,2580,02:35.9,2,178.6,155900,12:50.6,25.76,770599.9999,4 +605,2600,02:29.2,2,178.4,149200,12:56.6,25.66857143,776599.9999,4 +606,2620,02:26.5,2,178.3428571,146500,13:02.4,25.59142857,782400.0001,4 +607,2640,02:24.9,2,177.9142857,144900,13:08.2,25.26,788200,4 +608,2660,02:30.0,2,178,150000,13:14.2,25.70571429,794200,4 +609,2680,02:25.3,2,178,145300,13:20.0,26.26571429,800000,4 +610,2700,02:22.6,2,178,142600,13:25.7,26.32,805700,4 +611,2720,02:32.0,2,178,152000,13:31.8,25.91714286,811800,4 +612,2740,02:26.1,2,178,146100,13:37.6,25.96857143,817599.9999,4 +613,2760,02:29.2,2,178,149200,13:43.6,26.02,823599.9999,4 +614,2780,02:23.4,2,178.0857143,143400,13:49.4,26.26571429,829400.0001,4 +615,2800,02:26.5,2,177.6571429,146500,13:55.2,26.35142857,835200,4 +616,2820,02:19.1,2,177.5142857,139100,14:00.8,26.14857143,840800,4 +617,2840,02:25.7,2,177.6571429,145700,14:06.6,26.26857143,846599.9999,4 +618,2860,02:18.7,2,178.0857143,138700,14:12.1,27.1,852099.9999,4 +619,2880,02:19.5,2,178,139500,14:17.7,28.33142857,857700,4 +620,2900,02:28.8,2,178,148800,14:23.7,28.55714286,863700,4 +621,2920,02:32.4,2,178,152400,14:29.8,28.26571429,869800,4 +622,2940,02:21.0,2,178,141000,14:35.4,27.36,875400.0001,4 +623,2960,02:23.0,2,178,143000,14:41.1,27.18571429,881099.9999,4 +624,2980,02:30.8,2,177.9142857,150800,14:47.2,27.18285714,887200,4 +625,3000,02:27.7,2,178.3428571,147700,14:53.1,27.18571429,893099.9999,4 +626,3020,02:25.7,2,178.4,145700,14:58.9,26.68285714,898900.0001,4 +627,3040,02:23.0,2,178.6857143,143000,15:04.6,26.50285714,904599.9999,4 +628,3060,02:23.8,2,178.4,143800,15:10.4,26.31142857,910400.0001,4 +629,3080,02:17.1,2,178.3428571,137100,15:15.9,26.28,915900.0001,4 +630,3100,02:23.8,2,177.9142857,143800,15:21.6,26.49142857,921599.9999,4 +631,3120,02:17.1,2,178,137100,15:27.1,26.78857143,927099.9999,4 +632,3140,02:21.4,2,178,141400,15:32.7,26.59142857,932700,4 +633,3160,02:19.5,2,178,139500,15:38.3,26.32857143,938300,4 +634,3180,02:24.2,2,178,144200,15:44.1,26.28,944099.9999,4 +635,3200,02:17.9,2,177.9142857,137900,15:49.6,26.52857143,949599.9999,4 +636,3220,02:23.0,2,178.3428571,143000,15:55.3,26.70571429,955300,4 +637,3240,02:23.8,2,178.4857143,143800,16:01.1,26.63142857,961099.9999,4 +638,3260,02:31.6,2,178.4285714,151600,16:07.1,26.42857143,967099.9999,4 +639,3280,02:28.8,2,177.6571429,148800,16:13.1,26.63428571,973099.9999,4 +640,3300,02:23.4,2,177.2571429,143400,16:18.8,26.91142857,978800,4 +641,3320,02:29.6,2,176.8285714,149600,16:24.8,27.17428571,984800,4 +642,3340,02:19.9,2,177.2571429,139900,16:30.4,26.91428571,990400.0001,4 +643,3360,02:19.1,2,177.7428571,139100,16:36.0,26.72571429,996000,4 +644,3380,02:20.2,2,178.0857143,140200,16:41.6,26.74857143,1001600,4 +645,3400,02:22.6,2,177.9142857,142600,16:47.3,27.23142857,1007300,4 +646,3420,02:24.5,2,178.3428571,144500,16:53.1,27.3,1013100,4 +647,3440,02:19.5,2,178.4857143,139500,16:58.6,27,1018600,4 +648,3460,02:25.7,2,178.3428571,145700,17:04.5,26.54,1024500,4 +649,3480,02:13.6,2,177.9142857,133600,17:09.8,26.55714286,1029800,4 +650,3500,02:18.3,2,178,138300,17:15.3,26.65714286,1035300,4 +651,3520,02:16.0,2,178,136000,17:20.8,26.85714286,1040800,4 +652,3540,02:16.0,2,178,136000,17:26.2,26.88,1046200,4 +653,3560,02:22.6,2,178,142600,17:31.9,27.08285714,1051900,4 +654,3580,02:21.8,2,177.9142857,141800,17:37.6,27.36285714,1057600,4 +655,3600,02:17.1,2,178.2571429,137100,17:43.1,27.56,1063100,4 +656,3620,02:20.2,2,178.7428571,140200,17:48.7,27.68,1068700,4 +657,3640,02:16.3,2,179.0857143,136300,17:54.1,27.63142857,1074100,4 +658,3660,02:20.6,2,179,140600,17:59.8,27.75142857,1079800,4 +659,3680,02:17.9,2,179,137900,18:05.3,27.38571429,1085300,4 +660,3700,02:21.0,2,179,141000,18:10.9,27.30285714,1090900,4 +661,3720,02:16.3,2,179,136300,18:16.4,27.20571429,1096400,4 +662,3740,02:26.9,2,179,146900,18:22.2,27.24,1102200,4 +663,3760,02:32.4,2,179,152400,18:28.3,26.96571429,1108300,4 +664,3780,02:27.7,2,179,147700,18:34.2,26.4,1114200,4 +665,3800,02:33.5,2,178.9142857,153500,18:40.4,26.11428571,1120400,4 +666,3820,02:22.2,2,179.2571429,142200,18:46.1,26.40857143,1126100,4 +667,3840,02:22.2,2,179.7428571,142200,18:51.8,26.98285714,1131800,4 +668,3860,02:30.4,2,180.1714286,150400,18:57.8,27.06285714,1137800,4 +669,3880,02:22.6,2,179.7428571,142600,19:03.5,26.66571429,1143500,4 +670,3900,02:33.5,2,179.2571429,153500,19:09.6,26.30857143,1149600,4 +671,3920,02:29.2,2,178.8285714,149200,19:15.6,26.57714286,1155600,4 +672,3940,02:24.5,2,179.2571429,144500,19:21.4,27.16571429,1161400,4 +673,3960,02:23.4,2,179.7428571,143400,19:27.1,27.26285714,1167100,4 +674,3980,02:17.5,2,180.0857143,137500,19:32.6,27.38571429,1172600,4 +675,4000,02:18.7,2,179.9142857,138700,19:38.2,28.15714286,1178200,4 +676,4020,02:21.4,2,180.2571429,141400,19:43.8,28.81428571,1183800,4 +677,4040,02:18.7,2,180.7428571,138700,19:49.4,29.13714286,1189400,4 +678,4060,02:23.0,2,181.0857143,143000,19:55.1,28.86857143,1195100,4 +679,4080,02:19.5,2,181,139500,20:00.7,28.32857143,1200700,4 +680,4100,02:12.0,2,181,132000,20:05.9,28.18857143,1205900,4 +681,4120,02:14.4,2,181,134400,20:11.3,28.54571429,1211300,4 +682,4140,02:10.1,2,181,130100,20:16.5,27.95714286,1216500,4 +683,4160,02:17.9,2,181,137900,20:22.0,27.20857143,1222000,4 +684,4180,02:10.9,2,180.9142857,130900,20:27.3,27.03142857,1227300,4 +685,4200,02:16.7,2,182.2,136700,20:32.7,27.56285714,1232700,4 +686,4220,02:15.2,2,177.9714286,135200,20:38.1,27.39428571,1238100,4 +687,4240,02:23.4,2,176.7428571,143400,20:43.9,27.29714286,1243900,4 +688,4260,02:14.0,2,178.2285714,134000,20:49.2,27.35714286,1249200,4 +689,4280,02:20.6,2,182.9428571,140600,20:54.9,27.64,1254900,4 +690,4300,02:16.0,2,182,136000,21:00.3,27.76857143,1260300,4 +691,4320,02:19.1,2,182,139100,21:05.9,27.76571429,1265900,4 +692,4340,02:16.0,2,182,136000,21:11.3,27.46285714,1271300,4 +693,4360,02:18.3,2,182,138300,21:16.8,27.41714286,1276800,4 +694,4380,02:12.0,2,182,132000,21:22.1,27.64285714,1282100,4 +695,4400,02:17.5,2,182,137500,21:27.6,28.02857143,1287600,4 +696,4420,02:12.8,2,182,132800,21:32.9,27.86285714,1292900,4 +697,4440,02:19.5,2,182,139500,21:38.5,27.75428571,1298500,4 +698,4460,02:17.9,2,182,137900,21:44.0,27.56285714,1304000,4 +699,4480,02:13.6,2,182,133600,21:49.4,27.65428571,1309400,4 +700,4500,02:17.1,2,182,137100,21:54.8,27.64571429,1314800,4 +701,4520,02:16.3,2,181.9142857,136300,22:00.3,27.66857143,1320300,4 +702,4540,02:20.2,2,182.2571429,140200,22:05.9,27.82,1300.0001,4 +703,4560,02:14.4,2,182.7428571,134400,22:11.3,27.80857143,1331300,4 +704,4580,02:18.7,2,183.0857143,138700,22:16.8,27.68285714,1336800,4 +705,4600,02:12.4,2,183,132400,22:22.1,27.39428571,1342100,4 +706,4620,02:19.1,2,183,139100,22:27.7,27.61428571,1347700,4 +707,4640,02:11.7,2,183,131700,22:32.9,27.66,1352900,4 +708,4660,02:15.2,2,183,135200,22:38.4,27.98285714,1358400,4 +709,4680,02:10.9,2,183,130900,22:43.6,27.84,1363600,4 +710,4700,02:12.8,2,182.9142857,132800,22:48.9,27.81714286,1368900,4 +711,4720,02:13.6,2,183.2571429,133600,22:54.2,27.81428571,1374200,4 +712,4740,02:13.6,2,183.7428571,133600,22:59.6,27.78571429,1379600,4 +713,4760,02:18.7,2,184.0857143,138700,23:05.1,27.76,1385100,4 +714,4780,02:18.3,2,184,138300,23:10.7,27.95142857,1390700,4 +715,4800,02:07.7,2,184,127700,23:15.8,28.25714286,1395800,4 +716,4820,02:11.3,2,184,131300,23:21.0,28.85142857,1401000,4 +717,4840,02:09.3,2,183.9142857,129300,23:26.2,29.72285714,1406200,4 +718,4860,02:09.3,2,184.2571429,129300,23:31.4,30.53142857,1411400,4 +719,4880,02:03.1,2,184.8285714,123100,23:36.3,31.17142857,1416300,4 +720,4900,02:12.8,2,185.1714286,132800,23:41.6,28.64857143,1421600,4 +721,4920,03:32.5,2,183.5714286,212500,23:50.1,23.55428571,1430100,4 +722,4940,04:06.5,2,181.4571429,246500,24:00.0,17.26571429,1440000,4 +723,4960,04:53.0,2,172.3142857,293000,24:11.7,14.90285714,1451700,4 +725,5000,03:50.9,2,152.7714286,230900,24:33.6,18.27714286,1473600,4 +726,5020,03:38.8,2,150.2857143,218800,24:42.3,20.19142857,1482300,4 +727,5040,02:58.5,2,146.8,178500,24:49.5,18.47142857,1489500,4 +728,5060,03:29.0,2,146.4571429,209000,24:57.8,18.4,1497800,4 +729,5080,02:51.1,2,145.5428571,171100,25:04.7,17.55714286,1504700,4 +730,5100,03:15.7,2,144.6,195700,25:12.5,19.71714286,1512500,4 +731,5120,02:49.2,2,143.3428571,169200,25:19.3,20.26571429,1519300,4 +732,5140,02:45.2,2,143.4857143,165200,25:25.9,21.81714286,1525900,4 +733,5160,03:00.5,2,143.1714286,180500,25:33.1,21.63714286,1533100,4 +734,5180,02:47.2,2,141.9142857,167200,25:39.8,21.34,1539800,4 +735,5200,02:57.7,2,141.1714286,177700,25:46.9,21.07714286,1546900,4 +736,5220,02:53.5,2,141.3428571,173500,25:53.8,21.40285714,1553800,4 +737,5240,03:00.9,2,139.5428571,180900,26:01.1,20.84571429,1561100,4 +739,5280,04:33.1,2,136.4571429,273100,26:25.6,21.45714286,1585600,4 +740,5300,03:21.6,2,135.3428571,201600,26:33.7,20.42857143,1593700,4 +741,5320,03:02.0,2,133.3428571,182000,26:41.0,18.96857143,1601000,4 +742,5340,02:43.7,2,134.0857143,163700,26:47.5,20.21428571,1607500,4 +743,5360,02:39.0,2,135.5714286,159000,26:53.9,20.88857143,1613900,4 +744,5380,02:36.3,2,136.0857143,156300,27:00.1,20.68285714,1620100,4 +745,5400,02:37.8,2,136.2571429,157800,27:06.4,20.77142857,1626400,4 +746,5420,02:33.1,2,136.6571429,153100,27:12.6,20.93714286,1639.9999,4 +747,5440,02:36.7,2,137.2571429,156700,27:18.8,20.66,1638800,4 +748,5460,02:44.9,2,138,164900,27:25.4,20.41714286,1645400,4 +749,5480,02:42.1,2,138.7428571,162100,27:31.9,20.78,1651900,4 +750,5500,02:43.7,2,139.1714286,163700,27:38.5,21.37714286,1658500,4 +751,5520,02:36.7,2,140.1714286,156700,27:44.7,20.03142857,1664700,4 +752,5540,02:49.5,2,141.8285714,169500,27:51.5,19.53142857,1671500,4 +753,5560,02:52.7,2,142.9142857,172700,27:58.4,19.91142857,1678400,4 +754,5580,02:44.1,2,143.0857143,164100,28:05.0,21.20571429,1685000,4 +755,5600,02:44.5,2,143,164500,28:11.5,20.60857143,1691500,4 +756,5620,02:53.1,2,143.0857143,173100,28:18.5,20.82,1698500,4 +757,5640,02:40.6,2,142.8285714,160600,28:24.9,20.61714286,1704900,4 +758,5660,03:00.1,2,142.0857143,180100,28:32.1,19.02285714,1712100,4 +759,5680,03:15.3,2,141,195300,28:39.9,17.61714286,1719900,4 +760,5700,03:25.5,2,140.0857143,205500,28:48.1,18.15714286,1728100,4 +761,5720,03:13.0,2,138.7428571,193000,28:55.8,19.87142857,1735800,4 +762,5740,03:05.2,2,137.2571429,185200,29:03.2,19.95142857,1743200,4 +763,5760,02:55.0,2,135.8285714,175000,29:10.2,19.34,1750200,4 +764,5780,03:13.8,2,135.1714286,193800,29:18.0,19.10857143,1758000,4 +765,5800,03:05.2,2,135,185200,29:25.4,19.75428571,1765400,4 +766,5820,02:47.6,2,134.7428571,167600,29:32.1,19.80857143,1772100,4 +767,5840,02:57.7,2,134.1714286,177700,29:39.2,19.02285714,1779200,4 +768,5860,03:04.8,2,134.2571429,184800,29:46.6,17.70571429,1786600,4 +769,5880,03:01.7,2,134.4857143,181700,29:53.9,16.57714286,1793900,4 +770,5900,03:25.5,2,134.1714286,205500,30:02.1,17.24857143,1802100,4 +771,5920,02:58.9,2,134.4285714,178900,30:09.2,17.98857143,1809200,4 +772,5940,02:35.1,2,135.4857143,155100,30:15.5,19.07714286,1815500,4 +773,5960,02:29.6,2,136.0857143,149600,30:21.4,17.96285714,1821400,4 +774,5980,02:36.7,2,136.2571429,156700,30:27.7,18.49714286,1827700,4 +775,6000,03:03.6,2,136.7428571,183600,30:35.0,15.02857143,1835000,4 +776,6020,03:22.7,2,137.1714286,202700,30:43.2,13.74285714,1843200,4 +777,6040,03:20.4,2,136.7428571,200400,30:51.2,15.00571429,1851200,4 +778,6060,02:53.8,2,136.1714286,173800,30:58.1,19.22285714,1858100,4 +779,6080,02:38.2,2,136,158200,31:04.5,20.82,1864500,4 +780,6100,02:30.0,2,137.1714286,150000,31:10.5,20.95428571,1870500,4 +781,6120,02:29.6,2,138.6571429,149600,31:16.4,21.24857143,1876400,4 +782,6140,02:28.5,2,140.3428571,148500,31:22.4,21.18857143,1882400,4 +783,6160,02:27.3,2,141.9142857,147300,31:28.3,21.90857143,1888300,4 +784,6180,02:41.3,2,142.5714286,161300,31:34.7,17.56571429,1894700,4 +785,6200,03:59.9,2,142.6,239900,31:44.3,15.94,1904300,4 +786,6220,03:55.2,2,142.7428571,235200,31:53.7,17.42285714,1913700,4 +787,6240,02:41.7,2,142.8285714,161700,32:00.2,22.17142857,1920200,4 +788,6260,02:26.9,2,143.6285714,146900,32:06.1,22.28571429,1926100,4 +789,6280,03:09.1,2,138.0571429,189100,32:13.6,19.39714286,1933600,4 +791,6320,04:54.2,2,122.2285714,294200,32:51.5,14.22,1971500,4 +792,6340,04:40.1,2,123.2571429,280100,33:02.7,16.01428571,1982700,4 +793,6360,03:45.4,2,124.2285714,225400,33:11.7,16.48,1991700,4 +794,6380,03:25.9,2,125.8571429,205900,33:19.9,16.66571429,1999900,4 +795,6400,03:41.5,2,127.6571429,221500,33:28.8,16.66285714,2008800,4 +796,6420,03:34.5,2,128.4,214500,33:37.3,17.29142857,2017300,4 +797,6440,03:30.2,2,127.6857143,210200,33:45.8,16.38285714,2025800,4 +798,6460,03:04.8,2,128,184800,33:53.1,16.24,2033100,4 +799,6480,02:45.2,2,130,165200,33:59.8,17.13142857,2039800,4 +800,6500,04:58.8,2,130.7428571,298800,34:11.7,17.76857143,2051700,4 +801,6520,04:37.0,2,128.6571429,277000,34:22.8,17.44857143,2062800,4 +802,6540,04:17.0,2,125.6,257000,34:33.1,15.90571429,2073100,4 +803,6560,03:42.3,2,123.6571429,222300,34:42.0,17.48,2082000,4 +804,6580,03:22.4,2,124.4285714,202400,34:50.0,19.24285714,2090000,4 +805,6600,02:48.4,2,126.8285714,168400,34:56.8,20.73428571,2096800,4 +806,6620,02:51.5,2,129.7428571,171500,35:03.6,21.06,2103600,4 +807,6640,02:35.9,2,132.6857143,155900,35:09.9,24.12,2109900,4 +808,6660,02:42.5,2,133.7142857,162500,35:16.4,15.77428571,2116400,4 +810,6700,04:07.3,2,134.2285714,247300,35:34.6,11.19142857,2134600,4 +811,6720,03:03.6,2,134.0857143,183600,35:42.0,20.16,2142000,4 +812,6740,03:04.8,2,131.8285714,184800,35:49.4,19.37714286,2149400,4 +813,6760,03:04.8,2,130.7714286,184800,35:56.8,18.00571429,2156800,4 +814,6780,03:08.7,2,130.0571429,188700,36:04.3,17.85428571,2164300,4 +815,6800,03:06.0,2,129.5142857,186000,36:11.7,18.40571429,2171700,4 +816,6820,03:01.7,2,129.0857143,181700,36:19.0,19.38285714,2179000,4 +817,6840,02:51.5,2,129.7428571,171500,36:25.9,18.68571429,2185900,4 +818,6860,02:54.2,2,130.1714286,174200,36:32.8,18.47142857,2192800,4 +819,6880,02:55.0,2,129.7428571,175000,36:39.8,18.82285714,2199800,4 +820,6900,03:43.8,2,129.1714286,223800,36:48.8,17.32285714,2208800,4 +821,6920,03:35.6,2,129.3428571,215600,36:57.4,16.45428571,2217400,4 +822,6940,03:09.9,2,129.3142857,189900,37:05.0,16.78571429,2225000,4 +823,6960,03:14.2,2,128.2571429,194200,37:12.8,18.57428571,2232800,4 +824,6980,03:18.8,2,127.3428571,198800,37:20.7,18.82,2240700,4 +825,7000,03:27.4,2,127.7428571,207400,37:29.0,18.33428571,2249000,4 +826,7020,03:06.0,2,127.9142857,186000,37:36.5,16.97142857,2256500,4 +827,7040,03:07.5,2,127,187500,37:44.0,17.31428571,2264000,4 +828,7060,03:05.2,2,126.0857143,185200,37:51.4,15.52857143,2271400,4 +829,7080,03:42.7,2,126.1714286,222700,38:00.3,15.28285714,2280300,4 +830,7100,03:29.4,2,126.8285714,209400,38:08.6,16.79714286,2288600,4 +831,7120,03:10.2,2,126.5714286,190200,38:16.3,18.70571429,2296300,4 +832,7140,03:19.2,2,126.9428571,199200,38:24.2,17.78285714,2304200,4 +833,7160,02:56.2,2,128.4857143,176200,38:31.3,18.33142857,2311300,4 +834,7180,02:53.8,2,129.7428571,173800,38:38.2,20.31714286,2318200,4 +835,7200,02:55.8,2,129.1714286,175800,38:45.3,20.25714286,2325300,4 +836,7220,02:43.7,2,129.3428571,163700,38:51.8,20.09714286,2331800,4 +837,7240,02:42.9,2,130.6571429,162900,38:58.3,20.16571429,2338300,4 +838,7260,02:39.4,2,132.1714286,159400,39:04.7,20.67142857,2344700,4 +839,7280,02:35.9,2,132.5714286,155900,39:10.9,21.14857143,2350900,4 +840,7300,02:41.3,2,133.6857143,161300,39:17.4,20.89142857,2357400,4 +841,7320,02:35.9,2,135.6571429,155900,39:23.6,20.22285714,2363600,4 +842,7340,02:37.8,2,137.9142857,157800,39:29.9,20.23428571,2369900,4 +843,7360,02:37.0,2,139.0857143,157000,39:36.2,20.97142857,2376200,4 +844,7380,02:36.7,2,140,156700,39:42.5,20.93714286,2382500,4 +845,7400,02:35.1,2,141.1714286,155100,39:48.7,20.72571429,2388700,4 +846,7420,02:43.3,2,141.5714286,163300,39:55.2,19.34571429,2395200,4 +847,7440,02:59.3,2,141.3428571,179300,40:02.4,19.09714286,2402400,4 +848,7460,03:03.6,2,140.9142857,183600,40:09.7,19.59142857,2409700,4 +849,7480,02:40.6,2,140.9142857,160600,40:16.1,21.23142857,2416100,4 +850,7500,02:48.8,2,141.2571429,168800,40:22.9,21.16571429,2422900,4 +851,7520,02:39.0,2,141.8285714,159000,40:29.3,21.35428571,2429300,4 +852,7540,02:33.9,2,141.9142857,153900,40:35.4,21.19142857,2435400,4 +853,7560,02:47.6,2,141.0857143,167600,40:42.1,20.27428571,2442100,4 +854,7580,03:02.0,2,140.1714286,182000,40:49.4,19.01714286,2449400,4 +855,7600,03:09.5,2,138.4857143,189500,40:57.0,16.88,2457000,4 +856,7620,03:34.9,2,136.6,214900,41:05.6,14.68,2465600,4 +857,7640,03:27.4,2,134.5714286,207400,41:13.9,15.78285714,2473900,4 +858,7660,03:04.8,2,133.3428571,184800,41:21.3,18.14857143,2481300,4 +859,7680,03:11.8,2,131.8285714,191800,41:28.9,18.93428571,2488900,4 +860,7700,03:24.3,2,129.8285714,204300,41:37.1,20.09714286,2497100,4 +861,7720,03:25.9,2,127.2571429,205900,41:45.3,22.05428571,2505300,4 +862,7740,03:39.2,2,124.7428571,219200,41:54.1,20.40571429,2514100,4 +863,7760,04:09.6,2,123.3428571,249600,42:04.1,17.76,2524100,4 +864,7780,03:13.8,2,122.8285714,193800,42:11.8,17.50857143,2531800,4 +865,7800,03:03.2,2,122.7428571,183200,42:19.2,18.88571429,2539200,4 +866,7820,02:44.5,2,123.6857143,164500,42:25.7,19.37142857,2545700,4 +867,7840,02:35.5,2,125.5714286,155500,42:32.0,19.36,2552000,4 +868,7860,02:46.4,2,126.6571429,166400,42:38.6,18.94571429,2558600,4 +869,7880,02:53.1,2,126.5142857,173100,42:45.5,18.05714286,2565500,4 +870,7900,02:58.5,2,127,178500,42:52.7,18.42571429,2572700,4 +871,7920,02:50.7,2,127.5714286,170700,42:59.5,19.13428571,2579500,4 +872,7940,03:16.1,2,127.4285714,196100,43:07.3,18.88857143,2587300,4 +873,7960,03:12.6,2,126.6571429,192600,43:15.0,17.72285714,2595000,4 +874,7980,03:09.9,2,127.4571429,189900,43:22.6,17.56571429,2602600,4 +875,8000,03:21.2,2,120.9428571,201200,43:30.7,17.82571429,2610700,4 +876,8020,03:07.1,2,119.8,187100,43:38.2,17.67142857,2618200,4 +877,8040,02:55.0,2,122.6,175000,43:45.2,17.52571429,2625200,4 +878,8060,03:00.5,2,128.0285714,180500,43:52.4,19.36571429,2632400,4 +880,8100,03:02.8,2,125.4,182800,44:11.9,19.29714286,2651900,4 +881,8120,02:57.0,2,125,177000,44:19.0,18.31428571,2659000,4 +882,8140,03:05.6,2,124.5142857,185600,44:26.4,18.44285714,2666400,4 +883,8160,03:12.6,2,124.5714286,192600,44:34.1,18.39142857,2674100,4 +884,8180,03:02.0,2,123.8285714,182000,44:41.4,15.79714286,2681400,4 +885,8200,03:57.5,2,122.3428571,237500,44:50.9,15.76,2690900,4 +886,8220,03:24.3,2,122.0857143,204300,44:59.1,17.60571429,2699100,4 +887,8240,03:09.9,2,122.5714286,189900,45:06.7,19.90857143,2706700,4 +888,8260,02:55.4,2,123.3428571,175400,45:13.7,19.60857143,2713700,4 +889,8280,02:48.8,2,125.1714286,168800,45:20.5,20.53428571,2720500,4 +890,8300,02:45.6,2,127.5714286,165600,45:27.1,21.03714286,2727100,4 +891,8320,02:48.8,2,129.0857143,168800,45:33.8,20.94,2733800,4 +892,8340,02:45.2,2,130.3428571,165200,45:40.4,20.74285714,2740400,4 +893,8360,02:44.5,2,131.4857143,164500,45:47.0,21.22285714,2747000,4 +894,8380,02:44.1,2,132.4285714,164100,45:53.6,20.41428571,2753600,4 +895,8400,02:46.8,2,132.5714286,166800,46:00.3,20.10857143,2760300,4 +896,8420,02:39.4,2,133.6857143,159400,46:06.6,20.84,2766600,4 +897,8440,02:49.9,2,134.2285714,169900,46:13.4,19.14857143,2773400,4 +898,8460,03:00.9,2,134.4285714,180900,46:20.7,18.04285714,2780700,4 +899,8480,02:56.6,2,134.0857143,176600,46:27.7,17.96285714,2787700,4 +900,8500,02:55.0,2,133.4857143,175000,46:34.7,19.39428571,2794700,4 +901,8520,02:56.2,2,132.5142857,176200,46:41.8,19.5,2801800,4 +902,8540,02:53.8,2,131.7428571,173800,46:48.7,19.76285714,2808700,4 +903,8560,02:46.4,2,132.4285714,166400,46:55.4,19.37714286,2815400,4 +904,8580,02:42.5,2,132.3142857,162500,47:01.9,19.22571429,2821900,4 +905,8600,02:57.0,2,131.3428571,177000,47:09.0,19.37428571,2829000,4 +906,8620,03:09.9,2,130,189900,47:16.5,19.66571429,2836500,4 +907,8640,02:49.9,2,130.3428571,169900,47:23.3,18.85714286,2843300,4 +908,8660,02:46.4,2,130.4,166400,47:30.0,19.05714286,2850000,4 +909,8680,02:50.3,2,129.0857143,170300,47:36.8,17.12285714,2856800,4 +910,8700,02:58.1,2,127.4285714,178100,47:43.9,17.06571429,2863900,4 +911,8720,03:07.9,2,126.4857143,187900,47:51.5,17.68,2871500,4 +912,8740,02:58.1,2,126.4285714,178100,47:58.6,20.31428571,2878600,4 +913,8760,02:55.4,2,127,175400,48:05.6,18.96857143,2885600,4 +914,8780,03:12.6,2,127.4857143,192600,48:13.3,18.59714286,2893300,4 +915,8800,03:05.2,2,127.2571429,185200,48:20.7,19.44,2900700,4 +916,8820,02:58.9,2,128.8571429,178900,48:27.9,21.48857143,2907900,4 +917,8840,02:45.6,2,130.6285714,165600,48:34.5,18.81714286,2914500,4 +918,8860,03:02.4,2,130.7714286,182400,48:41.8,16.06,2921800,4 +919,8880,03:28.6,2,128.5714286,208600,48:50.1,15.00857143,2930100,4 +920,8900,03:20.8,2,127.4285714,200800,48:58.2,17.34571429,2938200,4 +921,8920,02:52.7,2,126.8285714,172700,49:05.1,18.52571429,2945100,4 +922,8940,02:50.3,2,127,170300,49:11.9,19.74857143,2951900,4 +923,8960,02:54.6,2,127,174600,49:18.9,20.26571429,2958900,4 +924,8980,02:47.6,2,126.8285714,167600,49:25.6,20.20571429,2965600,4 +925,9000,02:43.7,2,127.2571429,163700,49:32.1,19.37142857,2972100,4 +926,9020,02:46.0,2,129.0857143,166000,49:38.8,19.47142857,2978800,4 +927,9040,02:57.0,2,131.8285714,177000,49:45.8,20.43714286,2985800,4 +928,9060,02:35.5,2,133.8285714,155500,49:52.1,20.92857143,2992100,4 +929,9080,02:28.8,2,135.3428571,148800,49:58.0,20.89714286,2998000,4 +930,9100,02:30.4,2,136.7428571,150400,50:04.0,21.40285714,3004000,4 +931,9120,02:26.5,2,138.0857143,146500,50:09.9,22.31142857,3009900,4 +932,9140,02:26.9,2,138.9142857,146900,50:15.8,22.7,3015800,4 +933,9160,02:36.7,2,140.2571429,156700,50:22.0,22.59428571,3022000,4 +934,9180,02:30.0,2,141.7428571,150000,50:28.0,22.43142857,3028000,4 +935,9200,02:29.2,2,143.0857143,149200,50:34.0,22.20857143,3034000,4 +936,9220,02:27.3,2,144.2571429,147300,50:39.9,21.71142857,3039900,4 +937,9240,02:35.5,2,146.0285714,155500,50:46.1,23.12857143,3046100,4 +938,9260,03:08.3,2,138.9714286,188300,50:53.6,22.98857143,3053600,4 +939,9280,04:01.4,2,126.3428571,241400,51:03.3,13.11142857,3063300,4 +941,9320,03:36.4,2,117.5714286,216400,51:25.0,11.70571429,3085000,4 +942,9340,03:51.3,2,119.9142857,231300,51:34.3,19.73714286,3094300,4 +943,9360,03:22.0,2,122.0857143,202000,51:42.3,18.46857143,3102300,4 +944,9380,03:16.1,2,125.7142857,196100,51:50.2,15.80285714,3110200,4 +945,9400,03:25.9,2,118.5714286,205900,51:58.4,16.25428571,3118400,4 +947,9440,03:14.2,2,110.0285714,194200,52:23.5,20.32285714,3143500,4 +948,9460,02:58.9,2,118.1428571,178900,52:30.7,19.28285714,3150700,4 +949,9480,02:50.3,2,122.3142857,170300,52:37.5,17.68,3157500,4 +950,9500,04:10.0,2,127.4571429,250000,52:47.5,17.38,3167500,4 +951,9520,03:45.0,2,126.8857143,225000,52:56.5,16.28,3176500,4 +955,80,03:30.6,3,127.2857143,210600,01:02.5,18.89142857,62500,4 +956,100,03:25.9,3,132.5142857,205900,01:10.8,18.57714286,70799.99995,4 +957,120,03:00.5,3,135.2571429,180500,01:18.0,21.22571429,78000,4 +958,140,02:32.0,3,140,152000,01:24.1,24.74857143,84099.9999,4 +959,160,02:13.2,3,146.0857143,133200,01:29.4,27.41714286,89400.0001,4 +960,180,02:15.6,3,151.9142857,135600,01:34.8,27.46857143,94799.99995,4 +961,200,02:16.0,3,155.6571429,136000,01:40.3,27.24857143,100300,4 +962,220,02:23.8,3,157.1714286,143800,01:46.0,27.2,106000,4 +963,240,02:15.6,3,158.2571429,135600,01:51.4,27.46285714,111400.0001,4 +964,260,02:24.2,3,159.7428571,144200,01:57.2,27.71428571,117200,4 +965,280,02:11.7,3,161.1714286,131700,02:02.5,27.48285714,122500,4 +966,300,02:22.6,3,161.7428571,142600,02:08.2,27.20857143,128200,4 +967,320,02:18.7,3,162.2571429,138700,02:13.7,26.65142857,133700,4 +968,340,02:28.5,3,162.9142857,148500,02:19.6,26.58285714,139599.9999,4 +969,360,02:32.7,3,164,152700,02:25.8,26.19142857,145800,4 +970,380,02:26.9,3,165.0857143,146900,02:31.6,25.69428571,151599.9999,4 +971,400,02:31.6,3,165.8285714,151600,02:37.7,25.55714286,157700,4 +972,420,02:21.0,3,166.0857143,141000,02:43.3,25.83142857,163300,4 +973,440,02:33.5,3,166,153500,02:49.5,26.14857143,169500,4 +974,460,02:35.1,3,165.9142857,155100,02:55.7,26.13714286,175700,4 +975,480,02:25.3,3,166.2571429,145300,03:01.5,26.7,181500,4 +976,500,02:34.7,3,166.7428571,154700,03:07.7,26.58571429,187700,4 +977,520,02:34.7,3,167,154700,03:13.9,26.28857143,193900.0001,4 +978,540,02:32.0,3,167.2571429,152000,03:19.9,25.54,199900.0001,4 +979,560,02:41.0,3,167.6571429,161000,03:26.4,25.30571429,206400.0001,4 +980,580,02:35.1,3,168.3428571,155100,03:32.6,25.35142857,212599.9999,4 +981,600,02:29.2,3,168.8285714,149200,03:38.6,25.90571429,218599.9999,4 +982,620,02:33.1,3,168.7428571,153100,03:44.7,25.97142857,224700,4 +983,640,02:30.4,3,168.6,150400,03:50.7,25.86571429,230700,4 +984,660,02:29.6,3,168.4,149600,03:56.7,25.81142857,236700,4 +985,680,02:28.1,3,168.3428571,148100,04:02.6,25.72571429,242599.9999,4 +986,700,02:27.7,3,167.8285714,147700,04:08.5,25.31714286,248500,4 +987,720,02:30.0,3,168.2571429,150000,04:14.5,25.11714286,254500,4 +988,740,02:28.1,3,168.7428571,148100,04:20.4,25.24285714,260400.0001,4 +989,760,02:34.3,3,169.0857143,154300,04:26.6,25.32857143,266599.9999,4 +990,780,02:23.0,3,169,143000,04:32.3,25.67428571,272300,4 +991,800,02:26.1,3,169,146100,04:38.2,26.05142857,278200,4 +992,820,02:23.4,3,168.9142857,143400,04:43.9,26.58,283900.0001,4 +993,840,02:31.2,3,169.2571429,151200,04:49.9,26.56,289900.0001,4 +994,860,02:23.0,3,169.7428571,143000,04:55.7,26.81714286,295700,4 +995,880,02:30.0,3,170.0857143,150000,05:01.7,27.07714286,301700,4 +996,900,02:26.5,3,170,146500,05:07.5,27.39428571,307500,4 +997,920,02:20.6,3,170,140600,05:13.1,27.06285714,313099.9999,4 +998,940,02:24.2,3,170,144200,05:18.9,26.73714286,318900.0001,4 +999,960,02:18.3,3,170,138300,05:24.4,26.76,324400.0001,4 +1000,980,02:19.9,3,170,139900,05:30.0,26.83428571,330000,4 +1001,1000,02:16.7,3,169.9142857,136700,05:35.5,27.01714286,335500,4 +1002,1020,02:22.2,3,170.2571429,142200,05:41.2,27.38857143,341200,4 +1003,1040,02:23.4,3,170.7428571,143400,05:46.9,27.62857143,346900.0001,4 +1004,1060,02:15.6,3,171,135600,05:52.3,27.37142857,352300,4 +1005,1080,02:18.3,3,171.2571429,138300,05:57.9,27.40285714,357900.0001,4 +1006,1100,02:16.7,3,171.7428571,136700,06:03.3,27.36571429,363300,4 +1007,1120,02:24.9,3,172.0857143,144900,06:09.1,27.08285714,369099.9999,4 +1008,1140,02:18.7,3,172,138700,06:14.7,26.83142857,374700,4 +1009,1160,02:21.8,3,172.0857143,141800,06:20.4,26.92285714,380400.0001,4 +1010,1180,02:14.4,3,171.7428571,134400,06:25.7,27.00285714,385700,4 +1011,1200,02:18.7,3,171.2571429,138700,06:31.3,27.36857143,391300,4 +1012,1220,02:10.5,3,170.9142857,130500,06:36.5,27.42571429,396500,4 +1013,1240,02:10.9,3,170.9142857,130900,06:41.7,26.94571429,401700,4 +1014,1260,02:15.6,3,171.2571429,135600,06:47.2,26.62857143,407200,4 +1015,1280,02:12.4,3,171.7428571,132400,06:52.5,26.80285714,412500,4 +1016,1300,02:13.2,3,172.0857143,133200,06:57.8,27.13714286,417800,4 +1017,1320,02:09.3,3,172,129300,07:03.0,27.50857143,423000,4 +1018,1340,02:06.2,3,171.9142857,126200,07:08.0,27.71142857,428000,4 +1019,1360,02:16.0,3,172.2571429,136000,07:13.4,27.73142857,433400.0001,4 +1020,1380,02:10.9,3,172.7428571,130900,07:18.7,27.68857143,438700,4 +1021,1400,02:20.2,3,173.0857143,140200,07:24.3,27.54857143,444300,4 +1022,1420,02:09.3,3,173,129300,07:29.5,27.03428571,449500,4 +1023,1440,02:06.2,3,172.9142857,126200,07:34.5,26.83714286,454500,4 +1024,1460,02:16.0,3,173.2571429,136000,07:39.9,26.74285714,459900.0001,4 +1025,1480,02:10.9,3,173.7428571,130900,07:45.2,26.92571429,465200,4 +1026,1500,02:10.5,3,174.0857143,130500,07:50.4,26.86571429,470400.0001,4 +1027,1520,02:15.6,3,173.9142857,135600,07:55.8,26.92285714,475800,4 +1028,1540,02:16.0,3,174.2571429,136000,08:01.3,26.84857143,481300,4 +1029,1560,02:20.2,3,174.7428571,140200,08:06.9,26.97428571,486900.0001,4 +1030,1580,02:18.3,3,175.0857143,138300,08:12.4,26.74857143,492400.0001,4 +1031,1600,02:25.3,3,175.0857143,145300,08:18.2,26.52857143,498200,4 +1032,1620,02:28.1,3,174.7428571,148100,08:24.1,26.40571429,504099.9999,4 +1033,1640,02:19.9,3,174.2571429,139900,08:29.7,26.29142857,509700,4 +1034,1660,02:12.0,3,173.9142857,132000,08:35.0,26.10857143,515000,4 +1035,1680,02:20.2,3,174,140200,08:40.6,26.52285714,520599.9999,4 +1036,1700,02:18.3,3,174,138300,08:46.1,26.82285714,526099.9999,4 +1037,1720,02:24.9,3,174,144900,08:51.9,26.70571429,531900.0001,4 +1038,1740,02:17.9,3,174,137900,08:57.5,26.29142857,537500,4 +1039,1760,02:26.9,3,174,146900,09:03.3,26.23142857,543300,4 +1040,1780,02:23.4,3,173.9142857,143400,09:09.1,26.46285714,549099.9999,4 +1041,1800,02:26.9,3,174.2571429,146900,09:14.9,26.78,554900.0001,4 +1042,1820,02:28.1,3,174.7428571,148100,09:20.9,26.66285714,560900.0001,4 +1043,1840,02:20.2,3,175.0857143,140200,09:26.5,26.38285714,566500,4 +1044,1860,02:15.2,3,175,135200,09:31.9,26.30285714,571900.0001,4 +1045,1880,02:20.6,3,174.9142857,140600,09:37.5,26.46,577500,4 +1046,1900,02:13.2,3,175.3428571,133200,09:42.8,26.49142857,582800,4 +1047,1920,02:19.1,3,175.4,139100,09:48.4,26.88571429,588400.0001,4 +1048,1940,02:10.5,3,175.6,130500,09:53.6,27.38285714,593599.9999,4 +1049,1960,02:14.8,3,175.6571429,134800,09:59.0,27.04,599000,4 +1050,1980,02:16.7,3,176.0857143,136700,10:04.5,26.7,604500,4 +1051,2000,02:16.7,3,176,136700,10:09.9,26.51142857,609900.0001,4 +1052,2020,02:18.3,3,176,138300,10:15.5,26.86571429,615500,4 +1053,2040,02:13.2,3,176,133200,10:20.8,27.09142857,620800,4 +1054,2060,02:21.0,3,175.9142857,141000,10:26.4,27.39428571,626400.0001,4 +1055,2080,02:18.7,3,176.3428571,138700,10:32.0,27.6,632000,4 +1056,2100,02:22.2,3,176.4,142200,10:37.7,27.51714286,637700,4 +1057,2120,02:15.6,3,176.6,135600,10:43.1,27.26857143,643099.9999,4 +1058,2140,02:19.5,3,176.6571429,139500,10:48.7,27.10571429,648700,4 +1059,2160,02:14.0,3,177.0857143,134000,10:54.0,27.24285714,654000,4 +1060,2180,02:16.3,3,177,136300,10:59.5,27.28571429,659500,4 +1061,2200,02:07.7,3,177,127700,11:04.6,27.29428571,664599.9999,4 +1062,2220,02:14.0,3,177,134000,11:10.0,27.52857143,670000,4 +1063,2240,02:09.7,3,176.9142857,129700,11:15.1,28.00571429,675099.9999,4 +1064,2260,02:15.2,3,177.2571429,135200,11:20.6,28.47142857,680599.9999,4 +1065,2280,02:09.7,3,177.7428571,129700,11:25.7,28.77428571,685700,4 +1066,2300,02:20.6,3,178.0857143,140600,11:31.4,28.68571429,691400.0001,4 +1067,2320,02:20.2,3,177.9142857,140200,11:37.0,28.40571429,697000,4 +1068,2340,02:19.9,3,178.2571429,139900,11:42.6,28.06857143,702599.9999,4 +1069,2360,02:26.1,3,178.7428571,146100,11:48.4,27.66571429,708400.0001,4 +1070,2380,02:15.2,3,179.0857143,135200,11:53.8,27.4,713800,4 +1071,2400,02:16.3,3,179,136300,11:59.3,27.36857143,719300,4 +1072,2420,02:09.7,3,179,129700,12:04.5,27.51428571,724500,4 +1073,2440,02:14.4,3,179,134400,12:09.8,27.82857143,729800,4 +1074,2460,02:13.6,3,179,133600,12:15.2,27.65714286,735200,4 +1075,2480,02:28.5,3,178.9142857,148500,12:21.1,28.05142857,741099.9999,4 +1076,2500,02:25.7,3,179.3428571,145700,12:26.9,28.2,746900.0001,4 +1077,2520,02:18.7,3,179.4857143,138700,12:32.5,27.49142857,752500,4 +1078,2540,02:30.8,3,179.4285714,150800,12:38.5,26.26285714,758500,4 +1079,2560,02:25.7,3,178.5714286,145700,12:44.4,25.65428571,764400.0001,4 +1080,2580,02:35.9,3,178.6,155900,12:50.6,25.76,770599.9999,4 +1081,2600,02:29.2,3,178.4,149200,12:56.6,25.66857143,776599.9999,4 +1082,2620,02:26.5,3,178.3428571,146500,13:02.4,25.59142857,782400.0001,4 +1083,2640,02:24.9,3,177.9142857,144900,13:08.2,25.26,788200,4 +1084,2660,02:30.0,3,178,150000,13:14.2,25.70571429,794200,4 +1085,2680,02:25.3,3,178,145300,13:20.0,26.26571429,800000,4 +1086,2700,02:22.6,3,178,142600,13:25.7,26.32,805700,4 +1087,2720,02:32.0,3,178,152000,13:31.8,25.91714286,811800,4 +1088,2740,02:26.1,3,178,146100,13:37.6,25.96857143,817599.9999,4 +1089,2760,02:29.2,3,178,149200,13:43.6,26.02,823599.9999,4 +1090,2780,02:23.4,3,178.0857143,143400,13:49.4,26.26571429,829400.0001,4 +1091,2800,02:26.5,3,177.6571429,146500,13:55.2,26.35142857,835200,4 +1092,2820,02:19.1,3,177.5142857,139100,14:00.8,26.14857143,840800,4 +1093,2840,02:25.7,3,177.6571429,145700,14:06.6,26.26857143,846599.9999,4 +1094,2860,02:18.7,3,178.0857143,138700,14:12.1,27.1,852099.9999,4 +1095,2880,02:19.5,3,178,139500,14:17.7,28.33142857,857700,4 +1096,2900,02:28.8,3,178,148800,14:23.7,28.55714286,863700,4 +1097,2920,02:32.4,3,178,152400,14:29.8,28.26571429,869800,4 +1098,2940,02:21.0,3,178,141000,14:35.4,27.36,875400.0001,4 +1099,2960,02:23.0,3,178,143000,14:41.1,27.18571429,881099.9999,4 +1100,2980,02:30.8,3,177.9142857,150800,14:47.2,27.18285714,887200,4 +1101,3000,02:27.7,3,178.3428571,147700,14:53.1,27.18571429,893099.9999,4 +1102,3020,02:25.7,3,178.4,145700,14:58.9,26.68285714,898900.0001,4 +1103,3040,02:23.0,3,178.6857143,143000,15:04.6,26.50285714,904599.9999,4 +1104,3060,02:23.8,3,178.4,143800,15:10.4,26.31142857,910400.0001,4 +1105,3080,02:17.1,3,178.3428571,137100,15:15.9,26.28,915900.0001,4 +1106,3100,02:23.8,3,177.9142857,143800,15:21.6,26.49142857,921599.9999,4 +1107,3120,02:17.1,3,178,137100,15:27.1,26.78857143,927099.9999,4 +1108,3140,02:21.4,3,178,141400,15:32.7,26.59142857,932700,4 +1109,3160,02:19.5,3,178,139500,15:38.3,26.32857143,938300,4 +1110,3180,02:24.2,3,178,144200,15:44.1,26.28,944099.9999,4 +1111,3200,02:17.9,3,177.9142857,137900,15:49.6,26.52857143,949599.9999,4 +1112,3220,02:23.0,3,178.3428571,143000,15:55.3,26.70571429,955300,4 +1113,3240,02:23.8,3,178.4857143,143800,16:01.1,26.63142857,961099.9999,4 +1114,3260,02:31.6,3,178.4285714,151600,16:07.1,26.42857143,967099.9999,4 +1115,3280,02:28.8,3,177.6571429,148800,16:13.1,26.63428571,973099.9999,4 +1116,3300,02:23.4,3,177.2571429,143400,16:18.8,26.91142857,978800,4 +1117,3320,02:29.6,3,176.8285714,149600,16:24.8,27.17428571,984800,4 +1118,3340,02:19.9,3,177.2571429,139900,16:30.4,26.91428571,990400.0001,4 +1119,3360,02:19.1,3,177.7428571,139100,16:36.0,26.72571429,996000,4 +1120,3380,02:20.2,3,178.0857143,140200,16:41.6,26.74857143,1001600,4 +1121,3400,02:22.6,3,177.9142857,142600,16:47.3,27.23142857,1007300,4 +1122,3420,02:24.5,3,178.3428571,144500,16:53.1,27.3,1013100,4 +1123,3440,02:19.5,3,178.4857143,139500,16:58.6,27,1018600,4 +1124,3460,02:25.7,3,178.3428571,145700,17:04.5,26.54,1024500,4 +1125,3480,02:13.6,3,177.9142857,133600,17:09.8,26.55714286,1029800,4 +1126,3500,02:18.3,3,178,138300,17:15.3,26.65714286,1035300,4 +1127,3520,02:16.0,3,178,136000,17:20.8,26.85714286,1040800,4 +1128,3540,02:16.0,3,178,136000,17:26.2,26.88,1046200,4 +1129,3560,02:22.6,3,178,142600,17:31.9,27.08285714,1051900,4 +1130,3580,02:21.8,3,177.9142857,141800,17:37.6,27.36285714,1057600,4 +1131,3600,02:17.1,3,178.2571429,137100,17:43.1,27.56,1063100,4 +1132,3620,02:20.2,3,178.7428571,140200,17:48.7,27.68,1068700,4 +1133,3640,02:16.3,3,179.0857143,136300,17:54.1,27.63142857,1074100,4 +1134,3660,02:20.6,3,179,140600,17:59.8,27.75142857,1079800,4 +1135,3680,02:17.9,3,179,137900,18:05.3,27.38571429,1085300,4 +1136,3700,02:21.0,3,179,141000,18:10.9,27.30285714,1090900,4 +1137,3720,02:16.3,3,179,136300,18:16.4,27.20571429,1096400,4 +1138,3740,02:26.9,3,179,146900,18:22.2,27.24,1102200,4 +1139,3760,02:32.4,3,179,152400,18:28.3,26.96571429,1108300,4 +1140,3780,02:27.7,3,179,147700,18:34.2,26.4,1114200,4 +1141,3800,02:33.5,3,178.9142857,153500,18:40.4,26.11428571,1120400,4 +1142,3820,02:22.2,3,179.2571429,142200,18:46.1,26.40857143,1126100,4 +1143,3840,02:22.2,3,179.7428571,142200,18:51.8,26.98285714,1131800,4 +1144,3860,02:30.4,3,180.1714286,150400,18:57.8,27.06285714,1137800,4 +1145,3880,02:22.6,3,179.7428571,142600,19:03.5,26.66571429,1143500,4 +1146,3900,02:33.5,3,179.2571429,153500,19:09.6,26.30857143,1149600,4 +1147,3920,02:29.2,3,178.8285714,149200,19:15.6,26.57714286,1155600,4 +1148,3940,02:24.5,3,179.2571429,144500,19:21.4,27.16571429,1161400,4 +1149,3960,02:23.4,3,179.7428571,143400,19:27.1,27.26285714,1167100,4 +1150,3980,02:17.5,3,180.0857143,137500,19:32.6,27.38571429,1172600,4 +1151,4000,02:18.7,3,179.9142857,138700,19:38.2,28.15714286,1178200,4 +1152,4020,02:21.4,3,180.2571429,141400,19:43.8,28.81428571,1183800,4 +1153,4040,02:18.7,3,180.7428571,138700,19:49.4,29.13714286,1189400,4 +1154,4060,02:23.0,3,181.0857143,143000,19:55.1,28.86857143,1195100,4 +1155,4080,02:19.5,3,181,139500,20:00.7,28.32857143,1200700,4 +1156,4100,02:12.0,3,181,132000,20:05.9,28.18857143,1205900,4 +1157,4120,02:14.4,3,181,134400,20:11.3,28.54571429,1211300,4 +1158,4140,02:10.1,3,181,130100,20:16.5,27.95714286,1216500,4 +1159,4160,02:17.9,3,181,137900,20:22.0,27.20857143,1222000,4 +1160,4180,02:10.9,3,180.9142857,130900,20:27.3,27.03142857,1227300,4 +1161,4200,02:16.7,3,182.2,136700,20:32.7,27.56285714,1232700,4 +1162,4220,02:15.2,3,177.9714286,135200,20:38.1,27.39428571,1238100,4 +1163,4240,02:23.4,3,176.7428571,143400,20:43.9,27.29714286,1243900,4 +1164,4260,02:14.0,3,178.2285714,134000,20:49.2,27.35714286,1249200,4 +1165,4280,02:20.6,3,182.9428571,140600,20:54.9,27.64,1254900,4 +1166,4300,02:16.0,3,182,136000,21:00.3,27.76857143,1260300,4 +1167,4320,02:19.1,3,182,139100,21:05.9,27.76571429,1265900,4 +1168,4340,02:16.0,3,182,136000,21:11.3,27.46285714,1271300,4 +1169,4360,02:18.3,3,182,138300,21:16.8,27.41714286,1276800,4 +1170,4380,02:12.0,3,182,132000,21:22.1,27.64285714,1282100,4 +1171,4400,02:17.5,3,182,137500,21:27.6,28.02857143,1287600,4 +1172,4420,02:12.8,3,182,132800,21:32.9,27.86285714,1292900,4 +1173,4440,02:19.5,3,182,139500,21:38.5,27.75428571,1298500,4 +1174,4460,02:17.9,3,182,137900,21:44.0,27.56285714,1304000,4 +1175,4480,02:13.6,3,182,133600,21:49.4,27.65428571,1309400,4 +1176,4500,02:17.1,3,182,137100,21:54.8,27.64571429,1314800,4 +1177,4520,02:16.3,3,181.9142857,136300,22:00.3,27.66857143,1320300,4 +1178,4540,02:20.2,3,182.2571429,140200,22:05.9,27.82,1300.0001,4 +1179,4560,02:14.4,3,182.7428571,134400,22:11.3,27.80857143,1331300,4 +1180,4580,02:18.7,3,183.0857143,138700,22:16.8,27.68285714,1336800,4 +1181,4600,02:12.4,3,183,132400,22:22.1,27.39428571,1342100,4 +1182,4620,02:19.1,3,183,139100,22:27.7,27.61428571,1347700,4 +1183,4640,02:11.7,3,183,131700,22:32.9,27.66,1352900,4 +1184,4660,02:15.2,3,183,135200,22:38.4,27.98285714,1358400,4 +1185,4680,02:10.9,3,183,130900,22:43.6,27.84,1363600,4 +1186,4700,02:12.8,3,182.9142857,132800,22:48.9,27.81714286,1368900,4 +1187,4720,02:13.6,3,183.2571429,133600,22:54.2,27.81428571,1374200,4 +1188,4740,02:13.6,3,183.7428571,133600,22:59.6,27.78571429,1379600,4 +1189,4760,02:18.7,3,184.0857143,138700,23:05.1,27.76,1385100,4 +1190,4780,02:18.3,3,184,138300,23:10.7,27.95142857,1390700,4 +1191,4800,02:07.7,3,184,127700,23:15.8,28.25714286,1395800,4 +1192,4820,02:11.3,3,184,131300,23:21.0,28.85142857,1401000,4 +1193,4840,02:09.3,3,183.9142857,129300,23:26.2,29.72285714,1406200,4 +1194,4860,02:09.3,3,184.2571429,129300,23:31.4,30.53142857,1411400,4 +1195,4880,02:03.1,3,184.8285714,123100,23:36.3,31.17142857,1416300,4 +1196,4900,02:12.8,3,185.1714286,132800,23:41.6,28.64857143,1421600,4 +1197,4920,03:32.5,3,183.5714286,212500,23:50.1,23.55428571,1430100,4 +1198,4940,04:06.5,3,181.4571429,246500,24:00.0,17.26571429,1440000,4 +1199,4960,04:53.0,3,172.3142857,293000,24:11.7,14.90285714,1451700,4 +1201,5000,03:50.9,3,152.7714286,230900,24:33.6,18.27714286,1473600,4 +1202,5020,03:38.8,3,150.2857143,218800,24:42.3,20.19142857,1482300,4 +1203,5040,02:58.5,3,146.8,178500,24:49.5,18.47142857,1489500,4 +1204,5060,03:29.0,3,146.4571429,209000,24:57.8,18.4,1497800,4 +1205,5080,02:51.1,3,145.5428571,171100,25:04.7,17.55714286,1504700,4 +1206,5100,03:15.7,3,144.6,195700,25:12.5,19.71714286,1512500,4 +1207,5120,02:49.2,3,143.3428571,169200,25:19.3,20.26571429,1519300,4 +1208,5140,02:45.2,3,143.4857143,165200,25:25.9,21.81714286,1525900,4 +1209,5160,03:00.5,3,143.1714286,180500,25:33.1,21.63714286,1533100,4 +1210,5180,02:47.2,3,141.9142857,167200,25:39.8,21.34,1539800,4 +1211,5200,02:57.7,3,141.1714286,177700,25:46.9,21.07714286,1546900,4 +1212,5220,02:53.5,3,141.3428571,173500,25:53.8,21.40285714,1553800,4 +1213,5240,03:00.9,3,139.5428571,180900,26:01.1,20.84571429,1561100,4 +1215,5280,04:33.1,3,136.4571429,273100,26:25.6,21.45714286,1585600,4 +1216,5300,03:21.6,3,135.3428571,201600,26:33.7,20.42857143,1593700,4 +1217,5320,03:02.0,3,133.3428571,182000,26:41.0,18.96857143,1601000,4 +1218,5340,02:43.7,3,134.0857143,163700,26:47.5,20.21428571,1607500,4 +1219,5360,02:39.0,3,135.5714286,159000,26:53.9,20.88857143,1613900,4 +1220,5380,02:36.3,3,136.0857143,156300,27:00.1,20.68285714,1620100,4 +1221,5400,02:37.8,3,136.2571429,157800,27:06.4,20.77142857,1626400,4 +1222,5420,02:33.1,3,136.6571429,153100,27:12.6,20.93714286,1639.9999,4 +1223,5440,02:36.7,3,137.2571429,156700,27:18.8,20.66,1638800,4 +1224,5460,02:44.9,3,138,164900,27:25.4,20.41714286,1645400,4 +1225,5480,02:42.1,3,138.7428571,162100,27:31.9,20.78,1651900,4 +1226,5500,02:43.7,3,139.1714286,163700,27:38.5,21.37714286,1658500,4 +1227,5520,02:36.7,3,140.1714286,156700,27:44.7,20.03142857,1664700,4 +1228,5540,02:49.5,3,141.8285714,169500,27:51.5,19.53142857,1671500,4 +1229,5560,02:52.7,3,142.9142857,172700,27:58.4,19.91142857,1678400,4 +1230,5580,02:44.1,3,143.0857143,164100,28:05.0,21.20571429,1685000,4 +1231,5600,02:44.5,3,143,164500,28:11.5,20.60857143,1691500,4 +1232,5620,02:53.1,3,143.0857143,173100,28:18.5,20.82,1698500,4 +1233,5640,02:40.6,3,142.8285714,160600,28:24.9,20.61714286,1704900,4 +1234,5660,03:00.1,3,142.0857143,180100,28:32.1,19.02285714,1712100,4 +1235,5680,03:15.3,3,141,195300,28:39.9,17.61714286,1719900,4 +1236,5700,03:25.5,3,140.0857143,205500,28:48.1,18.15714286,1728100,4 +1237,5720,03:13.0,3,138.7428571,193000,28:55.8,19.87142857,1735800,4 +1238,5740,03:05.2,3,137.2571429,185200,29:03.2,19.95142857,1743200,4 +1239,5760,02:55.0,3,135.8285714,175000,29:10.2,19.34,1750200,4 +1240,5780,03:13.8,3,135.1714286,193800,29:18.0,19.10857143,1758000,4 +1241,5800,03:05.2,3,135,185200,29:25.4,19.75428571,1765400,4 +1242,5820,02:47.6,3,134.7428571,167600,29:32.1,19.80857143,1772100,4 +1243,5840,02:57.7,3,134.1714286,177700,29:39.2,19.02285714,1779200,4 +1244,5860,03:04.8,3,134.2571429,184800,29:46.6,17.70571429,1786600,4 +1245,5880,03:01.7,3,134.4857143,181700,29:53.9,16.57714286,1793900,4 +1246,5900,03:25.5,3,134.1714286,205500,30:02.1,17.24857143,1802100,4 +1247,5920,02:58.9,3,134.4285714,178900,30:09.2,17.98857143,1809200,4 +1248,5940,02:35.1,3,135.4857143,155100,30:15.5,19.07714286,1815500,4 +1249,5960,02:29.6,3,136.0857143,149600,30:21.4,17.96285714,1821400,4 +1250,5980,02:36.7,3,136.2571429,156700,30:27.7,18.49714286,1827700,4 +1251,6000,03:03.6,3,136.7428571,183600,30:35.0,15.02857143,1835000,4 +1252,6020,03:22.7,3,137.1714286,202700,30:43.2,13.74285714,1843200,4 +1253,6040,03:20.4,3,136.7428571,200400,30:51.2,15.00571429,1851200,4 +1254,6060,02:53.8,3,136.1714286,173800,30:58.1,19.22285714,1858100,4 +1255,6080,02:38.2,3,136,158200,31:04.5,20.82,1864500,4 +1256,6100,02:30.0,3,137.1714286,150000,31:10.5,20.95428571,1870500,4 +1257,6120,02:29.6,3,138.6571429,149600,31:16.4,21.24857143,1876400,4 +1258,6140,02:28.5,3,140.3428571,148500,31:22.4,21.18857143,1882400,4 +1259,6160,02:27.3,3,141.9142857,147300,31:28.3,21.90857143,1888300,4 +1260,6180,02:41.3,3,142.5714286,161300,31:34.7,17.56571429,1894700,4 +1261,6200,03:59.9,3,142.6,239900,31:44.3,15.94,1904300,4 +1262,6220,03:55.2,3,142.7428571,235200,31:53.7,17.42285714,1913700,4 +1263,6240,02:41.7,3,142.8285714,161700,32:00.2,22.17142857,1920200,4 +1264,6260,02:26.9,3,143.6285714,146900,32:06.1,22.28571429,1926100,4 +1265,6280,03:09.1,3,138.0571429,189100,32:13.6,19.39714286,1933600,4 +1267,6320,04:54.2,3,122.2285714,294200,32:51.5,14.22,1971500,4 +1268,6340,04:40.1,3,123.2571429,280100,33:02.7,16.01428571,1982700,4 +1269,6360,03:45.4,3,124.2285714,225400,33:11.7,16.48,1991700,4 +1270,6380,03:25.9,3,125.8571429,205900,33:19.9,16.66571429,1999900,4 +1271,6400,03:41.5,3,127.6571429,221500,33:28.8,16.66285714,2008800,4 +1272,6420,03:34.5,3,128.4,214500,33:37.3,17.29142857,2017300,4 +1273,6440,03:30.2,3,127.6857143,210200,33:45.8,16.38285714,2025800,4 +1274,6460,03:04.8,3,128,184800,33:53.1,16.24,2033100,4 +1275,6480,02:45.2,3,130,165200,33:59.8,17.13142857,2039800,4 +1276,6500,04:58.8,3,130.7428571,298800,34:11.7,17.76857143,2051700,4 +1277,6520,04:37.0,3,128.6571429,277000,34:22.8,17.44857143,2062800,4 +1278,6540,04:17.0,3,125.6,257000,34:33.1,15.90571429,2073100,4 +1279,6560,03:42.3,3,123.6571429,222300,34:42.0,17.48,2082000,4 +1280,6580,03:22.4,3,124.4285714,202400,34:50.0,19.24285714,2090000,4 +1281,6600,02:48.4,3,126.8285714,168400,34:56.8,20.73428571,2096800,4 +1282,6620,02:51.5,3,129.7428571,171500,35:03.6,21.06,2103600,4 +1283,6640,02:35.9,3,132.6857143,155900,35:09.9,24.12,2109900,4 +1284,6660,02:42.5,3,133.7142857,162500,35:16.4,15.77428571,2116400,4 +1286,6700,04:07.3,3,134.2285714,247300,35:34.6,11.19142857,2134600,4 +1287,6720,03:03.6,3,134.0857143,183600,35:42.0,20.16,2142000,4 +1288,6740,03:04.8,3,131.8285714,184800,35:49.4,19.37714286,2149400,4 +1289,6760,03:04.8,3,130.7714286,184800,35:56.8,18.00571429,2156800,4 +1290,6780,03:08.7,3,130.0571429,188700,36:04.3,17.85428571,2164300,4 +1291,6800,03:06.0,3,129.5142857,186000,36:11.7,18.40571429,2171700,4 +1292,6820,03:01.7,3,129.0857143,181700,36:19.0,19.38285714,2179000,4 +1293,6840,02:51.5,3,129.7428571,171500,36:25.9,18.68571429,2185900,4 +1294,6860,02:54.2,3,130.1714286,174200,36:32.8,18.47142857,2192800,4 +1295,6880,02:55.0,3,129.7428571,175000,36:39.8,18.82285714,2199800,4 +1296,6900,03:43.8,3,129.1714286,223800,36:48.8,17.32285714,2208800,4 +1297,6920,03:35.6,3,129.3428571,215600,36:57.4,16.45428571,2217400,4 +1298,6940,03:09.9,3,129.3142857,189900,37:05.0,16.78571429,2225000,4 +1299,6960,03:14.2,3,128.2571429,194200,37:12.8,18.57428571,2232800,4 +1300,6980,03:18.8,3,127.3428571,198800,37:20.7,18.82,2240700,4 +1301,7000,03:27.4,3,127.7428571,207400,37:29.0,18.33428571,2249000,4 +1302,7020,03:06.0,3,127.9142857,186000,37:36.5,16.97142857,2256500,4 +1303,7040,03:07.5,3,127,187500,37:44.0,17.31428571,2264000,4 +1304,7060,03:05.2,3,126.0857143,185200,37:51.4,15.52857143,2271400,4 +1305,7080,03:42.7,3,126.1714286,222700,38:00.3,15.28285714,2280300,4 +1306,7100,03:29.4,3,126.8285714,209400,38:08.6,16.79714286,2288600,4 +1307,7120,03:10.2,3,126.5714286,190200,38:16.3,18.70571429,2296300,4 +1308,7140,03:19.2,3,126.9428571,199200,38:24.2,17.78285714,2304200,4 +1309,7160,02:56.2,3,128.4857143,176200,38:31.3,18.33142857,2311300,4 +1310,7180,02:53.8,3,129.7428571,173800,38:38.2,20.31714286,2318200,4 +1311,7200,02:55.8,3,129.1714286,175800,38:45.3,20.25714286,2325300,4 +1312,7220,02:43.7,3,129.3428571,163700,38:51.8,20.09714286,2331800,4 +1313,7240,02:42.9,3,130.6571429,162900,38:58.3,20.16571429,2338300,4 +1314,7260,02:39.4,3,132.1714286,159400,39:04.7,20.67142857,2344700,4 +1315,7280,02:35.9,3,132.5714286,155900,39:10.9,21.14857143,2350900,4 +1316,7300,02:41.3,3,133.6857143,161300,39:17.4,20.89142857,2357400,4 +1317,7320,02:35.9,3,135.6571429,155900,39:23.6,20.22285714,2363600,4 +1318,7340,02:37.8,3,137.9142857,157800,39:29.9,20.23428571,2369900,4 +1319,7360,02:37.0,3,139.0857143,157000,39:36.2,20.97142857,2376200,4 +1320,7380,02:36.7,3,140,156700,39:42.5,20.93714286,2382500,4 +1321,7400,02:35.1,3,141.1714286,155100,39:48.7,20.72571429,2388700,4 +1322,7420,02:43.3,3,141.5714286,163300,39:55.2,19.34571429,2395200,4 +1323,7440,02:59.3,3,141.3428571,179300,40:02.4,19.09714286,2402400,4 +1324,7460,03:03.6,3,140.9142857,183600,40:09.7,19.59142857,2409700,4 +1325,7480,02:40.6,3,140.9142857,160600,40:16.1,21.23142857,2416100,4 +1326,7500,02:48.8,3,141.2571429,168800,40:22.9,21.16571429,2422900,4 +1327,7520,02:39.0,3,141.8285714,159000,40:29.3,21.35428571,2429300,4 +1328,7540,02:33.9,3,141.9142857,153900,40:35.4,21.19142857,2435400,4 +1329,7560,02:47.6,3,141.0857143,167600,40:42.1,20.27428571,2442100,4 +1330,7580,03:02.0,3,140.1714286,182000,40:49.4,19.01714286,2449400,4 +1331,7600,03:09.5,3,138.4857143,189500,40:57.0,16.88,2457000,4 +1332,7620,03:34.9,3,136.6,214900,41:05.6,14.68,2465600,4 +1333,7640,03:27.4,3,134.5714286,207400,41:13.9,15.78285714,2473900,4 +1334,7660,03:04.8,3,133.3428571,184800,41:21.3,18.14857143,2481300,4 +1335,7680,03:11.8,3,131.8285714,191800,41:28.9,18.93428571,2488900,4 +1336,7700,03:24.3,3,129.8285714,204300,41:37.1,20.09714286,2497100,4 +1337,7720,03:25.9,3,127.2571429,205900,41:45.3,22.05428571,2505300,4 +1338,7740,03:39.2,3,124.7428571,219200,41:54.1,20.40571429,2514100,4 +1339,7760,04:09.6,3,123.3428571,249600,42:04.1,17.76,2524100,4 +1340,7780,03:13.8,3,122.8285714,193800,42:11.8,17.50857143,2531800,4 +1341,7800,03:03.2,3,122.7428571,183200,42:19.2,18.88571429,2539200,4 +1342,7820,02:44.5,3,123.6857143,164500,42:25.7,19.37142857,2545700,4 +1343,7840,02:35.5,3,125.5714286,155500,42:32.0,19.36,2552000,4 +1344,7860,02:46.4,3,126.6571429,166400,42:38.6,18.94571429,2558600,4 +1345,7880,02:53.1,3,126.5142857,173100,42:45.5,18.05714286,2565500,4 +1346,7900,02:58.5,3,127,178500,42:52.7,18.42571429,2572700,4 +1347,7920,02:50.7,3,127.5714286,170700,42:59.5,19.13428571,2579500,4 +1348,7940,03:16.1,3,127.4285714,196100,43:07.3,18.88857143,2587300,4 +1349,7960,03:12.6,3,126.6571429,192600,43:15.0,17.72285714,2595000,4 +1350,7980,03:09.9,3,127.4571429,189900,43:22.6,17.56571429,2602600,4 +1351,8000,03:21.2,3,120.9428571,201200,43:30.7,17.82571429,2610700,4 +1352,8020,03:07.1,3,119.8,187100,43:38.2,17.67142857,2618200,4 +1353,8040,02:55.0,3,122.6,175000,43:45.2,17.52571429,2625200,4 +1354,8060,03:00.5,3,128.0285714,180500,43:52.4,19.36571429,2632400,4 +1356,8100,03:02.8,3,125.4,182800,44:11.9,19.29714286,2651900,4 +1357,8120,02:57.0,3,125,177000,44:19.0,18.31428571,2659000,4 +1358,8140,03:05.6,3,124.5142857,185600,44:26.4,18.44285714,2666400,4 +1359,8160,03:12.6,3,124.5714286,192600,44:34.1,18.39142857,2674100,4 +1360,8180,03:02.0,3,123.8285714,182000,44:41.4,15.79714286,2681400,4 +1361,8200,03:57.5,3,122.3428571,237500,44:50.9,15.76,2690900,4 +1362,8220,03:24.3,3,122.0857143,204300,44:59.1,17.60571429,2699100,4 +1363,8240,03:09.9,3,122.5714286,189900,45:06.7,19.90857143,2706700,4 +1364,8260,02:55.4,3,123.3428571,175400,45:13.7,19.60857143,2713700,4 +1365,8280,02:48.8,3,125.1714286,168800,45:20.5,20.53428571,2720500,4 +1366,8300,02:45.6,3,127.5714286,165600,45:27.1,21.03714286,2727100,4 +1367,8320,02:48.8,3,129.0857143,168800,45:33.8,20.94,2733800,4 +1368,8340,02:45.2,3,130.3428571,165200,45:40.4,20.74285714,2740400,4 +1369,8360,02:44.5,3,131.4857143,164500,45:47.0,21.22285714,2747000,4 +1370,8380,02:44.1,3,132.4285714,164100,45:53.6,20.41428571,2753600,4 +1371,8400,02:46.8,3,132.5714286,166800,46:00.3,20.10857143,2760300,4 +1372,8420,02:39.4,3,133.6857143,159400,46:06.6,20.84,2766600,4 +1373,8440,02:49.9,3,134.2285714,169900,46:13.4,19.14857143,2773400,4 +1374,8460,03:00.9,3,134.4285714,180900,46:20.7,18.04285714,2780700,4 +1375,8480,02:56.6,3,134.0857143,176600,46:27.7,17.96285714,2787700,4 +1376,8500,02:55.0,3,133.4857143,175000,46:34.7,19.39428571,2794700,4 +1377,8520,02:56.2,3,132.5142857,176200,46:41.8,19.5,2801800,4 +1378,8540,02:53.8,3,131.7428571,173800,46:48.7,19.76285714,2808700,4 +1379,8560,02:46.4,3,132.4285714,166400,46:55.4,19.37714286,2815400,4 +1380,8580,02:42.5,3,132.3142857,162500,47:01.9,19.22571429,2821900,4 +1381,8600,02:57.0,3,131.3428571,177000,47:09.0,19.37428571,2829000,4 +1382,8620,03:09.9,3,130,189900,47:16.5,19.66571429,2836500,4 +1383,8640,02:49.9,3,130.3428571,169900,47:23.3,18.85714286,2843300,4 +1384,8660,02:46.4,3,130.4,166400,47:30.0,19.05714286,2850000,4 +1385,8680,02:50.3,3,129.0857143,170300,47:36.8,17.12285714,2856800,4 +1386,8700,02:58.1,3,127.4285714,178100,47:43.9,17.06571429,2863900,4 +1387,8720,03:07.9,3,126.4857143,187900,47:51.5,17.68,2871500,4 +1388,8740,02:58.1,3,126.4285714,178100,47:58.6,20.31428571,2878600,4 +1389,8760,02:55.4,3,127,175400,48:05.6,18.96857143,2885600,4 +1390,8780,03:12.6,3,127.4857143,192600,48:13.3,18.59714286,2893300,4 +1391,8800,03:05.2,3,127.2571429,185200,48:20.7,19.44,2900700,4 +1392,8820,02:58.9,3,128.8571429,178900,48:27.9,21.48857143,2907900,4 +1393,8840,02:45.6,3,130.6285714,165600,48:34.5,18.81714286,2914500,4 +1394,8860,03:02.4,3,130.7714286,182400,48:41.8,16.06,2921800,4 +1395,8880,03:28.6,3,128.5714286,208600,48:50.1,15.00857143,2930100,4 +1396,8900,03:20.8,3,127.4285714,200800,48:58.2,17.34571429,2938200,4 +1397,8920,02:52.7,3,126.8285714,172700,49:05.1,18.52571429,2945100,4 +1398,8940,02:50.3,3,127,170300,49:11.9,19.74857143,2951900,4 +1399,8960,02:54.6,3,127,174600,49:18.9,20.26571429,2958900,4 +1400,8980,02:47.6,3,126.8285714,167600,49:25.6,20.20571429,2965600,4 +1401,9000,02:43.7,3,127.2571429,163700,49:32.1,19.37142857,2972100,4 +1402,9020,02:46.0,3,129.0857143,166000,49:38.8,19.47142857,2978800,4 +1403,9040,02:57.0,3,131.8285714,177000,49:45.8,20.43714286,2985800,4 +1404,9060,02:35.5,3,133.8285714,155500,49:52.1,20.92857143,2992100,4 +1405,9080,02:28.8,3,135.3428571,148800,49:58.0,20.89714286,2998000,4 +1406,9100,02:30.4,3,136.7428571,150400,50:04.0,21.40285714,3004000,4 +1407,9120,02:26.5,3,138.0857143,146500,50:09.9,22.31142857,3009900,4 +1408,9140,02:26.9,3,138.9142857,146900,50:15.8,22.7,3015800,4 +1409,9160,02:36.7,3,140.2571429,156700,50:22.0,22.59428571,3022000,4 +1410,9180,02:30.0,3,141.7428571,150000,50:28.0,22.43142857,3028000,4 +1411,9200,02:29.2,3,143.0857143,149200,50:34.0,22.20857143,3034000,4 +1412,9220,02:27.3,3,144.2571429,147300,50:39.9,21.71142857,3039900,4 +1413,9240,02:35.5,3,146.0285714,155500,50:46.1,23.12857143,3046100,4 +1414,9260,03:08.3,3,138.9714286,188300,50:53.6,22.98857143,3053600,4 +1415,9280,04:01.4,3,126.3428571,241400,51:03.3,13.11142857,3063300,4 +1417,9320,03:36.4,3,117.5714286,216400,51:25.0,11.70571429,3085000,4 +1418,9340,03:51.3,3,119.9142857,231300,51:34.3,19.73714286,3094300,4 +1419,9360,03:22.0,3,122.0857143,202000,51:42.3,18.46857143,3102300,4 +1420,9380,03:16.1,3,125.7142857,196100,51:50.2,15.80285714,3110200,4 +1421,9400,03:25.9,3,118.5714286,205900,51:58.4,16.25428571,3118400,4 +1423,9440,03:14.2,3,110.0285714,194200,52:23.5,20.32285714,3143500,4 +1424,9460,02:58.9,3,118.1428571,178900,52:30.7,19.28285714,3150700,4 +1425,9480,02:50.3,3,122.3142857,170300,52:37.5,17.68,3157500,4 +1426,9500,04:10.0,3,127.4571429,250000,52:47.5,17.38,3167500,4 +1427,9520,03:45.0,3,126.8857143,225000,52:56.5,16.28,3176500,4 diff --git a/rowers/utils.py b/rowers/utils.py index 6ef5e013..26c13c12 100644 --- a/rowers/utils.py +++ b/rowers/utils.py @@ -1244,7 +1244,7 @@ def get_timezone_from_c2data(data): timezone = pytz.timezone(data['timezone']) except UnknownTimeZoneError: timezone = pytz.utc - except KeyError: + except KeyError: # pragma: no cover timezone = pytz.utc return timezone diff --git a/rowers/views/importviews.py b/rowers/views/importviews.py index 7fd0d483..5e4e77f1 100644 --- a/rowers/views/importviews.py +++ b/rowers/views/importviews.py @@ -1755,7 +1755,7 @@ def workout_getimportview(request,externalid,source = 'c2',do_async=True): if result: # pragma: no cover messages.info(request,"Your workout will be imported in the background") # this should return to the respective import list page - else: + else: # pragma: no cover messages.error(request,'Error getting the workout') url = reverse(importlistviews[source]) diff --git a/rowers/views/statements.py b/rowers/views/statements.py index db7dc791..5d9daa8d 100644 --- a/rowers/views/statements.py +++ b/rowers/views/statements.py @@ -1273,166 +1273,6 @@ def sendmail(request): return HttpResponseRedirect('/rowers/email/') -# Create workout data from Strava or Concept2 -# data and create the associated Workout object and save it -def add_workout_from_strokedata(user,importid,data,strokedata, - source='c2',splitdata=None, - workoutsource='concept2'): - try: - workouttype = data['type'] - except KeyError: # pragma: no cover - workouttype = 'rower' - - if workouttype not in [x[0] for x in Workout.workouttypes]: # pragma: no cover - workouttype = 'other' - try: - comments = data['comments'] - except: # pragma: no cover - comments = ' ' - -# comments = "Imported data \n %s" % comments -# comments = "Imported data \n"+comments # str(comments) - try: - thetimezone = tz(data['timezone']) - except: # pragma: no cover - thetimezone = 'UTC' - - r = getrower(user) - try: - rowdatetime = iso8601.parse_date(data['date_utc']) - except KeyError: # pragma: no cover - rowdatetime = iso8601.parse_date(data['start_date']) - except ParseError: # pragma: no cover - rowdatetime = iso8601.parse_date(data['date']) - - - try: - c2intervaltype = data['workout_type'] - - except KeyError: # pragma: no cover - c2intervaltype = '' - - try: - title = data['name'] - except KeyError: # pragma: no cover - title = "" - try: - t = data['comments'].split('\n', 1)[0] - title += t[:20] - except: - title = '' - - starttimeunix = arrow.get(rowdatetime).timestamp() - - res = make_cumvalues(0.1*strokedata['t']) - cum_time = res[0] - lapidx = res[1] - - unixtime = cum_time+starttimeunix - # unixtime[0] = starttimeunix - seconds = 0.1*strokedata.loc[:,'t'] - - nr_rows = len(unixtime) - - try: # pragma: no cover - latcoord = strokedata.loc[:,'lat'] - loncoord = strokedata.loc[:,'lon'] - except: - latcoord = np.zeros(nr_rows) - loncoord = np.zeros(nr_rows) - - - try: - strokelength = strokedata.loc[:,'strokelength'] - except: - strokelength = np.zeros(nr_rows) - - dist2 = 0.1*strokedata.loc[:,'d'] - - try: - spm = strokedata.loc[:,'spm'] - except KeyError: # pragma: no cover - spm = 0*dist2 - - try: - hr = strokedata.loc[:,'hr'] - except KeyError: - hr = 0*spm - pace = strokedata.loc[:,'p']/10. - pace = np.clip(pace,0,1e4) - pace = pace.replace(0,300) - - velo = 500./pace - - power = 2.8*velo**3 - - # save csv - # Create data frame with all necessary data to write to csv - df = pd.DataFrame({'TimeStamp (sec)':unixtime, - ' Horizontal (meters)': dist2, - ' Cadence (stokes/min)':spm, - ' HRCur (bpm)':hr, - ' longitude':loncoord, - ' latitude':latcoord, - ' Stroke500mPace (sec/500m)':pace, - ' Power (watts)':power, - ' DragFactor':np.zeros(nr_rows), - ' DriveLength (meters)':np.zeros(nr_rows), - ' StrokeDistance (meters)':strokelength, - ' DriveTime (ms)':np.zeros(nr_rows), - ' StrokeRecoveryTime (ms)':np.zeros(nr_rows), - ' AverageDriveForce (lbs)':np.zeros(nr_rows), - ' PeakDriveForce (lbs)':np.zeros(nr_rows), - ' lapIdx':lapidx, - ' ElapsedTime (sec)':seconds - }) - - - df.sort_values(by='TimeStamp (sec)',ascending=True) - - timestr = strftime("%Y%m%d-%H%M%S") - - - # Create CSV file name and save data to CSV file - csvfilename ='media/{code}_{importid}.csv'.format( - importid=importid, - code = uuid4().hex[:16] - ) - - res = df.to_csv(csvfilename+'.gz',index_label='index', - compression='gzip') - - - # with Concept2 - if source=='c2': - try: - totaldist = data['distance'] - totaltime = data['time']/10. - except KeyError: # pragma: no cover - totaldist = 0 - totaltime = 0 - else: # pragma: no cover - totaldist = 0 - totaltime = 0 - - id,message = dataprep.save_workout_database( - csvfilename,r, - workouttype=workouttype, - dosmooth=r.dosmooth, - title=title,notes=comments, -# totaldist=totaldist, -# totaltime=totaltime, - workoutsource=workoutsource, - dosummary=True - ) - - - - return id,message - - - - def keyvalue_get_default(key,options,def_options): # pragma: no cover try: From f403d065a35eccce41636466e9a1f154dcc12f4d Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Fri, 21 May 2021 15:49:31 +0200 Subject: [PATCH 07/12] fixing omitted test --- rowers/tests/test_imports.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rowers/tests/test_imports.py b/rowers/tests/test_imports.py index a7ff7f6d..6b21c1db 100644 --- a/rowers/tests/test_imports.py +++ b/rowers/tests/test_imports.py @@ -361,13 +361,15 @@ class C2Objects(DjangoTestCase): timezone = str(utils.get_timezone_from_c2data(data['data'])) self.assertEqual(timezone,'UTC') - @patch('rowers.c2stuff.requests.get', side_effect=mocked_requests) + @patch('rowers.tasks.requests.get', side_effect=mocked_requests) @patch('rowers.dataprep.create_engine') def test_c2_import_tz2(self, mock_get, mocked_sqlalchemy): response = self.c.get('/rowers/workout/c2import/31/',follow=True) expected_url = '/rowers/workout/c2list/' + result = tasks.handle_c2_getworkout(self.r.user.id,self.r.c2token,31,self.r.defaulttimezone) + self.assertRedirects(response, expected_url=expected_url, status_code=302,target_status_code=200) From f3db042f8962407c8411602d8685424afbb5d246 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Fri, 21 May 2021 16:14:10 +0200 Subject: [PATCH 08/12] rdata - rdata csvfile --- rowers/tasks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rowers/tasks.py b/rowers/tasks.py index 710f77e0..1b093a48 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -3029,7 +3029,7 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone - + try: notes = data['comments'] @@ -3214,7 +3214,7 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone units = getlist(sa,sel='unit') types = getlist(sa,sel='type') - rowdata = rdata(csvfilename) + rowdata = rdata(csvfile=csvfilename) if rowdata: rowdata.updateintervaldata(values, units,types,results) From 791ed4a2bbc8ea359f910c064bddb0f8b4101c5d Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Sat, 22 May 2021 14:06:56 +0200 Subject: [PATCH 09/12] merge develop --- rowers/tasks.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/rowers/tasks.py b/rowers/tasks.py index 8d849304..c16924da 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -3030,10 +3030,6 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone duration=duration) dologging('debuglog.log',s) - - - - try: notes = data['comments'] name = notes[:40] From 5c8177f6eaf7938dd85b83093b0f843f9ecf5e49 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Sat, 22 May 2021 15:16:58 +0200 Subject: [PATCH 10/12] strava and c2 and sporttracks done --- rowers/c2stuff.py | 4 + rowers/views/importviews.py | 176 ++++-------------------------------- 2 files changed, 20 insertions(+), 160 deletions(-) diff --git a/rowers/c2stuff.py b/rowers/c2stuff.py index 58c14b07..200adba1 100644 --- a/rowers/c2stuff.py +++ b/rowers/c2stuff.py @@ -931,6 +931,7 @@ def default(o): # pragma: no cover # Uploading workout def workout_c2_upload(user,w,asynchron=False): message = 'trying C2 upload' + try: if mytypes.c2mapping[w.workouttype] is None: # pragma: no cover return "This workout type cannot be uploaded to Concept2",0 @@ -942,7 +943,9 @@ def workout_c2_upload(user,w,asynchron=False): r = Rower.objects.get(user=user) # ready to upload. Hurray + if (is_workout_user(user,w)): + c2userid = get_userid(r.c2token) if not c2userid: # pragma: no cover raise NoTokenError("User has no token") @@ -980,6 +983,7 @@ def workout_c2_upload(user,w,asynchron=False): message = "Something went wrong in workout_c2_upload_view. Response code 200/201 but C2 sync failed: "+response.text c2id = 0 else: # pragma: no cover + job = myqueue(queue, handle_c2_sync, w.id, diff --git a/rowers/views/importviews.py b/rowers/views/importviews.py index 5e4e77f1..d63a4503 100644 --- a/rowers/views/importviews.py +++ b/rowers/views/importviews.py @@ -81,113 +81,17 @@ def workout_tp_upload_view(request,id=0): def workout_strava_upload_view(request,id=0): message = "" r = getrower(request.user) - res = -1 + w = get_workout_by_opaqueid(request,id) + result = -1 + comment, result = stravastuff.workout_strava_upload(r.user,w,asynchron=True) + messages.info(request,'Your workout will be synchronized to Strava in the background') - try: - thetoken = strava_open(request.user) - except NoTokenError: # pragma: no cover - return HttpResponseRedirect("/rowers/me/stravaauthorize/") - - if (r.stravatoken == '') or (r.stravatoken is None): # pragma: no cover - s = "Token doesn't exist. Need to authorize" - return HttpResponseRedirect("/rowers/me/stravaauthorize/") - else: - # ready to upload. Hurray - w = get_workout_by_opaqueid(request,id) - r = w.user - - try: - tcxfile,tcxmessg = stravastuff.createstravaworkoutdata(w) - if tcxfile: - with open(tcxfile,'rb') as f: - try: - newnotes = w.notes+'\n from '+w.workoutsource+' via rowsandall.com' - except TypeError: - newnotes = 'from '+w.workoutsource+' via rowsandall.com' - activity_type = 'Ride' - if w.workouttype in mytypes.rowtypes: - activity_type = r.stravaexportas - if activity_type == 'match': - try: - activity_type = mytypes.stravamapping[w.workouttype] - except KeyError: # pragma: no cover - activity_type = 'Ride' - else: # pragma: no cover - try: - activity_type = mytypes.stravamapping[w.workouttype] - except KeyError: - activity_type = 'Ride' - - res,mes = stravastuff.handle_stravaexport( - f,w.name, - r.stravatoken, - description=newnotes, - activity_type=activity_type,quick=False) - if res==0: # pragma: no cover - messages.error(request,mes) - w.uploadedtostrava = -1 - w.save() - try: - os.remove(tcxfile) - except WindowsError: - pass - url = reverse(r.defaultlandingpage, - kwargs = { - 'id':encoder.encode_hex(w.id), - }) - response = HttpResponseRedirect(url) - return response - - try: - w.uploadedtostrava = res - w.save() - try: - os.remove(tcxfile) - except WindowsError: # pragma: no cover - pass - url = reverse('workout_edit_view',kwargs={'id':w.id}) - - - messages.info(request,mes) - except: # pragma: no cover - with open("media/stravaerrors.log","a") as errorlog: - errorstring = str(sys.exc_info()[0]) - timestr = strftime("%Y%m%d-%H%M%S") - errorlog.write(timestr+errorstring+"\r\n") - errorlog.write("views.py line 826\r\n") - message = 'Error: '+errorstring - messages.error(request,message) - else: # pragma: no cover # No tcxfile - message = "Strava Data error "+tcxmessg - messages.error(request,message) - w.uploadedtostrava = -1 - w.save() - url = reverse(r.defaultlandingpage, - kwargs = { - 'id':encoder.encode_hex(w.id), - }) - response = HttpResponseRedirect(url) - - - url = reverse(r.defaultlandingpage, - kwargs = { - 'id':encoder.encode_hex(w.id), - } - ) - response = HttpResponseRedirect(url) - except ActivityUploadFailed as e: # pragma: no cover - message = "Strava Upload error: %s" % e - messages.error(request,message) - w.uploadedtostrava = -1 - w.save() - os.remove(tcxfile) - url = reverse(r.defaultlandingpage, - kwargs = { - 'id':encoder.encode_hex(w.id), - }) - response = HttpResponseRedirect(url) - - return response + url = reverse(r.defaultlandingpage, + kwargs = { + 'id':encoder.encode_hex(w.id), + } + ) + return HttpResponseRedirect(url) # Upload workout to Concept2 logbook @login_required() @@ -205,15 +109,12 @@ def workout_c2_upload_view(request,id=0): dologging(s) try: - message,c2id = c2stuff.workout_c2_upload(request.user,w) + message,c2id = c2stuff.workout_c2_upload(request.user,w,asynchron=True) except NoTokenError: # pragma: no cover + print('jet') return HttpResponseRedirect("/rowers/me/c2authorize/") - if message and c2id <=0: # pragma: no cover - messages.error(request,message) - elif message: - messages.info(request,message) - + messages.info(request,'Your workout will be synchronized to the Concept2 Logbook in the background') url = reverse(r.defaultlandingpage, kwargs = { @@ -221,9 +122,8 @@ def workout_c2_upload_view(request,id=0): }) - response = HttpResponseRedirect(url) + return HttpResponseRedirect(url) - return response # Upload workout to SportTracks @@ -234,53 +134,9 @@ def workout_sporttracks_upload_view(request,id=0): w = get_workout(id) r = w.user - try: - thetoken = sporttracks_open(r.user) - except NoTokenError: # pragma: no cover - return HttpResponseRedirect("/rowers/me/sporttracksauthorize/") + message, res = sporttracksstuff.workout_sporttracks_upload(r.user,w,asynchron=True) - - - data = sporttracksstuff.createsporttracksworkoutdata(w) - - if not data: # pragma: no cover - message = "Data error" - messages.error(request,message) - url = reverse(r.defaultlandingpage, - kwargs = { - 'id':encoder.encode_hex(w.id), - }) - return HttpResponseRedirect(url) - - authorizationstring = str('Bearer ' + thetoken) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - - url = "https://api.sporttracks.mobi/api/v2/fitnessActivities.json" - response = requests.post(url,headers=headers,data=json.dumps(data,default=default)) - - - # check for duplicate error first - if (response.status_code == 409 ): # pragma: no cover - message = "Duplicate error" - messages.error(request,message) - w.uploadedtosporttracks = -1 - w.save() - elif (response.status_code == 201 or response.status_code==200): - s= response.json() - sporttracksid = sporttracksstuff.getidfromresponse(response) - w.uploadedtosporttracks = sporttracksid - w.save() - message = "Upload to SportTracks was successful" - messages.info(request,message) - - url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)}) - return HttpResponseRedirect(url) - else: # pragma: no cover - s = response - message = "Something went wrong in workout_sporttracks_upload_view: %s" % s.reason - messages.error(request,message) + messages.info(request,'Your workout will be synchronized with SportTracks in the background') url = reverse(r.defaultlandingpage, kwargs = { From 447284a5d99c99bcf66daf0f40bdeb7d85e28ed3 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Sat, 22 May 2021 17:18:11 +0200 Subject: [PATCH 11/12] no --- rowers/tests/testdata/testdata.tcx.gz | Bin 0 -> 4000 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 rowers/tests/testdata/testdata.tcx.gz diff --git a/rowers/tests/testdata/testdata.tcx.gz b/rowers/tests/testdata/testdata.tcx.gz new file mode 100644 index 0000000000000000000000000000000000000000..26c23e7e17038aff0d1836d269d35a4a58c4c27c GIT binary patch literal 4000 zcmV;R4`1*fiwFpLAE{sh|8!+@bYx+4VJ>uIcmVC4NpBoC7J%>m6@m}RVG#CP__!#t zf^35^U}u8Z$mBMtNFBLnq?XWKUh?mU?6zguRv~`U6u~Oc2SZ(5Th~{Qd^?Z6d2?}o z@M^i)t}fS)9-@JV2j3h&IC{S6R_oRJ?EB@qUv7Tr`tJ8`yF5rcueXmLzUcd_!^PtD z>(}P2+gz;H=H&8Xk-prXyjWgz+r{mNFJ95Z{V5K+H=l8qZ%_Kwt5yH!k8k?rI^W=p z6TI23J~+c`HkX^T1p(mVx2I2@?N0I4YQ62d^~o|FwOt+V&->)^r0aLT_D(l&pg-yr znK#?hzdrEqUH^S|ez{pKw~JT!*Zcp`^(XuNm)DoV&%4whpt~Nr|BVli9~>MUy?p@b zXXKCXH~e|5_haQ|ic`tj*80lKe1z9M*zd}#5IoQaM&!ruT60ge`F zr+525>8=i*_1&g_zPeaGdiYnzUSB93`uwu*&huf6ct@ ze!Tu}+4b9>mz$@n^~-+w@BYS*NT>O=JAb)6Mw>3O|MUG77PnmD#@A1~H>-=67yqXl z5O>QB+;WK&Ue*53F_9Sjc@WBIyTb}Q3hwIU6`^jaW|NPr$&jh!Q;UAwdo%3H^-zTw&M~nSmA768k zF8cA$yZsjPi*OrWEp-Nyq+P6nIPg?r}EUovny_O!98UYq-af^3E_D?!F@KmUiR3Q*gJzP(ki^5AIkM z_W%`fm&82@l}4NQ#!ZBKUGg5dBJSP<4^E@cJ6F<-W10_lUk`Ty;{#fayn8V+5$=_Z z^A*`~!X|=^8ty?#+V69c_fQdcXB-e{^tvcT_4)b8J3>W@okYW|bJHS}CC~RDPj!)} zYNmKPgk;Kz&XhxxlD-?Z^O1R$ipX0NlTxpec@h%}l9w5gj}?(m=A0l0Rd~h~wd37< z$Xizrc?9Dul1k>2@n6z&=jSue3sgj&jb#+pkT2}Ji!&lm6_Ixaoz97a&X=6$Ews^o z6!O7D5~~T%p${efclRRSM*BhXgvJqg)o35elAlk64y7Wij;s+tRB3oImbB;RMBavq z$R|CW3028g5KBhsEX`=N$BM{D6A-*rrQJ31Ga%1oT*Rm%pObS7lAn>^zNXQh#jpdf zndixtC2wa$zM_Z?2Lk|JG~@+JM(6E){Px_ex*_sOeyu}Q8Wu?`>BE~9`HFmamJK6X zO_Y{=(G2@WekAhFfK`$YFd3PzZJw_vN^67h=~YzO^AU`18s60Bc|nszUS-cSK+%ZJ zj7IyKWL~UE&lX5S9&s|deT&i#lXu1o22GTf35(kEb0S}nJ)bQ!wyJra8BLrBd2I9i z?c_P<-ZCI*JUQt_DVcR`UGv+ILS76o1eMGS6^+<5^5c;ACM1bR4SB~+=I=miR| zBtTF#$?#lM=6%!cMgB=55)m z>)2{(MGorgM=%kIHQrkX*m7^DFZ0Mo0+A+4>u@^c zxp{I1$-A6&t?Gp62#f0Wb0S~UXdewA22Fh4F%_+%_ANd?2Kk(O8!%}4-a1P~b8qKF zz9M^`tRaW2n&*WklY7gpetwX=H)xSmqrIb|_WX>2L2m7oF$lM7|>3 zK51(lQMGEB3*4f#GaxSpKvZ4MUE~&}o&IRg-iYWrA$n-!?@GQR-QI#>FDg%tM_W?E zyH_4w)9{ALbMAhs^4|Jn3C5OzIeGG8ymhFF)%m0w6pYmg&d8pxC_Zn4vB;>&$?@rJ zu@fO*n-4G4LtZe~(yG?9@KUsXeoiu9lZGd3ybx-9c;2~^e*0O?^A*|iNq#w!s>a59 z*D5OSNWP*dtwaM%pc?Iin~ZMXytf17g15oSSD3w zMnrDpryj9Mmsax;c@r$dhA(p-7;~w~yWz9qnCP zi+T+5``laIJRd?)t8Px@EAr$>ve1}7MLve2IXSM)^P`Y=CRk!klokQXhH2-7z9LtS z#GG&sL4}^6p}%AQ(`v?hmpk9Os2lGQ7>lOd-v>QZhF&T{FS%g~=mvaClR=NI-}NB+ zU<3(Cg+8fqkLvjTKb+a1p#TslOw7stCQ$EwVhS z&<8gesjmz@yL!+kJIw|Ht3n@rQ8jN)13p%Sp3_`UpqlFu!er3bHsIGJ_0BLLspfjb zvgI~&LeCYUk6FWyI;k(aYGFe^4*J{))v+ow3)76%H2fK$mptIBLbixPMWgj|Qu8V@ z?l>6o7*rZQy5`Nht8o|VL7&EMaJfI82E8xZ2lrkXnb3^8LG;!D5bLBq*vX*BX50;; z_X)kOiAK)mDvF*P`ccqF6RpyvL*R-UchtOjW1vsUdPH5>4N`XeH>saIdNIyx(No!0 zX>*c#s0e*9BBW}7jg%}x-_TFnrQ>sFOzT8c#vLUEK_=2Z2ivmrgXpbcuWO%^7si-O z=cH!W52N>nf&|@w@1ba6JvKFO4D^@;SXpp~6mT*faj~Uk4x(p+PS-UHDHdJ0bXEgC zRfOIdu%ye#W#GxIant7dVf4X7QC8nD+M+I)cSQxf=t0&af2J)z`C>ZKpy_%^L+h8v%?usdr&A z13tC{twHq8Sk$d$i0ot0#%a{-`ccqFLlLb`!w+S{H{85=W1zQ``)BFAc^qR?^QJ%G zTQMNY!Yhj~nRtC|$=DSIZEe!nkYZG!Cu(#3^wA5Ls9d-hEmP6RUGw3OgPu)vNILYE zC$qd+bL0-A-?dEiDmBlFZ7!YZJ92j|6VdDDdMA@f&}wO!1L(u9Wg_U7yg}=w8Fy2+ z>qBmtXhl%v$hDzW-`o{_s0e+?9kg^^HEb*!zTr0DkAWW1FpE=3y+GOJ>UlUs=mSosp-NNp2GGacG7%7?&aRKt(lTd&o=pIyH_t=a z<&2^A(isK4%jl!ZuJ_1AYwn;KccY+>#-lP1-&5HV3}`{yG0-FBhAK*_=dvXj(1Nz3 zpqJcGg>+JHrD)_1nwmEX`e0Zv=%ij;(NvA5=8b}$l5t1M)(YOa=E$A8ODE=*iJ)E6 z)_Xshxt?0kb`X6ovSv_)Z+!60uAc$=Xe3#8I;oF-GIl*RHE#$#lM!om;hO-V+4VC( zFS+mvbm*}t`n*(78}LU!9}F<+`r(J1ygw22)Vz5^=<`a}fI)|z<7Cjc_3MYxvk5}F z$X$9-N^1DI6GcNm0(xgW+o*Es1cxPEI4Z?U()M2HTg}}tddbx{L6wmkV$n+5dky%lm(DQykk_=;MeZULUF>XD8h$NVIs&_u ztO32sksDDa1o=8b}$cZ-;-jJqhYt!_DSZ(c_4a^aN{y^BSqzBNi62Yt+iS30{s258OG zChpBk=yxkwD$?p{iznUH^@pD>`{nld zi}U{LAJ3N;%XNS7Gc{h8kV#{BvE(`x_y z(f6Cg@pAKa-=Dhl_G~U+Z@cwrcYeNmTIu6zeRkUQT{>^Kf4dTu_s1Q5`?7y=xw-M0 ze0z0uzB=jp^wY0jjO%lMa`|Urc zxA>=*7r!slodJ9Wu>b#PapQ~qlixk2;|Dv`t95z~-zSvI%@65m{GKj-{NR7q#cVUg GfB^tPCqU%@ literal 0 HcmV?d00001 From 4839b64975eb01839dbca64516e70271c98f0e27 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Mon, 24 May 2021 20:54:24 +0200 Subject: [PATCH 12/12] coverage --- rowers/c2stuff.py | 2 +- rowers/sporttracksstuff.py | 2 +- rowers/tasks.py | 2 +- rowers/templatetags/rowerfilters.py | 2 +- rowers/tests/testdata/testdata.tcx.gz | Bin 4000 -> 0 bytes 5 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 rowers/tests/testdata/testdata.tcx.gz diff --git a/rowers/c2stuff.py b/rowers/c2stuff.py index 200adba1..98d93f29 100644 --- a/rowers/c2stuff.py +++ b/rowers/c2stuff.py @@ -963,7 +963,7 @@ def workout_c2_upload(user,w,asynchron=False): 'Content-Type': 'application/json'} import urllib url = "https://log.concept2.com/api/users/%s/results" % (c2userid) - if not asynchron: + if not asynchron: # pragma: no cover response = requests.post(url,headers=headers,data=json.dumps(data,default=default)) diff --git a/rowers/sporttracksstuff.py b/rowers/sporttracksstuff.py index 56ce890e..94b99ce2 100644 --- a/rowers/sporttracksstuff.py +++ b/rowers/sporttracksstuff.py @@ -259,7 +259,7 @@ def createsporttracksworkoutdata(w): # Obtain SportTracks Workout ID from the response returned on successful # upload -def getidfromresponse(response): +def getidfromresponse(response): # pragma: no cover t = response.json() uri = t['uris'][0] regex = '.*?sporttracks\.mobi\/api\/v2\/fitnessActivities/(\d+)\.json$' diff --git a/rowers/tasks.py b/rowers/tasks.py index c16924da..d8f24c01 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -2827,7 +2827,7 @@ def handle_rp3_async_workout(userid,rp3token,rp3id,startdatetime,max_attempts,de try: workout_download_details = pd.json_normalize(response.json()['data']['download']) - except JSONDecodeError: + except JSONDecodeError: # pragma: no cover return 0 if workout_download_details.iat[0,1] == 'ready': diff --git a/rowers/templatetags/rowerfilters.py b/rowers/templatetags/rowerfilters.py index ee91bdb0..1958c6e3 100644 --- a/rowers/templatetags/rowerfilters.py +++ b/rowers/templatetags/rowerfilters.py @@ -433,7 +433,7 @@ def deltatimeprint(d): # pragma: no cover return strfdeltah(d) @register.filter -def c2userid(user): +def c2userid(user): # pragma: no cover try: thetoken = c2_open(user) except NoTokenError: # pragma: no cover diff --git a/rowers/tests/testdata/testdata.tcx.gz b/rowers/tests/testdata/testdata.tcx.gz deleted file mode 100644 index 26c23e7e17038aff0d1836d269d35a4a58c4c27c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4000 zcmV;R4`1*fiwFpLAE{sh|8!+@bYx+4VJ>uIcmVC4NpBoC7J%>m6@m}RVG#CP__!#t zf^35^U}u8Z$mBMtNFBLnq?XWKUh?mU?6zguRv~`U6u~Oc2SZ(5Th~{Qd^?Z6d2?}o z@M^i)t}fS)9-@JV2j3h&IC{S6R_oRJ?EB@qUv7Tr`tJ8`yF5rcueXmLzUcd_!^PtD z>(}P2+gz;H=H&8Xk-prXyjWgz+r{mNFJ95Z{V5K+H=l8qZ%_Kwt5yH!k8k?rI^W=p z6TI23J~+c`HkX^T1p(mVx2I2@?N0I4YQ62d^~o|FwOt+V&->)^r0aLT_D(l&pg-yr znK#?hzdrEqUH^S|ez{pKw~JT!*Zcp`^(XuNm)DoV&%4whpt~Nr|BVli9~>MUy?p@b zXXKCXH~e|5_haQ|ic`tj*80lKe1z9M*zd}#5IoQaM&!ruT60ge`F zr+525>8=i*_1&g_zPeaGdiYnzUSB93`uwu*&huf6ct@ ze!Tu}+4b9>mz$@n^~-+w@BYS*NT>O=JAb)6Mw>3O|MUG77PnmD#@A1~H>-=67yqXl z5O>QB+;WK&Ue*53F_9Sjc@WBIyTb}Q3hwIU6`^jaW|NPr$&jh!Q;UAwdo%3H^-zTw&M~nSmA768k zF8cA$yZsjPi*OrWEp-Nyq+P6nIPg?r}EUovny_O!98UYq-af^3E_D?!F@KmUiR3Q*gJzP(ki^5AIkM z_W%`fm&82@l}4NQ#!ZBKUGg5dBJSP<4^E@cJ6F<-W10_lUk`Ty;{#fayn8V+5$=_Z z^A*`~!X|=^8ty?#+V69c_fQdcXB-e{^tvcT_4)b8J3>W@okYW|bJHS}CC~RDPj!)} zYNmKPgk;Kz&XhxxlD-?Z^O1R$ipX0NlTxpec@h%}l9w5gj}?(m=A0l0Rd~h~wd37< z$Xizrc?9Dul1k>2@n6z&=jSue3sgj&jb#+pkT2}Ji!&lm6_Ixaoz97a&X=6$Ews^o z6!O7D5~~T%p${efclRRSM*BhXgvJqg)o35elAlk64y7Wij;s+tRB3oImbB;RMBavq z$R|CW3028g5KBhsEX`=N$BM{D6A-*rrQJ31Ga%1oT*Rm%pObS7lAn>^zNXQh#jpdf zndixtC2wa$zM_Z?2Lk|JG~@+JM(6E){Px_ex*_sOeyu}Q8Wu?`>BE~9`HFmamJK6X zO_Y{=(G2@WekAhFfK`$YFd3PzZJw_vN^67h=~YzO^AU`18s60Bc|nszUS-cSK+%ZJ zj7IyKWL~UE&lX5S9&s|deT&i#lXu1o22GTf35(kEb0S}nJ)bQ!wyJra8BLrBd2I9i z?c_P<-ZCI*JUQt_DVcR`UGv+ILS76o1eMGS6^+<5^5c;ACM1bR4SB~+=I=miR| zBtTF#$?#lM=6%!cMgB=55)m z>)2{(MGorgM=%kIHQrkX*m7^DFZ0Mo0+A+4>u@^c zxp{I1$-A6&t?Gp62#f0Wb0S~UXdewA22Fh4F%_+%_ANd?2Kk(O8!%}4-a1P~b8qKF zz9M^`tRaW2n&*WklY7gpetwX=H)xSmqrIb|_WX>2L2m7oF$lM7|>3 zK51(lQMGEB3*4f#GaxSpKvZ4MUE~&}o&IRg-iYWrA$n-!?@GQR-QI#>FDg%tM_W?E zyH_4w)9{ALbMAhs^4|Jn3C5OzIeGG8ymhFF)%m0w6pYmg&d8pxC_Zn4vB;>&$?@rJ zu@fO*n-4G4LtZe~(yG?9@KUsXeoiu9lZGd3ybx-9c;2~^e*0O?^A*|iNq#w!s>a59 z*D5OSNWP*dtwaM%pc?Iin~ZMXytf17g15oSSD3w zMnrDpryj9Mmsax;c@r$dhA(p-7;~w~yWz9qnCP zi+T+5``laIJRd?)t8Px@EAr$>ve1}7MLve2IXSM)^P`Y=CRk!klokQXhH2-7z9LtS z#GG&sL4}^6p}%AQ(`v?hmpk9Os2lGQ7>lOd-v>QZhF&T{FS%g~=mvaClR=NI-}NB+ zU<3(Cg+8fqkLvjTKb+a1p#TslOw7stCQ$EwVhS z&<8gesjmz@yL!+kJIw|Ht3n@rQ8jN)13p%Sp3_`UpqlFu!er3bHsIGJ_0BLLspfjb zvgI~&LeCYUk6FWyI;k(aYGFe^4*J{))v+ow3)76%H2fK$mptIBLbixPMWgj|Qu8V@ z?l>6o7*rZQy5`Nht8o|VL7&EMaJfI82E8xZ2lrkXnb3^8LG;!D5bLBq*vX*BX50;; z_X)kOiAK)mDvF*P`ccqF6RpyvL*R-UchtOjW1vsUdPH5>4N`XeH>saIdNIyx(No!0 zX>*c#s0e*9BBW}7jg%}x-_TFnrQ>sFOzT8c#vLUEK_=2Z2ivmrgXpbcuWO%^7si-O z=cH!W52N>nf&|@w@1ba6JvKFO4D^@;SXpp~6mT*faj~Uk4x(p+PS-UHDHdJ0bXEgC zRfOIdu%ye#W#GxIant7dVf4X7QC8nD+M+I)cSQxf=t0&af2J)z`C>ZKpy_%^L+h8v%?usdr&A z13tC{twHq8Sk$d$i0ot0#%a{-`ccqFLlLb`!w+S{H{85=W1zQ``)BFAc^qR?^QJ%G zTQMNY!Yhj~nRtC|$=DSIZEe!nkYZG!Cu(#3^wA5Ls9d-hEmP6RUGw3OgPu)vNILYE zC$qd+bL0-A-?dEiDmBlFZ7!YZJ92j|6VdDDdMA@f&}wO!1L(u9Wg_U7yg}=w8Fy2+ z>qBmtXhl%v$hDzW-`o{_s0e+?9kg^^HEb*!zTr0DkAWW1FpE=3y+GOJ>UlUs=mSosp-NNp2GGacG7%7?&aRKt(lTd&o=pIyH_t=a z<&2^A(isK4%jl!ZuJ_1AYwn;KccY+>#-lP1-&5HV3}`{yG0-FBhAK*_=dvXj(1Nz3 zpqJcGg>+JHrD)_1nwmEX`e0Zv=%ij;(NvA5=8b}$l5t1M)(YOa=E$A8ODE=*iJ)E6 z)_Xshxt?0kb`X6ovSv_)Z+!60uAc$=Xe3#8I;oF-GIl*RHE#$#lM!om;hO-V+4VC( zFS+mvbm*}t`n*(78}LU!9}F<+`r(J1ygw22)Vz5^=<`a}fI)|z<7Cjc_3MYxvk5}F z$X$9-N^1DI6GcNm0(xgW+o*Es1cxPEI4Z?U()M2HTg}}tddbx{L6wmkV$n+5dky%lm(DQykk_=;MeZULUF>XD8h$NVIs&_u ztO32sksDDa1o=8b}$cZ-;-jJqhYt!_DSZ(c_4a^aN{y^BSqzBNi62Yt+iS30{s258OG zChpBk=yxkwD$?p{iznUH^@pD>`{nld zi}U{LAJ3N;%XNS7Gc{h8kV#{BvE(`x_y z(f6Cg@pAKa-=Dhl_G~U+Z@cwrcYeNmTIu6zeRkUQT{>^Kf4dTu_s1Q5`?7y=xw-M0 ze0z0uzB=jp^wY0jjO%lMa`|Urc zxA>=*7r!slodJ9Wu>b#PapQ~qlixk2;|Dv`t95z~-zSvI%@65m{GKj-{NR7q#cVUg GfB^tPCqU%@