From 634e191d6529eafbbebf222613d2b57a108a05e3 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Mon, 11 Jun 2018 15:26:14 +0200 Subject: [PATCH 1/3] form in place, not working yet --- rowers/forms.py | 14 ++ rowers/templates/summary_edit.html | 358 +++++++++++++++-------------- rowers/views.py | 30 ++- 3 files changed, 231 insertions(+), 171 deletions(-) diff --git a/rowers/forms.py b/rowers/forms.py index bd7c7ae1..d90372d4 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -481,6 +481,20 @@ class MyTimeField(forms.TimeField): super(MyTimeField, self).__init__(*args, **kwargs) supports_microseconds = True +# Form used to automatically define intervals by pace or power +class PowerIntervalUpdateForm(forms.Form): + selectorchoices = ( + ('power','Power'), + ('pace','Pace') + ) + + pace = forms.DurationField(label='Pace',required=False) + power = forms.IntegerField(label='Power',required=False) + selector = forms.ChoiceField(choices=selectorchoices, + required=True, + initial='power', + label='Use') + # Form used to update interval stats class IntervalUpdateForm(forms.Form): diff --git a/rowers/templates/summary_edit.html b/rowers/templates/summary_edit.html index 08322e00..59510b18 100644 --- a/rowers/templates/summary_edit.html +++ b/rowers/templates/summary_edit.html @@ -8,200 +8,220 @@ {% block content %}
- {% if form.errors %} -

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

- {% endif %} + {% if form.errors %} +

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

+ {% endif %} -

Edit Workout Interval Data

-
-
-

- Edit -

-
-
-

- Workflow View +

Edit Workout Interval Data

+
+
+

+ Edit +

+
+
+

+ Workflow View -

-
-
-

- Advanced -

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

+
+
+

+ Advanced +

+ Advanced Functionality (More interactive Charts) + +
+
+ - -{% localtime on %} - - - - - - - - - - +
Date/Time:{{ workout.startdatetime }}
Distance:{{ workout.distance }}m
Duration:{{ workout.duration |durationprint:"%H:%M:%S.%f" }}
Public link to this workout + {% localtime on %} + + + + + + + + + + - - + + -
Date/Time:{{ workout.startdatetime }}
Distance:{{ workout.distance }}m
Duration:{{ workout.duration |durationprint:"%H:%M:%S.%f" }}
Public link to this workout https://rowsandall.com/rowers/workout/{{ workout.id }} - -
Public link to interactive chart + +
Public link to interactive chart https://rowsandall.com/rowers/workout/{{ workout.id }}/interactiveplot - -
-{% endlocaltime %} -

Interval Translator

-

This is a quick way to enter the intervals using a special mini-language.

-

You enter something like 8x500m/3min, press "Update" and the site will interpret this for you and update the summary on the right. If you're happy with the result, press the green Save button to update the values. Nothing will be changed permanently until you hit Save.

+
+
+ {% endlocaltime %} +

Interval Translator

+

This is a quick way to enter the intervals using a special mini-language.

+

You enter something like 8x500m/3min, press "Update" and the site will interpret this for you and update the summary on the right. If you're happy with the result, press the green Save button to update the values. Nothing will be changed permanently until you hit Save.

+ +

Special characters are x (times), + and / (denotes a rest interval), as well as ( and ). Units are min (minutes), sec (seconds), m (meters) and km (km).

+ +

A typical interval is described as "10min/5min", with the work part before the "/" and the rest part after it. A zero rest can be omitted, so a single 1000m piece could be described either as "1km" or "1000m". The basic units can be combined with "+" and "Nx". You can use parentheses as in the example below.

+ +

Here are a few examples.

+ + + + + + + + + + + + + + + + + + + + + +
8x500m/2min8 times 500m with 2 minutes rest
10kmSingle distance of 10km
6min/3min + 5min/3min + 3min/3min + 3min Four intervals of 6, 5, 3 and 3 minutes length, 3 minutes rest
8x500m/3:30min 8 times 500m with 3 minutes 30 seconds rest
4x((500m+500m)/5min)4 times 1km, but each km is reported as two 500m intervals without rest. Note the nested parentheses.
2x500m/500mA 2k rowed as 500m "on", 500m "off"
-

