Completed views.py
This commit is contained in:
@@ -226,7 +226,6 @@ urlpatterns = [
|
|||||||
|
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
urlpatterns += [
|
urlpatterns += [
|
||||||
url(r'^workout/uploadd/$',views.workout_upload_view_debug),
|
|
||||||
url(r'^testreverse/$',views.test_reverse_view),
|
url(r'^testreverse/$',views.test_reverse_view),
|
||||||
url(r'^c2listug/$',views.c2listdebug_view),
|
url(r'^c2listug/$',views.c2listdebug_view),
|
||||||
]
|
]
|
||||||
|
|||||||
321
rowers/views.py
321
rowers/views.py
@@ -2678,7 +2678,7 @@ def workout_comparison_view(request,id1=0,id2=0,xparam='distance',yparam='spm'):
|
|||||||
'yparam':yparam,
|
'yparam':yparam,
|
||||||
})
|
})
|
||||||
|
|
||||||
# Updated version of comparison pliot
|
# Updated version of comparison plot
|
||||||
def workout_comparison_view2(request,id1=0,id2=0,xparam='distance',
|
def workout_comparison_view2(request,id1=0,id2=0,xparam='distance',
|
||||||
yparam='spm',plottype='line'):
|
yparam='spm',plottype='line'):
|
||||||
promember=0
|
promember=0
|
||||||
@@ -2945,6 +2945,7 @@ def workout_otwpowerplot_view(request,id=0,message="",successmessage=""):
|
|||||||
'the_div':div,
|
'the_div':div,
|
||||||
'mayedit':mayedit})
|
'mayedit':mayedit})
|
||||||
|
|
||||||
|
# the page where you can chose where to export this workout
|
||||||
@login_required()
|
@login_required()
|
||||||
def workout_export_view(request,id=0, message="", successmessage=""):
|
def workout_export_view(request,id=0, message="", successmessage=""):
|
||||||
request.session[translation.LANGUAGE_SESSION_KEY] = USER_LANGUAGE
|
request.session[translation.LANGUAGE_SESSION_KEY] = USER_LANGUAGE
|
||||||
@@ -2968,6 +2969,7 @@ def workout_export_view(request,id=0, message="", successmessage=""):
|
|||||||
'successmessage':successmessage,
|
'successmessage':successmessage,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# The basic edit page
|
||||||
@login_required()
|
@login_required()
|
||||||
def workout_edit_view(request,id=0,message="",successmessage=""):
|
def workout_edit_view(request,id=0,message="",successmessage=""):
|
||||||
request.session[translation.LANGUAGE_SESSION_KEY] = USER_LANGUAGE
|
request.session[translation.LANGUAGE_SESSION_KEY] = USER_LANGUAGE
|
||||||
@@ -3008,7 +3010,7 @@ def workout_edit_view(request,id=0,message="",successmessage=""):
|
|||||||
row.boattype = boattype
|
row.boattype = boattype
|
||||||
row.save()
|
row.save()
|
||||||
# change data in csv file
|
# change data in csv file
|
||||||
# startdatetime = dateutil.parser.parse("{}, {}".format(date,starttime))
|
|
||||||
r = rdata(row.csvfilename)
|
r = rdata(row.csvfilename)
|
||||||
if r == 0:
|
if r == 0:
|
||||||
return HttpResponse("Error: CSV Data File Not Found")
|
return HttpResponse("Error: CSV Data File Not Found")
|
||||||
@@ -3124,6 +3126,7 @@ def workout_edit_view(request,id=0,message="",successmessage=""):
|
|||||||
})
|
})
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
# Create the chart image with wind corrected pace (OTW)
|
||||||
@user_passes_test(promember,login_url="/",redirect_field_name=None)
|
@user_passes_test(promember,login_url="/",redirect_field_name=None)
|
||||||
def workout_add_otw_powerplot_view(request,id):
|
def workout_add_otw_powerplot_view(request,id):
|
||||||
w = Workout.objects.get(id=id)
|
w = Workout.objects.get(id=id)
|
||||||
@@ -3168,7 +3171,7 @@ def workout_add_otw_powerplot_view(request,id):
|
|||||||
url = "/rowers/workout/"+str(w.id)+"/edit"
|
url = "/rowers/workout/"+str(w.id)+"/edit"
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
# Create the Heart rate zone pie chart
|
||||||
@login_required()
|
@login_required()
|
||||||
def workout_add_piechart_view(request,id):
|
def workout_add_piechart_view(request,id):
|
||||||
w = Workout.objects.get(id=id)
|
w = Workout.objects.get(id=id)
|
||||||
@@ -3212,7 +3215,8 @@ def workout_add_piechart_view(request,id):
|
|||||||
|
|
||||||
url = "/rowers/workout/"+str(w.id)+"/edit"
|
url = "/rowers/workout/"+str(w.id)+"/edit"
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
# Create the Power zone pie chart
|
||||||
@login_required()
|
@login_required()
|
||||||
def workout_add_power_piechart_view(request,id):
|
def workout_add_power_piechart_view(request,id):
|
||||||
w = Workout.objects.get(id=id)
|
w = Workout.objects.get(id=id)
|
||||||
@@ -3248,15 +3252,14 @@ def workout_add_power_piechart_view(request,id):
|
|||||||
res = queue.enqueue(handle_makeplot,f1,w.csvfilename,
|
res = queue.enqueue(handle_makeplot,f1,w.csvfilename,
|
||||||
w.name,hrpwrdata,plotnr,imagename)
|
w.name,hrpwrdata,plotnr,imagename)
|
||||||
|
|
||||||
# i = GraphImage(workout=w,creationdatetime=datetime.datetime.now(),
|
|
||||||
# filename=fullpathimagename)
|
|
||||||
i = GraphImage(workout=w,creationdatetime=timezone.now(),
|
i = GraphImage(workout=w,creationdatetime=timezone.now(),
|
||||||
filename=fullpathimagename)
|
filename=fullpathimagename)
|
||||||
i.save()
|
i.save()
|
||||||
|
|
||||||
url = "/rowers/workout/"+str(w.id)+"/edit"
|
url = "/rowers/workout/"+str(w.id)+"/edit"
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
# Create the time based summary chart
|
||||||
@login_required()
|
@login_required()
|
||||||
def workout_add_timeplot_view(request,id):
|
def workout_add_timeplot_view(request,id):
|
||||||
w = Workout.objects.get(id=id)
|
w = Workout.objects.get(id=id)
|
||||||
@@ -3301,7 +3304,7 @@ def workout_add_timeplot_view(request,id):
|
|||||||
url = "/rowers/workout/"+str(w.id)+"/edit"
|
url = "/rowers/workout/"+str(w.id)+"/edit"
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
# Create the distance based summary chart
|
||||||
@login_required()
|
@login_required()
|
||||||
def workout_add_distanceplot_view(request,id):
|
def workout_add_distanceplot_view(request,id):
|
||||||
w = Workout.objects.get(id=id)
|
w = Workout.objects.get(id=id)
|
||||||
@@ -3339,13 +3342,12 @@ def workout_add_distanceplot_view(request,id):
|
|||||||
|
|
||||||
i = GraphImage(workout=w,creationdatetime=timezone.now(),
|
i = GraphImage(workout=w,creationdatetime=timezone.now(),
|
||||||
filename=fullpathimagename)
|
filename=fullpathimagename)
|
||||||
# i = GraphImage(workout=w,creationdatetime=datetime.datetime.now(),
|
|
||||||
# filename=fullpathimagename)
|
|
||||||
i.save()
|
i.save()
|
||||||
|
|
||||||
url = "/rowers/workout/"+str(w.id)+"/edit"
|
url = "/rowers/workout/"+str(w.id)+"/edit"
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
# Create the advanced parameters distance overview chart
|
||||||
@user_passes_test(promember,login_url="/",redirect_field_name=None)
|
@user_passes_test(promember,login_url="/",redirect_field_name=None)
|
||||||
def workout_add_distanceplot2_view(request,id):
|
def workout_add_distanceplot2_view(request,id):
|
||||||
w = Workout.objects.get(id=id)
|
w = Workout.objects.get(id=id)
|
||||||
@@ -3382,14 +3384,14 @@ def workout_add_distanceplot2_view(request,id):
|
|||||||
|
|
||||||
i = GraphImage(workout=w,creationdatetime=timezone.now(),
|
i = GraphImage(workout=w,creationdatetime=timezone.now(),
|
||||||
filename=fullpathimagename)
|
filename=fullpathimagename)
|
||||||
# i = GraphImage(workout=w,creationdatetime=datetime.datetime.now(),
|
|
||||||
# filename=fullpathimagename)
|
|
||||||
i.save()
|
i.save()
|
||||||
|
|
||||||
url = "/rowers/workout/"+str(w.id)+"/edit"
|
url = "/rowers/workout/"+str(w.id)+"/edit"
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
|
||||||
|
# Create the advanced parameters time based overview chart
|
||||||
@user_passes_test(promember,login_url="/",redirect_field_name=None)
|
@user_passes_test(promember,login_url="/",redirect_field_name=None)
|
||||||
def workout_add_timeplot2_view(request,id):
|
def workout_add_timeplot2_view(request,id):
|
||||||
w = Workout.objects.get(id=id)
|
w = Workout.objects.get(id=id)
|
||||||
@@ -3426,13 +3428,13 @@ def workout_add_timeplot2_view(request,id):
|
|||||||
|
|
||||||
i = GraphImage(workout=w,creationdatetime=timezone.now(),
|
i = GraphImage(workout=w,creationdatetime=timezone.now(),
|
||||||
filename=fullpathimagename)
|
filename=fullpathimagename)
|
||||||
# i = GraphImage(workout=w,creationdatetime=datetime.datetime.now(),
|
|
||||||
# filename=fullpathimagename)
|
|
||||||
i.save()
|
i.save()
|
||||||
|
|
||||||
url = "/rowers/workout/"+str(w.id)+"/edit"
|
url = "/rowers/workout/"+str(w.id)+"/edit"
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
# The page where you select which Strava workout to import
|
||||||
@login_required()
|
@login_required()
|
||||||
def workout_stravaimport_view(request,message=""):
|
def workout_stravaimport_view(request,message=""):
|
||||||
res = stravastuff.get_strava_workout_list(request.user)
|
res = stravastuff.get_strava_workout_list(request.user)
|
||||||
@@ -3461,6 +3463,7 @@ def workout_stravaimport_view(request,message=""):
|
|||||||
|
|
||||||
return HttpResponse(res)
|
return HttpResponse(res)
|
||||||
|
|
||||||
|
# The page where you select which SportTracks page to import
|
||||||
@login_required()
|
@login_required()
|
||||||
def workout_sporttracksimport_view(request,message=""):
|
def workout_sporttracksimport_view(request,message=""):
|
||||||
res = sporttracksstuff.get_sporttracks_workout_list(request.user)
|
res = sporttracksstuff.get_sporttracks_workout_list(request.user)
|
||||||
@@ -3499,6 +3502,7 @@ def workout_sporttracksimport_view(request,message=""):
|
|||||||
|
|
||||||
return HttpResponse(res)
|
return HttpResponse(res)
|
||||||
|
|
||||||
|
# List of workouts on Concept2 logbook. This view only used for debugging
|
||||||
@login_required()
|
@login_required()
|
||||||
def c2listdebug_view(request,message=""):
|
def c2listdebug_view(request,message=""):
|
||||||
try:
|
try:
|
||||||
@@ -3541,7 +3545,7 @@ def c2listdebug_view(request,message=""):
|
|||||||
{'workouts':workouts,
|
{'workouts':workouts,
|
||||||
'message':message})
|
'message':message})
|
||||||
|
|
||||||
|
# List of workouts available on Concept2 logbook - for import
|
||||||
@login_required()
|
@login_required()
|
||||||
def workout_c2import_view(request,message=""):
|
def workout_c2import_view(request,message=""):
|
||||||
try:
|
try:
|
||||||
@@ -3582,6 +3586,7 @@ def workout_c2import_view(request,message=""):
|
|||||||
{'workouts':workouts,
|
{'workouts':workouts,
|
||||||
'message':message})
|
'message':message})
|
||||||
|
|
||||||
|
# Import a workout from Strava
|
||||||
@login_required()
|
@login_required()
|
||||||
def workout_getstravaworkout_view(request,stravaid):
|
def workout_getstravaworkout_view(request,stravaid):
|
||||||
res = stravastuff.get_strava_workout(request.user,stravaid)
|
res = stravastuff.get_strava_workout(request.user,stravaid)
|
||||||
@@ -3595,6 +3600,7 @@ def workout_getstravaworkout_view(request,stravaid):
|
|||||||
url = "/rowers/workout/"+str(id)+"/edit"
|
url = "/rowers/workout/"+str(id)+"/edit"
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
# Imports a workout from SportTracks
|
||||||
@login_required()
|
@login_required()
|
||||||
def workout_getsporttracksworkout_view(request,sporttracksid):
|
def workout_getsporttracksworkout_view(request,sporttracksid):
|
||||||
res = sporttracksstuff.get_sporttracks_workout(request.user,sporttracksid)
|
res = sporttracksstuff.get_sporttracks_workout(request.user,sporttracksid)
|
||||||
@@ -3607,6 +3613,7 @@ def workout_getsporttracksworkout_view(request,sporttracksid):
|
|||||||
url = "/rowers/workout/"+str(id)+"/edit"
|
url = "/rowers/workout/"+str(id)+"/edit"
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
# Imports a workout from Concept2
|
||||||
@login_required()
|
@login_required()
|
||||||
def workout_getc2workout_view(request,c2id):
|
def workout_getc2workout_view(request,c2id):
|
||||||
try:
|
try:
|
||||||
@@ -3624,6 +3631,7 @@ def workout_getc2workout_view(request,c2id):
|
|||||||
if 'intervals' in data['workout']:
|
if 'intervals' in data['workout']:
|
||||||
splitdata = data['workout']['intervals']
|
splitdata = data['workout']['intervals']
|
||||||
|
|
||||||
|
# Check if workout has stroke data, and get the stroke data
|
||||||
if data['stroke_data']:
|
if data['stroke_data']:
|
||||||
res2 = c2stuff.get_c2_workout_strokes(request.user,c2id)
|
res2 = c2stuff.get_c2_workout_strokes(request.user,c2id)
|
||||||
else:
|
else:
|
||||||
@@ -3634,12 +3642,16 @@ def workout_getc2workout_view(request,c2id):
|
|||||||
})
|
})
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
# We have stroke data
|
||||||
if res2.status_code == 200:
|
if res2.status_code == 200:
|
||||||
strokedata = pd.DataFrame.from_dict(res2.json()['data'])
|
strokedata = pd.DataFrame.from_dict(res2.json()['data'])
|
||||||
|
# create the workout
|
||||||
id = add_workout_from_strokedata(request.user,c2id,data,strokedata,
|
id = add_workout_from_strokedata(request.user,c2id,data,strokedata,
|
||||||
source='c2')
|
source='c2')
|
||||||
w = Workout.objects.get(id=id)
|
w = Workout.objects.get(id=id)
|
||||||
w.uploadedtoc2=c2id
|
w.uploadedtoc2=c2id
|
||||||
|
# If we have split data, update the stroke data so they
|
||||||
|
# match exactly (some users are anal about this)
|
||||||
if splitdata:
|
if splitdata:
|
||||||
try:
|
try:
|
||||||
w.summary,sa,results = c2stuff.summaryfromsplitdata(splitdata,data,w.csvfilename)
|
w.summary,sa,results = c2stuff.summaryfromsplitdata(splitdata,data,w.csvfilename)
|
||||||
@@ -3655,7 +3667,7 @@ def workout_getc2workout_view(request,c2id):
|
|||||||
w.save()
|
w.save()
|
||||||
|
|
||||||
from rowingdata.trainingparser import getlist
|
from rowingdata.trainingparser import getlist
|
||||||
# set stroke data
|
# set stroke data in CSV file
|
||||||
if sa:
|
if sa:
|
||||||
values = getlist(sa)
|
values = getlist(sa)
|
||||||
units = getlist(sa,sel='unit')
|
units = getlist(sa,sel='unit')
|
||||||
@@ -3697,7 +3709,7 @@ def workout_getc2workout_view(request,c2id):
|
|||||||
})
|
})
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
# This is the main view for processing uploaded files
|
||||||
@login_required()
|
@login_required()
|
||||||
def workout_upload_view(request,message=""):
|
def workout_upload_view(request,message=""):
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
@@ -3707,7 +3719,6 @@ def workout_upload_view(request,message=""):
|
|||||||
f = request.FILES['file']
|
f = request.FILES['file']
|
||||||
res = handle_uploaded_file(f)
|
res = handle_uploaded_file(f)
|
||||||
t = form.cleaned_data['title']
|
t = form.cleaned_data['title']
|
||||||
# fileformat = form.cleaned_data['fileformat']
|
|
||||||
workouttype = form.cleaned_data['workouttype']
|
workouttype = form.cleaned_data['workouttype']
|
||||||
|
|
||||||
notes = form.cleaned_data['notes']
|
notes = form.cleaned_data['notes']
|
||||||
@@ -3719,15 +3730,18 @@ def workout_upload_view(request,message=""):
|
|||||||
f1 = res[0] # file name
|
f1 = res[0] # file name
|
||||||
f2 = res[1] # file name incl media directory
|
f2 = res[1] # file name incl media directory
|
||||||
|
|
||||||
# new
|
# get file type (ErgData, NK, BoatCoach, etc
|
||||||
fileformat = get_file_type(f2)
|
fileformat = get_file_type(f2)
|
||||||
if len(fileformat)==3 and fileformat[0]=='zip':
|
if len(fileformat)==3 and fileformat[0]=='zip':
|
||||||
f_to_be_deleted = f2
|
f_to_be_deleted = f2
|
||||||
with zipfile.ZipFile(f2) as z:
|
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/')
|
f2 = z.extract(z.namelist()[0],path='media/')
|
||||||
fileformat = fileformat[2]
|
fileformat = fileformat[2]
|
||||||
os.remove(f_to_be_deleted)
|
os.remove(f_to_be_deleted)
|
||||||
|
|
||||||
|
# Some people try to upload Concept2 logbook summaries
|
||||||
if fileformat == 'c2log':
|
if fileformat == 'c2log':
|
||||||
message = "This C2 logbook summary does not contain stroke data. Please download the Export Stroke Data file from the workout details on the C2 logbook."
|
message = "This C2 logbook summary does not contain stroke data. Please download the Export Stroke Data file from the workout details on the C2 logbook."
|
||||||
url = reverse(workout_upload_view,
|
url = reverse(workout_upload_view,
|
||||||
@@ -3735,13 +3749,18 @@ def workout_upload_view(request,message=""):
|
|||||||
response = HttpResponseRedirect(url)
|
response = HttpResponseRedirect(url)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
# Some people try to upload RowPro summary logs
|
||||||
if fileformat == 'rowprolog':
|
if fileformat == 'rowprolog':
|
||||||
message = "This RowPro logbook summary does not contain stroke data. Please use the Stroke Data CSV file for the individual workout in your log."
|
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,
|
url = reverse(workout_upload_view,
|
||||||
args=[str(message)])
|
args=[str(message)])
|
||||||
response = HttpResponseRedirect(url)
|
response = HttpResponseRedirect(url)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
# 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':
|
if fileformat == 'unknown':
|
||||||
message = "We couldn't recognize the file type"
|
message = "We couldn't recognize the file type"
|
||||||
url = reverse(workout_upload_view,
|
url = reverse(workout_upload_view,
|
||||||
@@ -3758,7 +3777,8 @@ def workout_upload_view(request,message=""):
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
summary = ''
|
summary = ''
|
||||||
# handle non-Painsled
|
# handle non-Painsled by converting it to painsled
|
||||||
|
# compatible CSV
|
||||||
try:
|
try:
|
||||||
if (fileformat != 'csv'):
|
if (fileformat != 'csv'):
|
||||||
# handle RowPro:
|
# handle RowPro:
|
||||||
@@ -3811,23 +3831,25 @@ def workout_upload_view(request,message=""):
|
|||||||
# handle FIT
|
# handle FIT
|
||||||
if (fileformat == 'fit'):
|
if (fileformat == 'fit'):
|
||||||
row = FITParser(f2)
|
row = FITParser(f2)
|
||||||
|
# The FIT files have nice lap/split summaries
|
||||||
|
# so we make use of it
|
||||||
s = fitsummarydata(f2)
|
s = fitsummarydata(f2)
|
||||||
s.setsummary()
|
s.setsummary()
|
||||||
summary = s.summarytext
|
summary = s.summarytext
|
||||||
|
|
||||||
|
# Save the Painsled compatible CSV file and delete
|
||||||
|
# the uploaded file
|
||||||
f_to_be_deleted = f2
|
f_to_be_deleted = f2
|
||||||
# should delete file
|
# should delete file
|
||||||
f2 = f2[:-4]+'o.csv'
|
f2 = f2[:-4]+'o.csv'
|
||||||
row.write_csv(f2,gzip=True)
|
row.write_csv(f2,gzip=True)
|
||||||
|
|
||||||
#os.remove(f2)
|
|
||||||
try:
|
try:
|
||||||
os.remove(f_to_be_deleted)
|
os.remove(f_to_be_deleted)
|
||||||
except:
|
except:
|
||||||
os.remove(f_to_be_deleted+'.gz')
|
os.remove(f_to_be_deleted+'.gz')
|
||||||
|
|
||||||
# make workout and put in database
|
# make Workout object and put in database
|
||||||
r = Rower.objects.get(user=request.user)
|
r = Rower.objects.get(user=request.user)
|
||||||
rr = rrower(hrmax=r.max,hrut2=r.ut2,
|
rr = rrower(hrmax=r.max,hrut2=r.ut2,
|
||||||
hrut1=r.ut1,hrat=r.at,
|
hrut1=r.ut1,hrat=r.at,
|
||||||
@@ -3870,7 +3892,6 @@ def workout_upload_view(request,message=""):
|
|||||||
if workouttype == 'rower' or workouttype == 'dynamic' or workouttype == 'slides':
|
if workouttype == 'rower' or workouttype == 'dynamic' or workouttype == 'slides':
|
||||||
try:
|
try:
|
||||||
row.erg_recalculatepower()
|
row.erg_recalculatepower()
|
||||||
# row.spm_fromtimestamps()
|
|
||||||
row.write_csv(f2,gzip=True)
|
row.write_csv(f2,gzip=True)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
@@ -3917,8 +3938,11 @@ def workout_upload_view(request,message=""):
|
|||||||
startdatetime=workoutstartdatetime)
|
startdatetime=workoutstartdatetime)
|
||||||
|
|
||||||
w.save()
|
w.save()
|
||||||
|
|
||||||
# put stroke data in database
|
# put stroke data in database
|
||||||
res = dataprep.dataprep(row.df,id=w.id,bands=True,barchart=True,otwpower=True,empower=True)
|
res = dataprep.dataprep(row.df,id=w.id,
|
||||||
|
bands=True,barchart=True,
|
||||||
|
otwpower=True,empower=True)
|
||||||
|
|
||||||
# Make Plot
|
# Make Plot
|
||||||
if (make_plot):
|
if (make_plot):
|
||||||
@@ -3946,8 +3970,6 @@ def workout_upload_view(request,message=""):
|
|||||||
plotnr = plotnr+3
|
plotnr = plotnr+3
|
||||||
|
|
||||||
|
|
||||||
# res = handle_makeplot.delay(f1,f2,t,
|
|
||||||
# hrpwrdata,plotnr,imagename)
|
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
res = handle_makeplot.delay(f1,f2,t,
|
res = handle_makeplot.delay(f1,f2,t,
|
||||||
hrpwrdata,plotnr,
|
hrpwrdata,plotnr,
|
||||||
@@ -3961,9 +3983,6 @@ def workout_upload_view(request,message=""):
|
|||||||
i = GraphImage(workout=w,
|
i = GraphImage(workout=w,
|
||||||
creationdatetime=timezone.now(),
|
creationdatetime=timezone.now(),
|
||||||
filename=fullpathimagename)
|
filename=fullpathimagename)
|
||||||
# i = GraphImage(workout=w,
|
|
||||||
# creationdatetime=datetime.datetime.now(),
|
|
||||||
# filename=fullpathimagename)
|
|
||||||
i.save()
|
i.save()
|
||||||
|
|
||||||
# upload to C2
|
# upload to C2
|
||||||
@@ -4037,216 +4056,8 @@ def workout_upload_view(request,message=""):
|
|||||||
'message':message})
|
'message':message})
|
||||||
|
|
||||||
|
|
||||||
@login_required()
|
|
||||||
def workout_upload_view_debug(request,message=""):
|
|
||||||
if request.method == 'POST':
|
|
||||||
form = DocumentsForm(request.POST,request.FILES)
|
|
||||||
optionsform = UploadOptionsForm(request.POST)
|
|
||||||
if form.is_valid():
|
|
||||||
f = request.FILES['file']
|
|
||||||
res = handle_uploaded_file(f)
|
|
||||||
t = form.cleaned_data['title']
|
|
||||||
fileformat = form.cleaned_data['fileformat']
|
|
||||||
workouttype = form.cleaned_data['workouttype']
|
|
||||||
notes = form.cleaned_data['notes']
|
|
||||||
make_plot = request.POST.getlist('make_plot')
|
|
||||||
plottype = request.POST['plottype']
|
|
||||||
upload_to_c2 = request.POST.getlist('upload_to_C2')
|
|
||||||
|
|
||||||
|
|
||||||
f1 = res[0] # file name
|
|
||||||
f2 = res[1] # file name incl media directory
|
|
||||||
|
|
||||||
|
|
||||||
# handle non-Painsled
|
|
||||||
if (fileformat != 'csv'):
|
|
||||||
# handle RowPro:
|
|
||||||
if (fileformat == 'rp'):
|
|
||||||
row = RowProParser(f2)
|
|
||||||
|
|
||||||
# handle TCX
|
|
||||||
if (fileformat == 'tcx'):
|
|
||||||
row = TCXParser(f2)
|
|
||||||
|
|
||||||
# handle TCX no HR
|
|
||||||
if (fileformat == 'tcxnohr'):
|
|
||||||
row = TCXParserNoHR(f2)
|
|
||||||
|
|
||||||
# handle ErgData
|
|
||||||
if (fileformat == 'ergdata'):
|
|
||||||
row = ErgDataParser(f2)
|
|
||||||
|
|
||||||
# handle BoatCoach
|
|
||||||
if (fileformat == 'boatcoach'):
|
|
||||||
row = BoatCoachParser(f2)
|
|
||||||
|
|
||||||
|
|
||||||
# handle painsled desktop
|
|
||||||
if (fileformat == 'painsleddesktop'):
|
|
||||||
row = painsledDesktopParser(f2)
|
|
||||||
|
|
||||||
# handle speed coach
|
|
||||||
if (fileformat == 'speedcoach'):
|
|
||||||
row = speedcoachParser(f2)
|
|
||||||
|
|
||||||
# handle ErgStick
|
|
||||||
if (fileformat == 'ergstick'):
|
|
||||||
row = ErgStickParser(f2)
|
|
||||||
|
|
||||||
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')
|
|
||||||
# remove uncompressed
|
|
||||||
|
|
||||||
# make workout and put in database
|
|
||||||
r = Rower.objects.get(user=request.user)
|
|
||||||
rr = rrower(hrmax=r.max,hrut2=r.ut2,
|
|
||||||
hrut1=r.ut1,hrat=r.at,
|
|
||||||
hrtr=r.tr,hran=r.an,ftp=r.ftp)
|
|
||||||
row = rdata(f2,rower=rr)
|
|
||||||
|
|
||||||
if row == 0:
|
|
||||||
return HttpResponse("Error: CSV Data File Not Found")
|
|
||||||
row.write_csv(f2,gzip=True)
|
|
||||||
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))
|
|
||||||
|
|
||||||
summary = row.summary()
|
|
||||||
summary += '\n'
|
|
||||||
summary += row.intervalstats()
|
|
||||||
|
|
||||||
duration = "%s:%s:%s.%s" % (hours,minutes,seconds,tenths)
|
|
||||||
|
|
||||||
|
|
||||||
workoutdate = row.rowdatetime.strftime('%Y-%m-%d')
|
|
||||||
workoutstarttime = row.rowdatetime.strftime('%H:%M:%S')
|
|
||||||
|
|
||||||
# check for duplicate start times
|
|
||||||
r = Rower.objects.get(user=request.user)
|
|
||||||
|
|
||||||
ws = Workout.objects.filter(starttime=workoutstarttime,
|
|
||||||
user=r)
|
|
||||||
if (len(ws) != 0):
|
|
||||||
print "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,
|
|
||||||
averagehr=averagehr,maxhr=maxhr)
|
|
||||||
|
|
||||||
w.save()
|
|
||||||
|
|
||||||
# Make Plot
|
|
||||||
if (make_plot):
|
|
||||||
imagename = f1[:-4]+'.png'
|
|
||||||
fullpathimagename = 'static/plots/'+imagename
|
|
||||||
u = request.user
|
|
||||||
hrpwrdata = {
|
|
||||||
'hrmax':r.max,
|
|
||||||
'hrut2':r.ut2,
|
|
||||||
'hrut1':r.ut1,
|
|
||||||
'hrat':r.at,
|
|
||||||
'hrtr':r.tr,
|
|
||||||
'hran':r.an,
|
|
||||||
}
|
|
||||||
|
|
||||||
# make plot - asynchronous task
|
|
||||||
plotnrs = {
|
|
||||||
'timeplot':1,
|
|
||||||
'distanceplot':2,
|
|
||||||
'pieplot':3,
|
|
||||||
}
|
|
||||||
|
|
||||||
plotnr = plotnrs[plottype]
|
|
||||||
if (workouttype=='water'):
|
|
||||||
plotnr = plotnr+3
|
|
||||||
|
|
||||||
|
|
||||||
# res = handle_makeplot.delay(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.save()
|
|
||||||
|
|
||||||
# upload to C2
|
|
||||||
if (upload_to_c2):
|
|
||||||
try:
|
|
||||||
thetoken = c2_open(request.user)
|
|
||||||
except C2NoTokenError:
|
|
||||||
return HttpResponseRedirect("/rowers/me/c2authorize/")
|
|
||||||
|
|
||||||
try:
|
|
||||||
response = c2stuff.workout_c2_upload(request.user,w)
|
|
||||||
if (response.status_code != 201):
|
|
||||||
if settings.DEBUG:
|
|
||||||
return HttpResponse(response)
|
|
||||||
else:
|
|
||||||
message = "C2 upload failed"
|
|
||||||
url = reverse(workout_edit_view,
|
|
||||||
kwargs={
|
|
||||||
'message':message,
|
|
||||||
'id':str(w.id),
|
|
||||||
})
|
|
||||||
return HttpResponseRedirect(url)
|
|
||||||
except:
|
|
||||||
message = "C2 upload failed"
|
|
||||||
url = reverse(workout_edit_view,
|
|
||||||
kwargs={
|
|
||||||
'message':message,
|
|
||||||
'id':str(w.id),
|
|
||||||
})
|
|
||||||
return HttpResponseRedirect(url)
|
|
||||||
|
|
||||||
# redirect to workout edit page
|
|
||||||
url = "/rowers/workout/"+str(w.id)+"/edit"
|
|
||||||
return HttpResponseRedirect(url)
|
|
||||||
|
|
||||||
else:
|
|
||||||
response = render(request,
|
|
||||||
'document_form.html',
|
|
||||||
{'form':form,
|
|
||||||
'optionsform': optionsform,
|
|
||||||
'message':message})
|
|
||||||
|
|
||||||
return response
|
|
||||||
else:
|
|
||||||
form = DocumentsForm()
|
|
||||||
optionsform = UploadOptionsForm()
|
|
||||||
return render(request, 'document_form.html',
|
|
||||||
{'form':form,
|
|
||||||
'optionsform': optionsform,
|
|
||||||
'message':message})
|
|
||||||
|
|
||||||
|
|
||||||
|
# Ask the user if he really wants to delete the workout
|
||||||
@login_required()
|
@login_required()
|
||||||
def workout_delete_confirm_view(request, id=0):
|
def workout_delete_confirm_view(request, id=0):
|
||||||
try:
|
try:
|
||||||
@@ -4261,6 +4072,7 @@ def workout_delete_confirm_view(request, id=0):
|
|||||||
except Workout.DoesNotExist:
|
except Workout.DoesNotExist:
|
||||||
return HttpResponseNotFound("Workout doesn't exist")
|
return HttpResponseNotFound("Workout doesn't exist")
|
||||||
|
|
||||||
|
# Really deleting the workout
|
||||||
@login_required()
|
@login_required()
|
||||||
def workout_delete_view(request,id=0):
|
def workout_delete_view(request,id=0):
|
||||||
try:
|
try:
|
||||||
@@ -4280,7 +4092,7 @@ def workout_delete_view(request,id=0):
|
|||||||
except Workout.DoesNotExist:
|
except Workout.DoesNotExist:
|
||||||
return HttpResponseNotFound("Workout doesn't exist")
|
return HttpResponseNotFound("Workout doesn't exist")
|
||||||
|
|
||||||
|
# Ask the user to confirm that he wants to delete a chart
|
||||||
@login_required()
|
@login_required()
|
||||||
def graph_delete_confirm_view(request, id=0):
|
def graph_delete_confirm_view(request, id=0):
|
||||||
try:
|
try:
|
||||||
@@ -4296,6 +4108,7 @@ def graph_delete_confirm_view(request, id=0):
|
|||||||
except Workout.DoesNotExist:
|
except Workout.DoesNotExist:
|
||||||
return HttpResponseNotFound("Workout doesn't exist")
|
return HttpResponseNotFound("Workout doesn't exist")
|
||||||
|
|
||||||
|
# Really deleting the chart
|
||||||
@login_required()
|
@login_required()
|
||||||
def graph_delete_view(request,id=0):
|
def graph_delete_view(request,id=0):
|
||||||
try:
|
try:
|
||||||
@@ -4317,7 +4130,7 @@ def graph_delete_view(request,id=0):
|
|||||||
return HttpResponse("Graph Image doesn't exist")
|
return HttpResponse("Graph Image doesn't exist")
|
||||||
|
|
||||||
|
|
||||||
|
# A page with all the recent graphs (searchable on workout name)
|
||||||
@login_required()
|
@login_required()
|
||||||
def graphs_view(request):
|
def graphs_view(request):
|
||||||
try:
|
try:
|
||||||
@@ -4344,7 +4157,7 @@ def graphs_view(request):
|
|||||||
except Rower.DoesNotExist:
|
except Rower.DoesNotExist:
|
||||||
return HttpResponse("User has no rower instance")
|
return HttpResponse("User has no rower instance")
|
||||||
|
|
||||||
|
# Show the chart (png image)
|
||||||
def graph_show_view(request,id):
|
def graph_show_view(request,id):
|
||||||
try:
|
try:
|
||||||
g = GraphImage.objects.get(id=id)
|
g = GraphImage.objects.get(id=id)
|
||||||
@@ -4359,6 +4172,7 @@ def graph_show_view(request,id):
|
|||||||
except GraphImage.DoesNotExist:
|
except GraphImage.DoesNotExist:
|
||||||
return HttpResponse("This graph doesn't exist")
|
return HttpResponse("This graph doesn't exist")
|
||||||
|
|
||||||
|
# Restore original stroke data and summary
|
||||||
@login_required()
|
@login_required()
|
||||||
def workout_summary_restore_view(request,id,message="",successmessage=""):
|
def workout_summary_restore_view(request,id,message="",successmessage=""):
|
||||||
try:
|
try:
|
||||||
@@ -4406,7 +4220,7 @@ def workout_summary_restore_view(request,id,message="",successmessage=""):
|
|||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
|
||||||
|
# Edit the splits/summary
|
||||||
@login_required()
|
@login_required()
|
||||||
def workout_summary_edit_view(request,id,message="",successmessage=""
|
def workout_summary_edit_view(request,id,message="",successmessage=""
|
||||||
):
|
):
|
||||||
@@ -4594,7 +4408,7 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
|
|||||||
'savebutton':savebutton,
|
'savebutton':savebutton,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# Page where user can manage his favorite charts
|
||||||
@user_passes_test(promember,login_url="/rowers/me/edit",redirect_field_name=None)
|
@user_passes_test(promember,login_url="/rowers/me/edit",redirect_field_name=None)
|
||||||
def rower_favoritecharts_view(request):
|
def rower_favoritecharts_view(request):
|
||||||
message = ''
|
message = ''
|
||||||
@@ -4658,6 +4472,8 @@ def rower_favoritecharts_view(request):
|
|||||||
|
|
||||||
return render(request,'favoritecharts.html',context)
|
return render(request,'favoritecharts.html',context)
|
||||||
|
|
||||||
|
# Page where user can set his details
|
||||||
|
# Add email address to form so user can change his email address
|
||||||
@login_required()
|
@login_required()
|
||||||
def rower_edit_view(request,message=""):
|
def rower_edit_view(request,message=""):
|
||||||
if request.method == 'POST' and "ut2" in request.POST:
|
if request.method == 'POST' and "ut2" in request.POST:
|
||||||
@@ -4740,6 +4556,9 @@ def rower_edit_view(request,message=""):
|
|||||||
except Rower.DoesNotExist:
|
except Rower.DoesNotExist:
|
||||||
return HttpResponse("This user doesn't exist")
|
return HttpResponse("This user doesn't exist")
|
||||||
|
|
||||||
|
# Revoke an app that you granted access through the API.
|
||||||
|
# this views is called when you press a button on the User edit page
|
||||||
|
# the button is only there when you have granted access to an app
|
||||||
@login_required()
|
@login_required()
|
||||||
def rower_revokeapp_view(request,id=0):
|
def rower_revokeapp_view(request,id=0):
|
||||||
tokens = AccessToken.objects.filter(user=request.user,application=id)
|
tokens = AccessToken.objects.filter(user=request.user,application=id)
|
||||||
@@ -4761,18 +4580,21 @@ def rower_revokeapp_view(request,id=0):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
# Utility to get stroke data in a JSON response
|
||||||
class JSONResponse(HttpResponse):
|
class JSONResponse(HttpResponse):
|
||||||
def __init__(self, data, **kwargs):
|
def __init__(self, data, **kwargs):
|
||||||
content = JSONRenderer().render(data)
|
content = JSONRenderer().render(data)
|
||||||
kwargs['content_type'] = 'application/json'
|
kwargs['content_type'] = 'application/json'
|
||||||
super(JSONResponse, self).__init__(content, **kwargs)
|
super(JSONResponse, self).__init__(content, **kwargs)
|
||||||
|
|
||||||
|
# Creates unix time stamp from a datetime object
|
||||||
def totimestamp(dt, epoch=datetime.datetime(1970,1,1,tzinfo=tz('UTC'))):
|
def totimestamp(dt, epoch=datetime.datetime(1970,1,1,tzinfo=tz('UTC'))):
|
||||||
td = dt - epoch
|
td = dt - epoch
|
||||||
# return td.total_seconds()
|
# return td.total_seconds()
|
||||||
return (td.microseconds + (td.seconds + td.days * 86400) * 10**6) / 10**6
|
return (td.microseconds + (td.seconds + td.days * 86400) * 10**6) / 10**6
|
||||||
|
# Check if a column of a dataframe has the required (aantal)
|
||||||
|
# number of elements. Also checks if the column is a numerical type
|
||||||
|
# Replaces any faulty columns with zeros
|
||||||
def trydf(df,aantal,column):
|
def trydf(df,aantal,column):
|
||||||
try:
|
try:
|
||||||
s = df[column]
|
s = df[column]
|
||||||
@@ -4785,6 +4607,7 @@ def trydf(df,aantal,column):
|
|||||||
|
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
# Stroke data form to test API upload
|
||||||
@login_required()
|
@login_required()
|
||||||
def strokedataform(request,id=0):
|
def strokedataform(request,id=0):
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
@@ -4803,7 +4626,8 @@ def strokedataform(request,id=0):
|
|||||||
'id':id,
|
'id':id,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# Process the POSTed stroke data according to the API definition
|
||||||
|
# Return the GET stroke data according to the API definition
|
||||||
from rest_framework_swagger.renderers import OpenAPIRenderer, SwaggerUIRenderer
|
from rest_framework_swagger.renderers import OpenAPIRenderer, SwaggerUIRenderer
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
@@ -4827,6 +4651,7 @@ def strokedatajson(request,id):
|
|||||||
|
|
||||||
|
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
|
# currently only returns a subset.
|
||||||
columns = ['spm','time','hr','pace','power','distance']
|
columns = ['spm','time','hr','pace','power','distance']
|
||||||
datadf = dataprep.getsmallrowdata_db(columns,ids=[id])
|
datadf = dataprep.getsmallrowdata_db(columns,ids=[id])
|
||||||
return JSONResponse(datadf)
|
return JSONResponse(datadf)
|
||||||
|
|||||||
Reference in New Issue
Block a user