adding splits to C2 workout export
This commit is contained in:
@@ -120,7 +120,7 @@ def c2_open(user):
|
||||
if (timezone.now()>r.tokenexpirydate):
|
||||
res = rower_c2_token_refresh(user)
|
||||
if res == None:
|
||||
raise NoTokenError("User has no token")
|
||||
raise NoTokenError("User has no token")
|
||||
if res[0] != None:
|
||||
thetoken = res[0]
|
||||
else:
|
||||
@@ -156,7 +156,7 @@ def get_c2_workouts(rower):
|
||||
|
||||
if not isprorower(rower):
|
||||
return 0
|
||||
|
||||
|
||||
try:
|
||||
thetoken = c2_open(rower.user)
|
||||
except NoTokenError:
|
||||
@@ -181,7 +181,7 @@ def get_c2_workouts(rower):
|
||||
]
|
||||
|
||||
knownc2ids = uniqify(knownc2ids+tombstones)
|
||||
|
||||
|
||||
newids = [c2id for c2id in c2ids if not c2id in knownc2ids]
|
||||
|
||||
for c2id in newids:
|
||||
@@ -267,7 +267,7 @@ def c2wc(weightclass):
|
||||
|
||||
# Concept2 logbook sends over split data for each interval
|
||||
# We use it here to generate a custom summary
|
||||
# Some users complained about small differences
|
||||
# Some users complained about small differences
|
||||
def summaryfromsplitdata(splitdata,data,filename,sep='|'):
|
||||
|
||||
totaldist = data['distance']
|
||||
@@ -310,17 +310,17 @@ def summaryfromsplitdata(splitdata,data,filename,sep='|'):
|
||||
restvelo = restdistance/resttime
|
||||
except (ZeroDivisionError,OverflowError):
|
||||
restvelo = 0
|
||||
|
||||
|
||||
restpower = 2.8*restvelo**(3.0)
|
||||
|
||||
try:
|
||||
avgdps = totaldist/data['stroke_count']
|
||||
except (ZeroDivisionError,OverflowError,KeyError):
|
||||
avgdps = 0
|
||||
|
||||
|
||||
from rowingdata import summarystring,workstring,interval_string
|
||||
|
||||
|
||||
|
||||
sums = summarystring(totaldist,totaltime,avgpace,spm,avghr,maxhr,
|
||||
avgdps,avgpower,readFile=filename,
|
||||
separator=sep)
|
||||
@@ -336,16 +336,16 @@ def summaryfromsplitdata(splitdata,data,filename,sep='|'):
|
||||
sums += '#-{sep}SDist{sep}-Split-{sep}-SPace-{sep}-Pwr-{sep}SPM-{sep}AvgHR{sep}MaxHR{sep}DPS-\n'.format(
|
||||
sep=sep
|
||||
)
|
||||
|
||||
|
||||
intervalnr=0
|
||||
sa = []
|
||||
results = []
|
||||
|
||||
|
||||
try:
|
||||
timebased = data['workout_type'] in ['FixedTimeSplits','FixedTimeInterval']
|
||||
except KeyError:
|
||||
timebased = False
|
||||
|
||||
|
||||
for interval in splitdata:
|
||||
idist = interval['distance']
|
||||
itime = interval['time']/10.
|
||||
@@ -373,7 +373,7 @@ def summaryfromsplitdata(splitdata,data,filename,sep='|'):
|
||||
if timebased:
|
||||
iarr = [itime,'seconds','work']
|
||||
resarr = [idist]
|
||||
|
||||
|
||||
if irest_time > 0:
|
||||
iarr += [irest_time,'seconds','rest']
|
||||
try:
|
||||
@@ -390,7 +390,7 @@ def summaryfromsplitdata(splitdata,data,filename,sep='|'):
|
||||
else:
|
||||
ivelo = 0
|
||||
ipower = 0
|
||||
|
||||
|
||||
sums += interval_string(intervalnr,idist,itime,ipace,ispm,
|
||||
iavghr,imaxhr,0,ipower,separator=sep)
|
||||
intervalnr+=1
|
||||
@@ -398,14 +398,14 @@ def summaryfromsplitdata(splitdata,data,filename,sep='|'):
|
||||
return sums,sa,results
|
||||
|
||||
# Not used now. Could be used to add workout split data to Concept2
|
||||
# logbook but needs to be reviewed.
|
||||
# logbook but needs to be reviewed.
|
||||
def createc2workoutdata_as_splits(w):
|
||||
filename = w.csvfilename
|
||||
row = rowingdata(csvfile=filename)
|
||||
|
||||
# resize per minute
|
||||
df = row.df.groupby(lambda x:x/60).mean()
|
||||
|
||||
|
||||
averagehr = int(df[' HRCur (bpm)'].mean())
|
||||
maxhr = int(df[' HRCur (bpm)'].max())
|
||||
|
||||
@@ -443,7 +443,7 @@ def createc2workoutdata_as_splits(w):
|
||||
wtype = w.workouttype
|
||||
if wtype in otwtypes:
|
||||
wtype = 'water'
|
||||
|
||||
|
||||
data = {
|
||||
"type": wtype,
|
||||
"date": w.startdatetime.isoformat(),
|
||||
@@ -467,7 +467,7 @@ def createc2workoutdata_as_splits(w):
|
||||
def createc2workoutdata(w):
|
||||
filename = w.csvfilename
|
||||
try:
|
||||
row = rowingdata(filename)
|
||||
row = rowingdata(csvfile=filename)
|
||||
except IOError:
|
||||
return 0
|
||||
|
||||
@@ -478,19 +478,45 @@ def createc2workoutdata(w):
|
||||
averagehr = 0
|
||||
maxhr = 0
|
||||
|
||||
# Calculate intervalstats
|
||||
itime, idist, itype = row.intervalstats_values()
|
||||
lapnames = row.df[' lapIdx'].unique()
|
||||
nrintervals = len(itime)
|
||||
if len(lapnames != nrintervals):
|
||||
newlapnames = []
|
||||
for name in lapnames:
|
||||
newlapnames += [name,name]
|
||||
lapnames = newlapnames
|
||||
intervaldata = []
|
||||
for i in range(nrintervals):
|
||||
if itime[i]>0:
|
||||
mask = (row.df[' lapIdx'] == lapnames[i]) & (row.df[' WorkoutState'] == itype[i])
|
||||
spmav = int(row.df[' Cadence (stokes/min)'][mask].mean().astype(int))
|
||||
hrav = int(row.df[' HRCur (bpm)'][mask].mean().astype(int))
|
||||
intervaldict = {
|
||||
'type': 'distance',
|
||||
'time': int(10*itime[i]),
|
||||
'distance': int(idist[i]),
|
||||
'heart_rate': {
|
||||
'average':hrav,
|
||||
},
|
||||
'stroke_rate': spmav,
|
||||
}
|
||||
intervaldata.append(intervaldict)
|
||||
|
||||
# adding diff, trying to see if this is valid
|
||||
t = 10*row.df.loc[:,'TimeStamp (sec)'].values-10*row.df.loc[:,'TimeStamp (sec)'].iloc[0]
|
||||
try:
|
||||
t[0] = t[1]
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
|
||||
d = 10*row.df.loc[:,' Horizontal (meters)'].values
|
||||
try:
|
||||
d[0] = d[1]
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
|
||||
p = abs(10*row.df.loc[:,' Stroke500mPace (sec/500m)'].values)
|
||||
p = np.clip(p,0,3600)
|
||||
if w.workouttype == 'bike':
|
||||
@@ -516,7 +542,7 @@ def createc2workoutdata(w):
|
||||
p = p.tolist()
|
||||
spm = spm.tolist()
|
||||
hr = hr.tolist()
|
||||
|
||||
|
||||
for i in range(len(t)):
|
||||
thisrecord = {"t":t[i],
|
||||
"d":d[i],
|
||||
@@ -547,14 +573,18 @@ def createc2workoutdata(w):
|
||||
"time": int(10*makeseconds(durationstr)),
|
||||
"weight_class": c2wc(w.weightcategory),
|
||||
"comments": w.notes,
|
||||
'stroke_rate': int(row.df[' Cadence (stokes/min)'].mean()),
|
||||
'drag_factor': int(row.dragfactor),
|
||||
"heart_rate": {
|
||||
"average": averagehr,
|
||||
"max": maxhr,
|
||||
},
|
||||
"stroke_data": stroke_data,
|
||||
'workout': {
|
||||
'splits': intervaldata,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return data
|
||||
|
||||
# Refresh Concept2 authorization token
|
||||
@@ -570,7 +600,7 @@ def do_refresh_token(refreshtoken):
|
||||
url = "https://log.concept2.com/oauth/access_token"
|
||||
s = Session()
|
||||
req = Request('POST',url, data=post_data, headers=headers)
|
||||
|
||||
|
||||
prepped = req.prepare()
|
||||
prepped.body+="&scope="
|
||||
prepped.body+=scope
|
||||
@@ -672,7 +702,7 @@ def get_workout(user,c2id):
|
||||
url = "https://log.concept2.com/api/users/me/results/"+str(c2id)
|
||||
s = requests.get(url,headers=headers)
|
||||
|
||||
|
||||
|
||||
data = s.json()['data']
|
||||
splitdata = None
|
||||
|
||||
@@ -694,7 +724,7 @@ def get_workout(user,c2id):
|
||||
strokedata = pd.DataFrame()
|
||||
else:
|
||||
strokedata = pd.DataFrame()
|
||||
|
||||
|
||||
return data,strokedata
|
||||
|
||||
# Get stroke data belonging to C2 ID
|
||||
@@ -740,7 +770,7 @@ def get_c2_workout_list(user,page=1):
|
||||
|
||||
return s
|
||||
|
||||
|
||||
|
||||
# Get username, having access token.
|
||||
# Handy for checking if the API access is working
|
||||
def get_username(access_token):
|
||||
@@ -751,7 +781,7 @@ def get_username(access_token):
|
||||
import urllib
|
||||
url = "https://log.concept2.com/api/users/me"
|
||||
response = requests.get(url,headers=headers)
|
||||
|
||||
|
||||
|
||||
me_json = response.json()
|
||||
|
||||
@@ -776,14 +806,14 @@ def get_userid(access_token):
|
||||
response = requests.get(url,headers=headers)
|
||||
except:
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
me_json = response.json()
|
||||
try:
|
||||
res = me_json['data']['id']
|
||||
except KeyError:
|
||||
res = 0
|
||||
|
||||
|
||||
return res
|
||||
|
||||
# For debugging purposes
|
||||
@@ -799,7 +829,7 @@ def process_callback(request):
|
||||
return HttpResponse("got a user name: %s" % username)
|
||||
|
||||
def default(o):
|
||||
if isinstance(o, numpy.int64): return int(o)
|
||||
if isinstance(o, numpy.int64): return int(o)
|
||||
raise TypeError
|
||||
|
||||
# Uploading workout
|
||||
@@ -810,7 +840,7 @@ def workout_c2_upload(user,w):
|
||||
return "This workout type cannot be uploaded to Concept2",0
|
||||
except KeyError:
|
||||
return "This workout type cannot be uploaded to Concept2",0
|
||||
|
||||
|
||||
thetoken = c2_open(user)
|
||||
|
||||
r = Rower.objects.get(user=user)
|
||||
@@ -825,7 +855,7 @@ def workout_c2_upload(user,w):
|
||||
|
||||
if data == 0:
|
||||
return "Error: No data file. Contact info@rowsandall.com if the problem persists",0
|
||||
|
||||
|
||||
authorizationstring = str('Bearer ' + r.c2token)
|
||||
headers = {'Authorization': authorizationstring,
|
||||
'user-agent': 'sanderroosendaal',
|
||||
@@ -849,7 +879,7 @@ def workout_c2_upload(user,w):
|
||||
else:
|
||||
message = "Something went wrong in workout_c2_upload_view. Response code 200/201 but C2 sync failed: "+response.text
|
||||
c2id = 0
|
||||
|
||||
|
||||
|
||||
return message,c2id
|
||||
|
||||
@@ -882,7 +912,7 @@ def add_workout_from_data(user,importid,data,strokedata,
|
||||
workouttype = mytypes.c2mappinginv[data['type']]
|
||||
except KeyError:
|
||||
workouttype = 'rower'
|
||||
|
||||
|
||||
if workouttype not in [x[0] for x in Workout.workouttypes]:
|
||||
workouttype = 'other'
|
||||
try:
|
||||
@@ -902,14 +932,14 @@ def add_workout_from_data(user,importid,data,strokedata,
|
||||
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:
|
||||
@@ -951,7 +981,7 @@ def add_workout_from_data(user,importid,data,strokedata,
|
||||
spm = strokedata.loc[:,'spm']
|
||||
except KeyError:
|
||||
spm = 0*dist2
|
||||
|
||||
|
||||
try:
|
||||
hr = strokedata.loc[:,'hr']
|
||||
except KeyError:
|
||||
@@ -966,7 +996,7 @@ def add_workout_from_data(user,importid,data,strokedata,
|
||||
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,
|
||||
@@ -988,9 +1018,9 @@ def add_workout_from_data(user,importid,data,strokedata,
|
||||
' ElapsedTime (sec)':seconds
|
||||
})
|
||||
|
||||
|
||||
|
||||
df.sort_values(by='TimeStamp (sec)',ascending=True)
|
||||
|
||||
|
||||
timestr = strftime("%Y%m%d-%H%M%S")
|
||||
|
||||
|
||||
@@ -1024,6 +1054,6 @@ def add_workout_from_data(user,importid,data,strokedata,
|
||||
dosummary=True
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
return id,message
|
||||
|
||||
Reference in New Issue
Block a user