diff --git a/rowers/templates/workout_form.html b/rowers/templates/workout_form.html index 27965b5e..fcae276d 100644 --- a/rowers/templates/workout_form.html +++ b/rowers/templates/workout_form.html @@ -8,34 +8,40 @@ {% block content %}
- {% if form.errors %} -

- Please correct the error{{ form.errors|pluralize }} below. -

- {% endif %} - -

Edit Workout Data

-
-
-

- Delete -

-
-
-

- Export - -

-
-
-

- Advanced -

- Advanced Functionality (More interactive Charts) - -
-
+ {% if form.errors %} +

+ Please correct the error{{ form.errors|pluralize }} below. +

+ {% endif %} +

Edit Workout Data

+
+
+

+ Delete +

+
+
+

+ Export + +

+
+
+

+ Advanced +

+ Advanced Functionality (More interactive Charts) + +
+
+
+
+

+ Statistics +

+
+
{% localtime on %} diff --git a/rowers/templates/workoutstats.html b/rowers/templates/workoutstats.html new file mode 100644 index 00000000..360c0071 --- /dev/null +++ b/rowers/templates/workoutstats.html @@ -0,0 +1,127 @@ +{% extends "base.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block title %}Workout Statistics{% endblock %} + +{% block content %} +
+

Workout Statistics

+
+

+ Edit Workout +

+
+
+

+ Export +

+ +
+
+

+ Advanced +

+
+
+
+ {% csrf_token %} + {% if workstrokesonly == True %} + + + {% else %} + + + {% endif %} + + If your data source allows, this will show or hide strokes taken during rest intervals. +
+
+
+

Stroke Rate

+
+ + + + + + + + + + + + + + + + + + + + + + + +
MetricValue
Mean{{ stats.spm.mean|floatformat:-2 }}
Minimum{{ stats.spm.min|floatformat:-2 }}
25%{{ stats.spm.firstq|floatformat:-2 }}
Median{{ stats.spm.median|floatformat:-2 }}
75%{{ stats.spm.thirdq|floatformat:-2 }}
Maximum{{ stats.spm.max|floatformat:-2 }}
Standard Deviation{{ stats.spm.std|floatformat:-2 }}
+
+
+

Heart Rate

+ + + + + + + + + + + + + + + + + + + + + + + + +
MetricValue
Mean{{ stats.hr.mean|floatformat:-2 }}
Minimum{{ stats.hr.min|floatformat:-2 }}
25%{{ stats.hr.firstq|floatformat:-2 }}
Median{{ stats.hr.median|floatformat:-2 }}
75%{{ stats.hr.thirdq|floatformat:-2 }}
Maximum{{ stats.hr.max|floatformat:-2 }}
Standard Deviation{{ stats.hr.std|floatformat:-2 }}
+
+
+
+

Power

+ + + + + + + + + + + + + + + + + + + + + + + + +
MetricValue
Mean{{ stats.power.mean|floatformat:-2 }}
Minimum{{ stats.power.min|floatformat:-2 }}
25%{{ stats.power.firstq|floatformat:-2 }}
Median{{ stats.power.median|floatformat:-2 }}
75%{{ stats.power.thirdq|floatformat:-2 }}
Maximum{{ stats.power.max|floatformat:-2 }}
Standard Deviation{{ stats.power.std|floatformat:-2 }}
+
+
+ +{% endblock %} diff --git a/rowers/urls.py b/rowers/urls.py index 13ba7bb3..c493656a 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -154,6 +154,7 @@ urlpatterns = [ url(r'^workout/(?P\d+)/advanced/s/(?P.+.*)$',views.workout_advanced_view), url(r'^workout/(?P\d+)/geeky$',views.workout_geeky_view), url(r'^workout/(\d+)/advanced$',views.workout_advanced_view), + url(r'^workout/(\d+)/stats$',views.workout_stats_view), url(r'^workout/(\d+)/otwsetpower$',views.workout_otwsetpower_view), url(r'^workout/(\d+)/interactiveotwplot$',views.workout_otwpowerplot_view), url(r'^workout/(\d+)/wind$',views.workout_wind_view), diff --git a/rowers/views.py b/rowers/views.py index 76674819..6cf816ea 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -2604,6 +2604,84 @@ def workout_geeky_view(request,id=0,message="",successmessage=""): 'interactiveplot':script, 'the_div':div}) +# Stats page +@login_required() +def workout_stats_view(request,id=0,message="",successmessage=""): + workstrokesonly = True + if request.method == 'POST' and 'workstrokesonly' in request.POST: + workstrokesonly = request.POST['workstrokesonly'] + + row = Workout.objects.get(id=id) + if (checkworkoutuser(request.user,row)==False): + message = "You are not allowed to see the stats of this workout" + url = reverse(workouts_view,args=[str(message)]) + return HttpResponseRedirect(url) + + columns = ['hr','spm','power','workoutstate'] + datadf = dataprep.getsmallrowdata_db(columns,ids=[id]) + + if datadf.empty: + return HttpResponse("CSV data file not found") + + workoutstateswork = [1,4,5,8,9,6,7] + workoutstatesrest = [3] + workoutstatetransition = [0,2,10,11,12,13] + + if workstrokesonly=='True' or workstrokesonly==True: + try: + datadf = datadf[~datadf['workoutstate'].isin(workoutstatesrest)] + except: + pass + workstrokesonly = True + + stats = {} + # SPM + spmdict = { + 'mean':datadf['spm'].mean(), + 'max': datadf['spm'].max(), + 'min': datadf['spm'].min(), + 'std': datadf['spm'].std(), + 'median': datadf['spm'].median(), + 'firstq':datadf['spm'].quantile(q=0.25), + 'thirdq':datadf['spm'].quantile(q=0.75), + } + + stats['spm'] = spmdict + + # HR + hrdict = { + 'mean':datadf['hr'].mean(), + 'max': datadf['hr'].max(), + 'min': datadf['hr'].min(), + 'std': datadf['hr'].std(), + 'median': datadf['hr'].median(), + 'firstq':datadf['hr'].quantile(q=0.25), + 'thirdq':datadf['hr'].quantile(q=0.75), + } + + stats['hr'] = hrdict + + # Power + powerdict = { + 'mean':datadf['power'].mean(), + 'max': datadf['power'].max(), + 'min': datadf['power'].min(), + 'std': datadf['power'].std(), + 'median': datadf['power'].median(), + 'firstq':datadf['power'].quantile(q=0.25), + 'thirdq':datadf['power'].quantile(q=0.75), + } + + stats['power'] = powerdict + + return render(request, + 'workoutstats.html', + { + 'stats':stats, + 'workout':row, + 'workstrokesonly':workstrokesonly, + }) + # The Advanced edit page @login_required() def workout_advanced_view(request,id=0,message="",successmessage=""):