Special characters are x (times), + and / (denotes a rest interval), as well as ( and ). Units are min (minutes), sec (seconds), m (meters) and km (km).

+
+ + {{ form.as_table }} +
+ {% csrf_token %} +
+ +
+
-

A typical interval is described as "10min/5min", with the work part before the "/" and the rest part after it. A zero rest can be omitted, so a single 1000m piece could be described either as "1km" or "1000m". The basic units can be combined with "+" and "Nx". You can use parentheses as in the example below.

+

Intervals by Power/Pace

-

Here are a few examples.

- - - - - - - - - - - - - - - - - - - - - -
8x500m/2min8 times 500m with 2 minutes rest
10kmSingle distance of 10km
6min/3min + 5min/3min + 3min/3min + 3min Four intervals of 6, 5, 3 and 3 minutes length, 3 minutes rest
8x500m/3:30min 8 times 500m with 3 minutes 30 seconds rest
4x((500m+500m)/5min)4 times 1km, but each km is reported as two 500m intervals without rest. Note the nested parentheses.
2x500m/500mA 2k rowed as 500m "on", 500m "off"
+

With this form, you can specify a power or pace level. Everything faster/harder than the + specified pace/power will become a work interval. Everything slower will become a rest + interval. +

-
- - {{ form.as_table }} -
- {% csrf_token %} -
- -
-
+
+ + {{ powerupdateform.as_table }} +
+ + {% csrf_token %} +
+ +
+
+ +
-
- - - - - {{ interactiveplot |safe }} +
+ + + + + {{ interactiveplot |safe }} - - -
- {{ the_div |safe }} -
-
- - -
-

Updated Summary

+ + +
+ {{ the_div |safe }} +
+
+ + +
+

Updated Summary

- {% csrf_token %} - - - {% for field in detailform %} - {{ field.as_hidden }} - {% endfor %} -
+ {% csrf_token %} + + + {% for field in detailform %} + {{ field.as_hidden }} + {% endfor %} +
-
-
+
+ -
+
+ +
-
-

-

-{{ intervalstats }}
-
-

-
-
- -
-

Detailed Summary Edit

-

This is still experimental and there are known bugs. Use at your own risk. Nothing is stored permanently until you hit Save on the summary above. You can use the restore original button to restore the original values.

-
-
#
-
- Time -
-
- Distance -
-
- Type -
-
+
+

+

+          {{ intervalstats }}
+        
+

+
+
+ +
+

Detailed Summary Edit

+

This is still experimental and there are known bugs. Use at your own risk. Nothing is stored permanently until you hit Save on the summary above. You can use the restore original button to restore the original values.

