Private
Public Access
1
0

done all except mapmyfitness

This commit is contained in:
Sander Roosendaal
2018-06-26 16:01:46 +02:00
parent 39c2c23842
commit bc396e62a1
7 changed files with 883 additions and 606 deletions

View File

@@ -15,6 +15,7 @@ from django.utils import timezone
from datetime import datetime from datetime import datetime
from datetime import timedelta from datetime import timedelta
import time import time
from time import strftime
# Django # Django
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
@@ -25,7 +26,7 @@ from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
import dataprep import dataprep
import pytz import pytz
from rowingdata import rowingdata from rowingdata import rowingdata, make_cumvalues
import pandas as pd import pandas as pd
import numpy as np import numpy as np
from rowers.models import Rower,Workout from rowers.models import Rower,Workout
@@ -36,6 +37,8 @@ from requests import Request, Session
from utils import myqueue,uniqify,isprorower, custom_exception_handler, NoTokenError from utils import myqueue,uniqify,isprorower, custom_exception_handler, NoTokenError
from uuid import uuid4
from rowers.types import otwtypes from rowers.types import otwtypes
from rowsandall_app.settings import C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET from rowsandall_app.settings import C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET
@@ -540,7 +543,7 @@ def make_authorization_url(request):
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
# Get workout from C2 ID # Get workout from C2 ID
def get_c2_workout(user,c2id): def get_workout(user,c2id):
r = Rower.objects.get(user=user) r = Rower.objects.get(user=user)
if (r.c2token == '') or (r.c2token is None): if (r.c2token == '') or (r.c2token is None):
s = "Token doesn't exist. Need to authorize" s = "Token doesn't exist. Need to authorize"
@@ -557,7 +560,24 @@ def get_c2_workout(user,c2id):
url = "https://log.concept2.com/api/users/me/results/"+str(c2id) url = "https://log.concept2.com/api/users/me/results/"+str(c2id)
s = requests.get(url,headers=headers) s = requests.get(url,headers=headers)
return s data = s.json()['data']
splitdata = None
if 'workout' in data:
if 'splits' in data['workout']:
splitdata = data['workout']['splits']
if 'intervals' in data['workout']:
splitdata = data['workout']['intervals']
# 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:
strokedata = pd.DataFrame()
return data,strokedata
# Get stroke data belonging to C2 ID # Get stroke data belonging to C2 ID
def get_c2_workout_strokes(user,c2id): def get_c2_workout_strokes(user,c2id):
@@ -725,3 +745,154 @@ def rower_c2_token_refresh(user):
else: else:
return None 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 = data['type']
except KeyError:
workouttype = 'rower'
if workouttype not in [x[0] for x in Workout.workouttypes]:
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:
rowdatetime = iso8601.parse_date(data['date'])
try:
c2intervaltype = data['workout_type']
except KeyError:
c2intervaltype = ''
try:
title = data['name']
except KeyError:
title = ""
try:
t = data['comments'].split('\n', 1)[0]
title += t[:20]
except:
title = 'Imported'
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.ix[:,'t']
nr_rows = len(unixtime)
try:
latcoord = strokedata.ix[:,'lat']
loncoord = strokedata.ix[:,'lon']
except:
latcoord = np.zeros(nr_rows)
loncoord = np.zeros(nr_rows)
try:
strokelength = strokedata.ix[:,'strokelength']
except:
strokelength = np.zeros(nr_rows)
dist2 = 0.1*strokedata.ix[:,'d']
try:
spm = strokedata.ix[:,'spm']
except KeyError:
spm = 0*dist2
try:
hr = strokedata.ix[:,'hr']
except KeyError:
hr = 0*spm
pace = strokedata.ix[:,'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:
totaldist = 0
totaltime = 0
else:
totaldist = 0
totaltime = 0
id,message = dataprep.save_workout_database(
csvfilename,r,
workouttype=workouttype,
title=title,notes=comments,
workoutsource=workoutsource,
dosummary=True
)
return id,message

View File

@@ -12,6 +12,8 @@ from datetime import datetime
import numpy as np import numpy as np
from dateutil import parser from dateutil import parser
import time import time
import dateutil
from time import strftime
import math import math
from math import sin,cos,atan2,sqrt from math import sin,cos,atan2,sqrt
import os,sys import os,sys
@@ -29,7 +31,10 @@ from django.contrib.auth.decorators import login_required
from rowingdata import rowingdata from rowingdata import rowingdata
import pandas as pd import pandas as pd
from rowers.models import Rower,Workout,checkworkoutuser from rowers.models import Rower,Workout,checkworkoutuser
from uuid import uuid4
import iso8601
import arrow
from rowers import types
from rowsandall_app.settings import ( from rowsandall_app.settings import (
C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET, C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET,
STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, STRAVA_CLIENT_SECRET, STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, STRAVA_CLIENT_SECRET,
@@ -38,6 +43,27 @@ from rowsandall_app.settings import (
from utils import geo_distance,ewmovingaverage,NoTokenError, custom_exception_handler from utils import geo_distance,ewmovingaverage,NoTokenError, custom_exception_handler
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)]
import dataprep
# Checks if user has SportTracks token, renews them if they are expired # Checks if user has SportTracks token, renews them if they are expired
def runkeeper_open(user): def runkeeper_open(user):
@@ -75,7 +101,6 @@ def get_token(code):
def make_authorization_url(request): def make_authorization_url(request):
# Generate a random string for the state parameter # Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks # Save it for use later to prevent xsrf attacks
from uuid import uuid4
state = str(uuid4()) state = str(uuid4())
params = {"client_id": RUNKEEPER_CLIENT_ID, params = {"client_id": RUNKEEPER_CLIENT_ID,
@@ -105,7 +130,7 @@ def get_runkeeper_workout_list(user):
return s return s
# Get workout summary data by Runkeeper ID # Get workout summary data by Runkeeper ID
def get_runkeeper_workout(user,runkeeperid): def get_workout(user,runkeeperid):
r = Rower.objects.get(user=user) r = Rower.objects.get(user=user)
if (r.runkeepertoken == '') or (r.runkeepertoken is None): if (r.runkeepertoken == '') or (r.runkeepertoken is None):
return custom_exception_handler(401,s) return custom_exception_handler(401,s)
@@ -119,7 +144,16 @@ def get_runkeeper_workout(user,runkeeperid):
url = "https://api.runkeeper.com/fitnessActivities/"+str(runkeeperid) url = "https://api.runkeeper.com/fitnessActivities/"+str(runkeeperid)
s = requests.get(url,headers=headers) s = requests.get(url,headers=headers)
return s try:
data = s.json()
except ValueError:
data = {}
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 # Create Workout Data for upload to SportTracks
def createrunkeeperworkoutdata(w): def createrunkeeperworkoutdata(w):
@@ -328,3 +362,183 @@ def workout_runkeeper_upload(user,w):
return message, rkid return message, rkid
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:
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:
rowdatetime = datetime.strptime(data['start_time'],"%Y-%m-%d %H:%M:%S")
rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
except ValueError:
try:
rowdatetime = dateutil.parser.parse(data['start_time'])
#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
#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:
times_location = times_distance
latcoord = np.zeros(len(times_distance))
loncoord = np.zeros(len(times_distance))
if workouttype in types.otwtypes:
workouttype = 'rower'
try:
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:
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:
latseries = 0.0*distseries
lonseries = pd.Series(loncoord,index=times_location)
try:
lonseries = lonseries.groupby(lonseries.index).first()
except TypeError:
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:
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:
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,
notes=comments)
return (id,message)

View File

@@ -17,7 +17,9 @@ from math import sin,cos,atan2,sqrt
import urllib import urllib
import c2stuff import c2stuff
import pytz import pytz
import iso8601
from uuid import uuid4
import arrow
# Django # Django
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect, HttpResponse,JsonResponse from django.http import HttpResponseRedirect, HttpResponse,JsonResponse
@@ -31,10 +33,26 @@ from django.contrib.auth.decorators import login_required
from rowingdata import rowingdata from rowingdata import rowingdata
import pandas as pd import pandas as pd
from rowers.models import Rower,Workout,checkworkoutuser from rowers.models import Rower,Workout,checkworkoutuser
from rowers import types
from rowsandall_app.settings import C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET, STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, STRAVA_CLIENT_SECRET, SPORTTRACKS_CLIENT_SECRET, SPORTTRACKS_CLIENT_ID, SPORTTRACKS_REDIRECT_URI from rowsandall_app.settings import C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET, STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, STRAVA_CLIENT_SECRET, SPORTTRACKS_CLIENT_SECRET, SPORTTRACKS_CLIENT_ID, SPORTTRACKS_REDIRECT_URI
from utils import NoTokenError, custom_exception_handler from utils import NoTokenError, custom_exception_handler, ewmovingaverage
from time import strftime
import dataprep
# Splits SportTracks data which is one long sequence of
# [t,[lat,lon],t2,[lat2,lon2] ...]
# to [t,t2,t3, ...], [[lat,long],[lat2,long2],...
def splitstdata(lijst):
t = []
latlong = []
while len(lijst)>=2:
t.append(lijst[0])
latlong.append(lijst[1])
lijst = lijst[2:]
return [np.array(t),np.array(latlong)]
# Checks if user has SportTracks token, renews them if they are expired # Checks if user has SportTracks token, renews them if they are expired
@@ -125,7 +143,7 @@ def get_token(code):
def make_authorization_url(request): def make_authorization_url(request):
# Generate a random string for the state parameter # Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks # Save it for use later to prevent xsrf attacks
from uuid import uuid4
state = str(uuid4()) state = str(uuid4())
params = {"client_id": SPORTTRACKS_CLIENT_ID, params = {"client_id": SPORTTRACKS_CLIENT_ID,
@@ -178,7 +196,7 @@ def get_sporttracks_workout_list(user):
return s return s
# Get workout summary data by SportTracks ID # Get workout summary data by SportTracks ID
def get_sporttracks_workout(user,sporttracksid): def get_workout(user,sporttracksid):
r = Rower.objects.get(user=user) r = Rower.objects.get(user=user)
if (r.sporttrackstoken == '') or (r.sporttrackstoken is None): if (r.sporttrackstoken == '') or (r.sporttrackstoken is None):
return custom_exception_handler(401,s) return custom_exception_handler(401,s)
@@ -195,7 +213,13 @@ def get_sporttracks_workout(user,sporttracksid):
url = "https://api.sporttracks.mobi/api/v2/fitnessActivities/"+str(sporttracksid) url = "https://api.sporttracks.mobi/api/v2/fitnessActivities/"+str(sporttracksid)
s = requests.get(url,headers=headers) s = requests.get(url,headers=headers)
return s 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 SportTracks # Create Workout Data for upload to SportTracks
def createsporttracksworkoutdata(w): def createsporttracksworkoutdata(w):
@@ -366,3 +390,176 @@ def workout_sporttracks_upload(user,w):
return message,stid return message,stid
return message,stid return message,stid
# Create workout from SportTracks Data, which are slightly different
# than Strava or Concept2 data
def add_workout_from_data(user,importid,data,strokedata,source='sporttracks',
workoutsource='sporttracks'):
try:
workouttype = data['type']
except KeyError:
workouttype = 'other'
if workouttype not in [x[0] for x in Workout.workouttypes]:
workouttype = 'other'
try:
comments = data['comments']
except:
comments = ''
r = Rower.objects.get(user=user)
try:
rowdatetime = iso8601.parse_date(data['start_time'])
except iso8601.ParseError:
try:
rowdatetime = datetime.datetime.strptime(data['start_time'],"%Y-%m-%d %H:%M:%S")
rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
except:
try:
rowdatetime = dateutil.parser.parse(data['start_time'])
rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
except:
rowdatetime = datetime.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:
title = "Imported data"
try:
res = splitstdata(data['distance'])
distance = res[1]
times_distance = res[0]
except KeyError:
try:
res = splitstdata(data['heartrate'])
times_distance = res[0]
distance = 0*times_distance
except KeyError:
return (0,"No distance or heart rate data in the workout")
try:
l = data['location']
res = splitstdata(l)
times_location = res[0]
latlong = res[1]
latcoord = []
loncoord = []
for coord in latlong:
lat = coord[0]
lon = coord[1]
latcoord.append(lat)
loncoord.append(lon)
except:
times_location = times_distance
latcoord = np.zeros(len(times_distance))
loncoord = np.zeros(len(times_distance))
if workouttype in types.otwtypes:
workouttype = 'rower'
try:
res = splitstdata(data['cadence'])
times_spm = res[0]
spm = res[1]
except KeyError:
times_spm = times_distance
spm = 0*times_distance
try:
res = splitstdata(data['heartrate'])
hr = res[1]
times_hr = res[0]
except KeyError:
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)
velo2 = 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,
title=title,
notes=comments,
workoutsource='sporttracks')
return (id,message)

View File

@@ -11,6 +11,7 @@ from datetime import datetime
import numpy as np import numpy as np
from dateutil import parser from dateutil import parser
import time import time
from time import strftime,strptime
import math import math
from math import sin,cos,atan2,sqrt from math import sin,cos,atan2,sqrt
import os,sys import os,sys
@@ -35,6 +36,7 @@ queuehigh = django_rq.get_queue('low')
# Project # Project
# from .models import Profile # from .models import Profile
from rowingdata import rowingdata from rowingdata import rowingdata
from rowingdata import make_cumvalues
import pandas as pd import pandas as pd
from rowers.models import Rower,Workout from rowers.models import Rower,Workout
from rowers.models import checkworkoutuser from rowers.models import checkworkoutuser
@@ -252,7 +254,7 @@ def create_async_workout(alldata,user,stravaid):
from utils import get_strava_stream from utils import get_strava_stream
# Get a Strava workout summary data and stroke data by ID # Get a Strava workout summary data and stroke data by ID
def get_strava_workout(user,stravaid): def get_workout(user,stravaid):
r = Rower.objects.get(user=user) r = Rower.objects.get(user=user)
if (r.stravatoken == '') or (r.stravatoken is None): if (r.stravatoken == '') or (r.stravatoken is None):
s = "Token doesn't exist. Need to authorize" s = "Token doesn't exist. Need to authorize"
@@ -347,7 +349,7 @@ def get_strava_workout(user,stravaid):
# startdatetime = datetime.datetime.strptime(startdatetime,"%Y-%m-%d-%H:%M:%S") # startdatetime = datetime.datetime.strptime(startdatetime,"%Y-%m-%d-%H:%M:%S")
return [workoutsummary,df] return [workoutsummary,df]
# Generate Workout data for Strava (a TCX file) # Generate Workout data for Strava (a TCX file)
def createstravaworkoutdata(w,dozip=True): def createstravaworkoutdata(w,dozip=True):
filename = w.csvfilename filename = w.csvfilename
@@ -482,3 +484,142 @@ def workout_strava_upload(user,w):
return message,stravaid return message,stravaid
return message,stravaid return message,stravaid
return message,stravaid return message,stravaid
# 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 = data['type']
except KeyError:
workouttype = 'rower'
if workouttype not in [x[0] for x in Workout.workouttypes]:
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:
rowdatetime = iso8601.parse_date(data['date'])
try:
intervaltype = data['workout_type']
except KeyError:
intervaltype = ''
try:
title = data['name']
except KeyError:
title = ""
try:
t = data['comments'].split('\n', 1)[0]
title += t[:20]
except:
title = 'Imported'
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.ix[:,'t']
nr_rows = len(unixtime)
try:
latcoord = strokedata.ix[:,'lat']
loncoord = strokedata.ix[:,'lon']
except:
latcoord = np.zeros(nr_rows)
loncoord = np.zeros(nr_rows)
try:
strokelength = strokedata.ix[:,'strokelength']
except:
strokelength = np.zeros(nr_rows)
dist2 = 0.1*strokedata.ix[:,'d']
try:
spm = strokedata.ix[:,'spm']
except KeyError:
spm = 0*dist2
try:
hr = strokedata.ix[:,'hr']
except KeyError:
hr = 0*spm
pace = strokedata.ix[:,'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')
id,message = dataprep.save_workout_database(
csvfilename,r,
workouttype=workouttype,
title=title,notes=comments,
workoutsource=workoutsource,
dosummary=True
)
return id,message

View File

@@ -321,17 +321,17 @@ urlpatterns = [
url(r'^workout/c2list/$',views.workout_c2import_view), url(r'^workout/c2list/$',views.workout_c2import_view),
url(r'^workout/c2list/(?P<page>\d+)$',views.workout_c2import_view), url(r'^workout/c2list/(?P<page>\d+)$',views.workout_c2import_view),
url(r'^workout/stravaimport/$',views.workout_stravaimport_view), url(r'^workout/stravaimport/$',views.workout_stravaimport_view),
url(r'^workout/c2import/(?P<c2id>\d+)/$',views.workout_getc2workout_view), # url(r'^workout/c2import/(?P<c2id>\d+)/$',views.workout_getc2workout_view),
url(r'^workout/c2import/all/$',views.workout_getc2workout_all), url(r'^workout/c2import/all/$',views.workout_getc2workout_all),
url(r'^workout/c2import/all/(?P<page>\d+)$',views.workout_getc2workout_all), url(r'^workout/c2import/all/(?P<page>\d+)$',views.workout_getc2workout_all),
url(r'^workout/stravaimport/(?P<stravaid>\d+)/$',views.workout_getstravaworkout_view), # url(r'^workout/stravaimport/(?P<stravaid>\d+)/$',views.workout_getstravaworkout_view),
url(r'^workout/(?P<source>\w+.*)import/(?P<externalid>\d+)/$',views.workout_getimportview),
url(r'^workout/stravaimport/all/$',views.workout_getstravaworkout_all), url(r'^workout/stravaimport/all/$',views.workout_getstravaworkout_all),
url(r'^workout/sporttracksimport/$',views.workout_sporttracksimport_view), url(r'^workout/sporttracksimport/$',views.workout_sporttracksimport_view),
url(r'^workout/sporttracksimport/(?P<sporttracksid>\d+)/$',views.workout_getsporttracksworkout_view),
url(r'^workout/sporttracksimport/all/$',views.workout_getsporttracksworkout_all), url(r'^workout/sporttracksimport/all/$',views.workout_getsporttracksworkout_all),
url(r'^workout/polarimport/$',views.workout_polarimport_view), url(r'^workout/polarimport/$',views.workout_polarimport_view),
url(r'^workout/runkeeperimport/$',views.workout_runkeeperimport_view), url(r'^workout/runkeeperimport/$',views.workout_runkeeperimport_view),
url(r'^workout/runkeeperimport/(?P<runkeeperid>\d+)/$',views.workout_getrunkeeperworkout_view), # url(r'^workout/runkeeperimport/(?P<runkeeperid>\d+)/$',views.workout_getrunkeeperworkout_view),
url(r'^workout/underarmourimport/$',views.workout_underarmourimport_view), url(r'^workout/underarmourimport/$',views.workout_underarmourimport_view),
url(r'^workout/underarmourimport/(?P<underarmourid>\d+)/$',views.workout_getunderarmourworkout_view), url(r'^workout/underarmourimport/(?P<underarmourid>\d+)/$',views.workout_getunderarmourworkout_view),
url(r'^workout/(?P<id>\d+)/deleteconfirm$',views.workout_delete_confirm_view), url(r'^workout/(?P<id>\d+)/deleteconfirm$',views.workout_delete_confirm_view),

View File

@@ -435,8 +435,8 @@ def get_strava_stream(r,metric,stravaid,series_type='time',fetchresolution='high
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'resolution': 'medium',} 'resolution': 'medium',}
url = "https://www.strava.com/api/v3/activities/{stravaid}/streams/{metric}?resolution={fetchresolutions}&series_type={series_type}".format( url = "https://www.strava.com/api/v3/activities/{stravaid}/streams/{metric}?resolution={fetchresolution}&series_type={series_type}".format(
stravaid=stravid, stravaid=stravaid,
fetchresolution=fetchresolution, fetchresolution=fetchresolution,
series_type=series_type, series_type=series_type,
metric=metric metric=metric

View File

@@ -839,6 +839,12 @@ def get_time(second):
def getidfromsturi(uri,length=8): def getidfromsturi(uri,length=8):
return uri[len(uri)-length:] return uri[len(uri)-length:]
import re
def getidfromuri(uri):
m = re.search('/(\w.*)\/(\d+)',uri)
return m.group(2)
def splituadata(lijst): def splituadata(lijst):
t = [] t = []
y = [] y = []
@@ -848,38 +854,6 @@ def splituadata(lijst):
return np.array(t),np.array(y) return np.array(t),np.array(y)
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)]
# Splits SportTracks data which is one long sequence of
# [t,[lat,lon],t2,[lat2,lon2] ...]
# to [t,t2,t3, ...], [[lat,long],[lat2,long2],...
def splitstdata(lijst):
t = []
latlong = []
while len(lijst)>=2:
t.append(lijst[0])
latlong.append(lijst[1])
lijst = lijst[2:]
return [np.array(t),np.array(latlong)]
from utils import ( from utils import (
geo_distance,serialize_list,deserialize_list,uniqify, geo_distance,serialize_list,deserialize_list,uniqify,
@@ -1268,353 +1242,8 @@ def add_workout_from_strokedata(user,importid,data,strokedata,
return id,message return id,message
# Create workout from RunKeeper Data
def add_workout_from_runkeeperdata(user,importid,data):
# 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:
comments = ''
try:
utcoffset = tz(data['utcoffset'])
except:
utcoffset = 0
r = getrower(user)
try:
rowdatetime = iso8601.parse_date(data['start_time'])
except iso8601.ParseError:
try:
rowdatetime = datetime.datetime.strptime(data['start_time'],"%Y-%m-%d %H:%M:%S")
rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
except:
try:
rowdatetime = dateutil.parser.parse(data['start_time'])
#rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
except:
rowdatetime = datetime.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:
times_location = times_distance
latcoord = np.zeros(len(times_distance))
loncoord = np.zeros(len(times_distance))
if workouttype in types.otwtypes:
workouttype = 'rower'
try:
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:
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:
latseries = 0.0*distseries
lonseries = pd.Series(loncoord,index=times_location)
try:
lonseries = lonseries.groupby(lonseries.index).first()
except TypeError:
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:
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:
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,
notes=comments)
return (id,message)
# Create workout from SportTracks Data, which are slightly different
# than Strava or Concept2 data
def add_workout_from_stdata(user,importid,data):
workouttype = data['type']
if workouttype not in [x[0] for x in Workout.workouttypes]:
workouttype = 'other'
try:
comments = data['comments']
except:
comments = ''
r = getrower(user)
try:
rowdatetime = iso8601.parse_date(data['start_time'])
except iso8601.ParseError:
try:
rowdatetime = datetime.datetime.strptime(data['start_time'],"%Y-%m-%d %H:%M:%S")
rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
except:
try:
rowdatetime = dateutil.parser.parse(data['start_time'])
rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
except:
rowdatetime = datetime.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:
title = "Imported data"
try:
res = splitstdata(data['distance'])
distance = res[1]
times_distance = res[0]
except KeyError:
try:
res = splitstdata(data['heartrate'])
times_distance = res[0]
distance = 0*times_distance
except KeyError:
return (0,"No distance or heart rate data in the workout")
try:
l = data['location']
res = splitstdata(l)
times_location = res[0]
latlong = res[1]
latcoord = []
loncoord = []
for coord in latlong:
lat = coord[0]
lon = coord[1]
latcoord.append(lat)
loncoord.append(lon)
except:
times_location = times_distance
latcoord = np.zeros(len(times_distance))
loncoord = np.zeros(len(times_distance))
if workouttype in types.otwtypes:
workouttype = 'rower'
try:
res = splitstdata(data['cadence'])
times_spm = res[0]
spm = res[1]
except KeyError:
times_spm = times_distance
spm = 0*times_distance
try:
res = splitstdata(data['heartrate'])
hr = res[1]
times_hr = res[0]
except KeyError:
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)
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,
title=title,
notes=comments,
workoutsource='sporttracks')
return (id,message)
# Create workout from SportTracks Data, which are slightly different # Create workout from SportTracks Data, which are slightly different
# than Strava or Concept2 data # than Strava or Concept2 data
@@ -9781,12 +9410,13 @@ def workout_runkeeperimport_view(request,message=""):
workouts = [] workouts = []
for item in res.json()['items']: for item in res.json()['items']:
d = int(float(item['total_distance'])) d = int(float(item['total_distance']))
i = getidfromsturi(item['uri'],length=9) i = getidfromuri(item['uri'])
ttot = str(datetime.timedelta(seconds=int(float(item['duration'])))) ttot = str(datetime.timedelta(seconds=int(float(item['duration']))))
s = item['start_time'] s = item['start_time']
r = item['type'] r = item['type']
keys = ['id','distance','duration','starttime','type'] keys = ['id','distance','duration','starttime','type']
values = [i,d,ttot,s,r] values = [i,d,ttot,s,r]
res = dict(zip(keys,values)) res = dict(zip(keys,values))
workouts.append(res) workouts.append(res)
return render(request,'runkeeper_list_import.html', return render(request,'runkeeper_list_import.html',
@@ -9906,14 +9536,14 @@ def workout_sporttracksimport_view(request,message=""):
else: else:
workouts = [] workouts = []
r = getrower(request.user) r = getrower(request.user)
stids = [int(getidfromsturi(item['uri'])) for item in res.json()['items']] stids = [int(getidfromuri(item['uri'])) for item in res.json()['items']]
knownstids = uniqify([ knownstids = uniqify([
w.uploadedtosporttracks for w in Workout.objects.filter(user=r) w.uploadedtosporttracks for w in Workout.objects.filter(user=r)
]) ])
newids = [stid for stid in stids if not stid in knownstids] newids = [stid for stid in stids if not stid in knownstids]
for item in res.json()['items']: for item in res.json()['items']:
d = int(float(item['total_distance'])) d = int(float(item['total_distance']))
i = int(getidfromsturi(item['uri'])) i = int(getidfromuri(item['uri']))
if i in knownstids: if i in knownstids:
nnn = '' nnn = ''
else: else:
@@ -10060,63 +9690,151 @@ def workout_c2import_view(request,page=1,message=""):
'page':page, 'page':page,
}) })
importsources = {
# Import a workout from Strava 'c2':c2stuff,
'strava':stravastuff,
'polar':polarstuff,
'ownapi':ownapistuff,
'runkeeper':runkeeperstuff,
'sporttracks':sporttracksstuff,
'trainingpeaks':tpstuff,
'underarmour':underarmourstuff
}
@login_required() @login_required()
def workout_getstravaworkout_view(request,stravaid): def workout_getimportview(request,externalid,source = 'c2'):
res = stravastuff.get_strava_workout(request.user,stravaid) res = importsources[source].get_workout(request.user,externalid)
if not res[0]: if not res[0]:
messages.error(request,res[1]) messages.error(request,res[1])
return imports_view(request) return imports_view(request)
strokedata = res[1] strokedata = res[1]
data = res[0] data = res[0]
id,message = add_workout_from_strokedata(request.user,stravaid,data,strokedata,
source='strava',
workoutsource='strava') # Now works only for C2
if strokedata.empty:
distance = data['distance']
c2id = data['id']
workouttype = 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')
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 = 'Imported from C2'
w.workouttype = 'rower'
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':int(id),
})
return HttpResponseRedirect(url)
# strokdata not empty - continue
id,message = importsources[source].add_workout_from_data(
request.user,
externalid,data,
strokedata,
source=source,
workoutsource=source)
w = get_workout(id) w = get_workout(id)
w.uploadedtostrava=stravaid if 'workout' in data:
if 'splits' in data['workout']:
splitdata = data['workout']['splits']
if 'intervals' in data['workout']:
splitdata = data['workout']['intervals']
else:
splitdata = False
# splitdata (only for C2)
if splitdata:
w.summary,sa,results = c2stuff.summaryfromsplitdata(splitdata,data,w.csvfilename)
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(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':
w.uploadedtopolar = externalid
elif source == 'runkeeper':
w.uploadedtorunkeeper = externalid
elif source == 'sporttracks':
w.uploadedtosporttracks = externalid
elif source == 'trainingpeaks':
w.uploadedtotp = externalid
elif source == 'underarmour':
w.uploadedtounderarmour = externalid
w.save() w.save()
if message:
messages.error(request,message)
r = getrower(request.user)
url = reverse(r.defaultlandingpage,
kwargs = {
'id':int(id),
})
return HttpResponseRedirect(url)
# Imports a workout from Runkeeper
@login_required()
def workout_getrunkeeperworkout_view(request,runkeeperid):
res = runkeeperstuff.get_runkeeper_workout(request.user,runkeeperid)
try:
data = res.json()
except ValueError:
messages.error(request,'Error getting workout from Runkeeper')
url = reverse(workout_runkeeperimport_view)
return HttpResponseRedirect(url)
id,message = add_workout_from_runkeeperdata(request.user,runkeeperid,data)
w = Workout.objects.get(id=id)
w.uploadedtorunkeeper=runkeeperid
thetoken = runkeeper_open(request.user)
w.save()
if message: if message:
messages.error(request,message) messages.error(request,message)
r = getrower(request.user) r = getrower(request.user)
url = reverse(r.defaultlandingpage, url = reverse(r.defaultlandingpage,
kwargs = { kwargs = {
'id':int(id), 'id':int(id)
}) })
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
# Imports a workout from Underarmour # Imports a workout from Underarmour
@login_required() @login_required()
@@ -10141,30 +9859,6 @@ def workout_getunderarmourworkout_view(request,underarmourid):
# Imports a workout from SportTracks
@login_required()
def workout_getsporttracksworkout_view(request,sporttracksid):
res = sporttracksstuff.get_sporttracks_workout(request.user,sporttracksid)
data = res.json()
id,message = add_workout_from_stdata(request.user,sporttracksid,data)
if id==0:
messages.error(request,message)
url = reverse(workouts_view)
return HttpResponseRedirect(url)
w = Workout.objects.get(id=id)
w.uploadedtosporttracks=sporttracksid
w.save()
if message:
messages.error(request,message)
r = getrower(request.user)
url = reverse(r.defaultlandingpage,
kwargs = {
'id':int(id),
})
return HttpResponseRedirect(url)
# Imports all new workouts from SportTracks # Imports all new workouts from SportTracks
@login_required() @login_required()
@@ -10172,7 +9866,7 @@ def workout_getsporttracksworkout_all(request):
res = sporttracksstuff.get_sporttracks_workout_list(request.user) res = sporttracksstuff.get_sporttracks_workout_list(request.user)
if (res.status_code == 200): if (res.status_code == 200):
r = getrower(request.user) r = getrower(request.user)
stids = [int(getidfromsturi(item['uri'])) for item in res.json()['items']] stids = [int(getidfromuri(item['uri'])) for item in res.json()['items']]
knownstids = uniqify([ knownstids = uniqify([
w.uploadedtosporttracks for w in Workout.objects.filter(user=r) w.uploadedtosporttracks for w in Workout.objects.filter(user=r)
]) ])
@@ -10235,146 +9929,6 @@ def workout_getstravaworkout_all(request):
# Imports a workout from Concept2
@login_required()
def workout_getc2workout_view(request,c2id):
try:
thetoken = c2_open(request.user)
except NoTokenError:
return HttpResponseRedirect("/rowers/me/c2authorize/")
res = c2stuff.get_c2_workout(request.user,c2id)
if (res.status_code == 200):
data = res.json()['data']
splitdata = None
if 'workout' in data:
if 'splits' in data['workout']:
splitdata = data['workout']['splits']
if 'intervals' in data['workout']:
splitdata = data['workout']['intervals']
# Check if workout has stroke data, and get the stroke data
if data['stroke_data']:
res2 = c2stuff.get_c2_workout_strokes(request.user,c2id)
else:
distance = data['distance']
c2id = data['id']
workouttype = 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')
r = getrower(request.user)
id, message = dataprep.create_row_df(r,
distance,
duration,
startdatetime,
# title = 'Imported from C2',
workouttype=workouttype)
w = Workout.objects.get(id=id)
w.uploadedtoc2 = c2id
w.name = 'Imported from C2'
w.workouttype = 'rower'
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':int(id),
})
return HttpResponseRedirect(url)
# We have stroke data
if res2.status_code == 200:
strokedata = pd.DataFrame.from_dict(res2.json()['data'])
# create the workout
id,message = add_workout_from_strokedata(request.user,c2id,data,strokedata,
source='c2')
w = Workout.objects.get(id=id)
w.uploadedtoc2=c2id
# If we have split data, update the stroke data so they
# match exactly (some users are anal about this)
if splitdata:
try:
w.summary,sa,results = c2stuff.summaryfromsplitdata(splitdata,data,w.csvfilename)
except:
sa = []
results = []
with open("media/c2splitdata.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 952\r\n")
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(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 message:
messages.error(request,message)
r = getrower(request.user)
url = reverse(r.defaultlandingpage,
kwargs = {
'id':int(id),
})
return HttpResponseRedirect(url)
else:
# message = json.loads(s.text)['message']
message = json.loads(res2.text)['message']
messages.error(request,message)
url = reverse(workout_c2import_view)
return HttpResponseRedirect(url)
else:
message = "Received error code from Concept2"
messages.error(request,message)
if settings.DEBUG:
return HttpResponse(res)
else:
url = reverse(workout_c2import_view)
return HttpResponseRedirect(url)
@login_required @login_required
def workout_toggle_ranking(request,id=0): def workout_toggle_ranking(request,id=0):