moved workout creation to dataprep for workout_upload
This commit is contained in:
358
rowers/views.py
358
rowers/views.py
@@ -4053,6 +4053,7 @@ def workout_getc2workout_view(request,c2id):
|
||||
|
||||
# This is the main view for processing uploaded files
|
||||
@login_required()
|
||||
def workout_upload_view(request,message=""):
|
||||
r = Rower.objects.get(user=request.user)
|
||||
if request.method == 'POST':
|
||||
form = DocumentsForm(request.POST,request.FILES)
|
||||
@@ -4070,283 +4071,82 @@ def workout_upload_view(request,message=""):
|
||||
|
||||
|
||||
f1 = res[0] # file name
|
||||
f2 = res[1] # file name incl media directory
|
||||
|
||||
# get file type (ErgData, NK, BoatCoach, etc
|
||||
fileformat = get_file_type(f2)
|
||||
if len(fileformat)==3 and fileformat[0]=='zip':
|
||||
f_to_be_deleted = f2
|
||||
with zipfile.ZipFile(f2) as z:
|
||||
# for now, we're getting only the first file
|
||||
# from the NK zip file (issue #69 on bitbucket)
|
||||
f2 = z.extract(z.namelist()[0],path='media/')
|
||||
fileformat = fileformat[2]
|
||||
f2 = res[1] # file name incl media directory
|
||||
|
||||
# Some people try to upload Concept2 logbook summaries
|
||||
if fileformat == 'c2log':
|
||||
os.remove(f2)
|
||||
|
||||
|
||||
id,message = dataprep.new_workout_from_file(r,f2,
|
||||
workouttype=workouttype,
|
||||
title = t,
|
||||
notes='')
|
||||
if not id:
|
||||
url = reverse(workout_upload_view,
|
||||
args=[str(message)])
|
||||
response = HttpResponseRedirect(url)
|
||||
return response
|
||||
|
||||
# Some people try to upload RowPro summary logs
|
||||
if fileformat == 'rowprolog':
|
||||
os.remove(f2)
|
||||
message = "This RowPro logbook summary does not contain stroke data. Please use the Stroke Data CSV file for the individual workout in your log."
|
||||
url = reverse(workout_upload_view,
|
||||
args=[str(message)])
|
||||
response = HttpResponseRedirect(url)
|
||||
|
||||
else:
|
||||
if message:
|
||||
url = reverse(workout_edit_view,
|
||||
kwargs = {
|
||||
'id':id,
|
||||
'message':message,
|
||||
})
|
||||
else:
|
||||
url = reverse(workout_edit_view,
|
||||
kwargs = {
|
||||
'id':id,
|
||||
})
|
||||
|
||||
response = HttpResponseRedirect(url)
|
||||
w = Workout.objects.get(id=id)
|
||||
|
||||
# Sometimes people try an unsupported file type.
|
||||
# Send an email to info@rowsandall.com with the file attached
|
||||
# for me to check if it is a bug, or a new file type
|
||||
# worth supporting
|
||||
if fileformat == 'unknown':
|
||||
message = "We couldn't recognize the file type"
|
||||
url = reverse(workout_upload_view,
|
||||
args=[str(message)])
|
||||
response = HttpResponseRedirect(url)
|
||||
if settings.DEBUG:
|
||||
res = handle_sendemail_unrecognized.delay(f2,
|
||||
request.user.email)
|
||||
|
||||
else:
|
||||
res = queuehigh.enqueue(handle_sendemail_unrecognized,
|
||||
f2,request.user.email)
|
||||
|
||||
return response
|
||||
|
||||
summary = ''
|
||||
# handle non-Painsled by converting it to painsled
|
||||
# compatible CSV
|
||||
try:
|
||||
if (fileformat != 'csv'):
|
||||
# handle RowPro:
|
||||
if (fileformat == 'rp'):
|
||||
row = RowProParser(f2)
|
||||
# handle TCX
|
||||
if (fileformat == 'tcx'):
|
||||
row = TCXParser(f2)
|
||||
|
||||
# handle Mystery
|
||||
if (fileformat == 'mystery'):
|
||||
row = MysteryParser(f2)
|
||||
|
||||
# handle RowPerfect
|
||||
if (fileformat == 'rowperfect3'):
|
||||
row = RowPerfectParser(f2)
|
||||
|
||||
# handle TCX no HR
|
||||
if (fileformat == 'tcxnohr'):
|
||||
row = TCXParserNoHR(f2)
|
||||
|
||||
# handle ErgData
|
||||
if (fileformat == 'ergdata'):
|
||||
row = ErgDataParser(f2)
|
||||
|
||||
# handle Mike
|
||||
if (fileformat == 'bcmike'):
|
||||
row = BoatCoachAdvancedParser(f2)
|
||||
|
||||
# handle BoatCoach
|
||||
if (fileformat == 'boatcoach'):
|
||||
row = BoatCoachParser(f2)
|
||||
|
||||
# handle painsled desktop
|
||||
if (fileformat == 'painsleddesktop'):
|
||||
row = painsledDesktopParser(f2)
|
||||
|
||||
# handle speed coach GPS
|
||||
if (fileformat == 'speedcoach'):
|
||||
row = speedcoachParser(f2)
|
||||
|
||||
# handle speed coach GPS 2
|
||||
if (fileformat == 'speedcoach2'):
|
||||
row = SpeedCoach2Parser(f2)
|
||||
try:
|
||||
summary = row.allstats()
|
||||
except:
|
||||
pass
|
||||
|
||||
# handle ErgStick
|
||||
if (fileformat == 'ergstick'):
|
||||
row = ErgStickParser(f2)
|
||||
|
||||
# handle FIT
|
||||
if (fileformat == 'fit'):
|
||||
row = FITParser(f2)
|
||||
# The FIT files have nice lap/split summaries
|
||||
# so we make use of it
|
||||
s = fitsummarydata(f2)
|
||||
s.setsummary()
|
||||
summary = s.summarytext
|
||||
|
||||
# Save the Painsled compatible CSV file and delete
|
||||
# the uploaded file
|
||||
f_to_be_deleted = f2
|
||||
# should delete file
|
||||
f2 = f2[:-4]+'o.csv'
|
||||
row.write_csv(f2,gzip=True)
|
||||
|
||||
try:
|
||||
os.remove(f_to_be_deleted)
|
||||
except:
|
||||
os.remove(f_to_be_deleted+'.gz')
|
||||
|
||||
|
||||
if (make_plot):
|
||||
imagename = f1[:-4]+'.png'
|
||||
fullpathimagename = 'static/plots/'+imagename
|
||||
u = request.user
|
||||
r = Rower.objects.get(user=request.user)
|
||||
r = Rower.objects.get(user=request.user)
|
||||
powerperc = 100*np.array([r.pw_ut2,
|
||||
r.pw_ut1,
|
||||
r.pw_at,
|
||||
r.pw_tr,r.pw_an])/r.ftp
|
||||
|
||||
rr = rrower(hrmax=r.max,hrut2=r.ut2,
|
||||
hrut1=r.ut1,hrat=r.at,
|
||||
hrtr=r.tr,hran=r.an,ftp=r.ftp,
|
||||
powerperc=powerperc,powerzones=r.powerzones)
|
||||
row = rdata(f2,rower=rr)
|
||||
if row == 0:
|
||||
|
||||
hrpwrdata = {
|
||||
'hrmax':r.max,
|
||||
'hrut2':r.ut2,
|
||||
'hrut1':r.ut1,
|
||||
'hrat':r.at,
|
||||
'hrtr':r.tr,
|
||||
'hran':r.an,
|
||||
'ftp':r.ftp,
|
||||
'powerperc':serialize_list(powerperc),
|
||||
'powerzones':serialize_list(r.powerzones),
|
||||
}
|
||||
|
||||
# auto smoothing
|
||||
pace = row.df[' Stroke500mPace (sec/500m)'].values
|
||||
velo = 500./pace
|
||||
|
||||
f = row.df['TimeStamp (sec)'].diff().mean()
|
||||
windowsize = 2*(int(10./(f)))+1
|
||||
if not 'originalvelo' in row.df:
|
||||
|
||||
# make plot - asynchronous task
|
||||
plotnrs = {
|
||||
'timeplot':1,
|
||||
'distanceplot':2,
|
||||
'pieplot':3,
|
||||
}
|
||||
|
||||
if windowsize > 3 and windowsize<len(velo):
|
||||
|
||||
plotnr = plotnrs[plottype]
|
||||
if (workouttype=='water'):
|
||||
plotnr = plotnr+3
|
||||
|
||||
|
||||
if settings.DEBUG:
|
||||
res = handle_makeplot.delay(f1,f2,t,
|
||||
hrpwrdata,plotnr,
|
||||
imagename)
|
||||
else:
|
||||
velo2 = velo
|
||||
|
||||
velo3 = pd.Series(velo2)
|
||||
velo3 = velo3.replace([-np.inf,np.inf],np.nan)
|
||||
velo3 = velo3.fillna(method='ffill')
|
||||
|
||||
pace2 = 500./abs(velo3)
|
||||
|
||||
row.df[' Stroke500mPace (sec/500m)'] = pace2
|
||||
|
||||
row.df = row.df.fillna(0)
|
||||
|
||||
row.write_csv(f2,gzip=True)
|
||||
try:
|
||||
os.remove(f2)
|
||||
except:
|
||||
pass
|
||||
|
||||
# recalculate power data
|
||||
if workouttype == 'rower' or workouttype == 'dynamic' or workouttype == 'slides':
|
||||
try:
|
||||
row.erg_recalculatepower()
|
||||
row.write_csv(f2,gzip=True)
|
||||
except:
|
||||
pass
|
||||
|
||||
if fileformat != 'fit' and summary == '':
|
||||
summary = row.summary()
|
||||
summary += '\n'
|
||||
summary += row.intervalstats_painsled()
|
||||
|
||||
averagehr = row.df[' HRCur (bpm)'].mean()
|
||||
maxhr = row.df[' HRCur (bpm)'].max()
|
||||
|
||||
totaldist = row.df['cum_dist'].max()
|
||||
totaltime = row.df['TimeStamp (sec)'].max()-row.df['TimeStamp (sec)'].min()
|
||||
totaltime = totaltime+row.df.ix[0,' ElapsedTime (sec)']
|
||||
|
||||
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')
|
||||
workoutstartdatetime = thetimezone.localize(row.rowdatetime).astimezone(utc)
|
||||
|
||||
# check for duplicate start times
|
||||
r = Rower.objects.get(user=request.user)
|
||||
|
||||
ws = Workout.objects.filter(starttime=workoutstarttime,
|
||||
user=r)
|
||||
if (len(ws) != 0):
|
||||
message = "Warning: This workout probably already exists in the database"
|
||||
|
||||
w = Workout(user=r,name=t,date=workoutdate,
|
||||
workouttype=workouttype,
|
||||
duration=duration,distance=totaldist,
|
||||
weightcategory=r.weightcategory,
|
||||
starttime=workoutstarttime,
|
||||
csvfilename=f2,notes=notes,summary=summary,
|
||||
maxhr=maxhr,averagehr=averagehr,
|
||||
startdatetime=workoutstartdatetime)
|
||||
|
||||
w.save()
|
||||
|
||||
# put stroke data in database
|
||||
res = dataprep.dataprep(row.df,id=w.id,
|
||||
bands=True,barchart=True,
|
||||
otwpower=True,empower=True)
|
||||
|
||||
# Make Plot
|
||||
if (make_plot):
|
||||
imagename = f1[:-4]+'.png'
|
||||
fullpathimagename = 'static/plots/'+imagename
|
||||
u = request.user
|
||||
r = Rower.objects.get(user=request.user)
|
||||
powerperc = 100*np.array([r.pw_ut2,
|
||||
r.pw_ut1,
|
||||
r.pw_at,
|
||||
r.pw_tr,r.pw_an])/r.ftp
|
||||
|
||||
|
||||
hrpwrdata = {
|
||||
'hrmax':r.max,
|
||||
'hrut2':r.ut2,
|
||||
'hrut1':r.ut1,
|
||||
'hrat':r.at,
|
||||
'hrtr':r.tr,
|
||||
'hran':r.an,
|
||||
'ftp':r.ftp,
|
||||
'powerperc':serialize_list(powerperc),
|
||||
'powerzones':serialize_list(r.powerzones),
|
||||
}
|
||||
|
||||
# make plot - asynchronous task
|
||||
plotnrs = {
|
||||
'timeplot':1,
|
||||
'distanceplot':2,
|
||||
'pieplot':3,
|
||||
}
|
||||
|
||||
plotnr = plotnrs[plottype]
|
||||
if (workouttype=='water'):
|
||||
else:
|
||||
res = queue.enqueue(handle_makeplot,f1,f2,
|
||||
t,hrpwrdata,
|
||||
plotnr,imagename)
|
||||
|
||||
|
||||
if settings.DEBUG:
|
||||
res = handle_makeplot.delay(f1,f2,t,
|
||||
hrpwrdata,plotnr,
|
||||
imagename)
|
||||
else:
|
||||
res = queue.enqueue(handle_makeplot,f1,f2,
|
||||
t,hrpwrdata,
|
||||
plotnr,imagename)
|
||||
|
||||
|
||||
i = GraphImage(workout=w,
|
||||
creationdatetime=timezone.now(),
|
||||
filename=fullpathimagename)
|
||||
|
||||
i = GraphImage(workout=w,
|
||||
creationdatetime=timezone.now(),
|
||||
filename=fullpathimagename)
|
||||
i.save()
|
||||
|
||||
# upload to C2
|
||||
@@ -4355,7 +4155,6 @@ def workout_upload_view(request,message=""):
|
||||
thetoken = c2_open(request.user)
|
||||
except C2NoTokenError:
|
||||
return HttpResponseRedirect("/rowers/me/c2authorize/")
|
||||
try:
|
||||
try:
|
||||
c2userid = c2stuff.get_userid(thetoken)
|
||||
data = c2stuff.createc2workoutdata(w)
|
||||
@@ -4383,28 +4182,29 @@ def workout_upload_view(request,message=""):
|
||||
s= json.loads(response.text)
|
||||
c2id = s['data']['id']
|
||||
w.uploadedtoc2 = c2id
|
||||
w.save()
|
||||
|
||||
except:
|
||||
message = "C2 upload failed"
|
||||
url = reverse(workout_edit_view,
|
||||
w.save()
|
||||
except:
|
||||
message = "C2 upload failed"
|
||||
url = reverse(workout_edit_view,
|
||||
kwargs={
|
||||
'message':message,
|
||||
'id':str(w.id),
|
||||
'id':str(w.id),
|
||||
})
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
# redirect to workout edit page
|
||||
url = "/rowers/workout/"+str(w.id)+"/edit"
|
||||
return HttpResponseRedirect(url)
|
||||
except:
|
||||
if settings.DEBUG:
|
||||
errorstring = str(sys.exc_info()[0])
|
||||
print errorstring
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
url = reverse(workout_upload_view,
|
||||
args=[str(message)])
|
||||
|
||||
|
||||
if message:
|
||||
url = reverse(workout_edit_view,
|
||||
kwargs={
|
||||
'message':message,
|
||||
'id':w.id,
|
||||
})
|
||||
|
||||
else:
|
||||
url = reverse(workout_edit_view,
|
||||
kwargs = {
|
||||
'id':w.id,
|
||||
})
|
||||
return HttpResponseRedirect(url)
|
||||
else:
|
||||
response = render(request,
|
||||
|
||||
Reference in New Issue
Block a user