+
+
#
+
+ Time +
+
+ Distance +
+
+ Type +
+
- {% for i in nrintervals|times %} -
-
{{ i }}
-
- {% get_field_id i "intervalt_" detailform %} -
-
- {% get_field_id i "intervald_" detailform %} -
-
- {% get_field_id i "type_" detailform %} -
-
- {% endfor %} - {% csrf_token %} -
+ {% for i in nrintervals|times %} +
+
{{ i }}
+
+ {% get_field_id i "intervalt_" detailform %} +
+
+ {% get_field_id i "intervald_" detailform %} +
+
+ {% get_field_id i "type_" detailform %} +
+
+ {% endfor %} + {% csrf_token %} +
-
+
+
- {% endblock %} diff --git a/rowers/views.py b/rowers/views.py index 4c94ef91..33235b2d 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -39,7 +39,7 @@ from rowers.forms import ( LandingPageForm,PlannedSessionSelectForm,WorkoutSessionSelectForm, PlannedSessionTeamForm,PlannedSessionTeamMemberForm, VirtualRaceSelectForm,WorkoutRaceSelectForm,CourseSelectForm, - RaceResultFilterForm, + RaceResultFilterForm,PowerIntervalUpdateForm ) from django.core.urlresolvers import reverse from django.core.exceptions import PermissionDenied @@ -11303,6 +11303,31 @@ def workout_summary_edit_view(request,id,message="",successmessage="" form = SummaryStringForm(initial=data) savebutton = 'savestringform' + # we are saving the results obtained from the power update form + elif request.method == 'POST' and 'selector' in request.POST: + powerupdateform = PowerIntervalUpdateForm(request.POST) + if powerupdateform.is_valid(): + cd = powerupdateform.cleaned_data + powerorpace = cd['selector'] + power = cd['power'] + pace = cd['pace'] + + if powerorpace == 'power': + try: + rowdata.updateinterval_power(power) + except: + messages.error(request,'Error updating power') + elif powerorpace == 'pace': + try: + rowdata.updateinterval_pace(pace) + except: + messages.error(request,'Error updating pace') + + intervalstats = rowdata.allstats() + itime,idist,itype = rowdata.intervalstats_values() + nrintervals = len(idist) + savebutton = 'savestringform' + # we are saving the results obtained from the detailed form elif request.method == 'POST' and "savedetailform" in request.POST: savebutton = 'savedetailform' @@ -11410,13 +11435,14 @@ def workout_summary_edit_view(request,id,message="",successmessage="" detailform = IntervalUpdateForm(aantal=nrintervals,initial=initial) - + powerupdateform = PowerIntervalUpdateForm() # render page return render(request, 'summary_edit.html', {'form':form, 'detailform':detailform, + 'powerupdateform':powerupdateform, 'workout':row, 'teams':get_my_teams(request.user), 'intervalstats':intervalstats, From 7d6f8c5981c752383aaffcb00c8a3dce9c88ef17 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Mon, 11 Jun 2018 15:29:25 +0200 Subject: [PATCH 2/3] bug fix --- rowers/views.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rowers/views.py b/rowers/views.py index 33235b2d..7ffb56fa 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -11327,6 +11327,8 @@ def workout_summary_edit_view(request,id,message="",successmessage="" itime,idist,itype = rowdata.intervalstats_values() nrintervals = len(idist) savebutton = 'savestringform' + + form = SummaryStringForm() # we are saving the results obtained from the detailed form elif request.method == 'POST' and "savedetailform" in request.POST: From f9167c1b8886a5748be4b7c532000b5c72a5a09b Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Wed, 13 Jun 2018 21:14:33 +0200 Subject: [PATCH 3/3] changes --- rowers/views.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/rowers/views.py b/rowers/views.py index 7ffb56fa..a069ef1b 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -11311,15 +11311,22 @@ def workout_summary_edit_view(request,id,message="",successmessage="" powerorpace = cd['selector'] power = cd['power'] pace = cd['pace'] + try: + pace_secs = pace.seconds+pace.microseconds/1.0e6 + except AttributeError: + pace_secs = 120. - if powerorpace == 'power': + if powerorpace == 'power' and power is not None: try: - rowdata.updateinterval_power(power) + rowdata.updateinterval_metric(' Power (watts)',power,mode='larger', + debug=False,smoothwindow=15) except: messages.error(request,'Error updating power') elif powerorpace == 'pace': try: - rowdata.updateinterval_pace(pace) + velo = 500./pace_secs + rowdata.updateinterval_metric(' AverageBoatSpeed (m/s)',velo,mode='larger', + debug=False,smoothwindow=15) except: messages.error(request,'Error updating pace') @@ -11327,6 +11334,8 @@ def workout_summary_edit_view(request,id,message="",successmessage="" itime,idist,itype = rowdata.intervalstats_values() nrintervals = len(idist) savebutton = 'savestringform' + powerupdateform = PowerIntervalUpdateForm(initial=cd) + form = SummaryStringForm() @@ -11428,6 +11437,7 @@ def workout_summary_edit_view(request,id,message="",successmessage="" else: form = SummaryStringForm() + powerupdateform = PowerIntervalUpdateForm() initial = {} for i in xrange(nrintervals): @@ -11437,7 +11447,6 @@ def workout_summary_edit_view(request,id,message="",successmessage="" detailform = IntervalUpdateForm(aantal=nrintervals,initial=initial) - powerupdateform = PowerIntervalUpdateForm() # render page