Private
Public Access
1
0

Merge branch 'feature/powerintervals' into develop

This commit is contained in:
Sander Roosendaal
2018-06-13 21:15:41 +02:00
3 changed files with 242 additions and 171 deletions

View File

@@ -481,6 +481,20 @@ class MyTimeField(forms.TimeField):
super(MyTimeField, self).__init__(*args, **kwargs) super(MyTimeField, self).__init__(*args, **kwargs)
supports_microseconds = True 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 # Form used to update interval stats
class IntervalUpdateForm(forms.Form): class IntervalUpdateForm(forms.Form):

View File

@@ -37,7 +37,7 @@
</div> </div>
{% localtime on %} {% localtime on %}
<table width=100%> <table width=100%>
<tr> <tr>
<th>Date/Time:</th><td>{{ workout.startdatetime }}</td> <th>Date/Time:</th><td>{{ workout.startdatetime }}</td>
@@ -57,38 +57,38 @@
<td> <td>
</tr> </tr>
</table> </table>
{% endlocaltime %} {% endlocaltime %}
<h1>Interval Translator</h1> <h1>Interval Translator</h1>
<p>This is a quick way to enter the intervals using a special mini-language.</p> <p>This is a quick way to enter the intervals using a special mini-language.</p>
<p>You enter something like <em>8x500m/3min</em>, 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.</p> <p>You enter something like <em>8x500m/3min</em>, 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.</p>
<p>Special characters are <em>x</em> (times), <em>+</em> and <em>/</em> (denotes a rest interval), as well as <em>(</em> and <em>)</em>. Units are <em>min</em> (minutes), <em>sec</em> (seconds), <em>m</em> (meters) and <em>km</em> (km). </p> <p>Special characters are <em>x</em> (times), <em>+</em> and <em>/</em> (denotes a rest interval), as well as <em>(</em> and <em>)</em>. Units are <em>min</em> (minutes), <em>sec</em> (seconds), <em>m</em> (meters) and <em>km</em> (km). </p>
<p>A typical interval is described as "<b>10min/5min</b>", with the work part before the "<b>/</b>" and the rest part after it. A zero rest can be omitted, so a single 1000m piece could be described either as "<b>1km</b>" or "<b>1000m</b>". The basic units can be combined with "<b>+</b>" and "<b>Nx</b>". You can use parentheses as in the example below.</p> <p>A typical interval is described as "<b>10min/5min</b>", with the work part before the "<b>/</b>" and the rest part after it. A zero rest can be omitted, so a single 1000m piece could be described either as "<b>1km</b>" or "<b>1000m</b>". The basic units can be combined with "<b>+</b>" and "<b>Nx</b>". You can use parentheses as in the example below.</p>
<p>Here are a few examples.</p> <p>Here are a few examples.</p>
<table class="listtable" width=100%> <table class="listtable" width=100%>
<tr> <tr>
<td>8x500m/2min</td><td>8 times 500m with 2 minutes rest</td> <td>8x500m/2min</td><td>8 times 500m with 2 minutes rest</td>
</tr> </tr>
<tr> <tr>
<td>10km</td><td>Single distance of 10km</td> <td>10km</td><td>Single distance of 10km</td>
</tr> </tr>
<tr> <tr>
<td>6min/3min + 5min/3min + 3min/3min + 3min </td> <td>6min/3min + 5min/3min + 3min/3min + 3min </td>
<td>Four intervals of 6, 5, 3 and 3 minutes length, 3 minutes rest</td> <td>Four intervals of 6, 5, 3 and 3 minutes length, 3 minutes rest</td>
</tr> </tr>
<tr> <tr>
<td>8x500m/3:30min </td> <td>8x500m/3:30min </td>
<td>8 times 500m with 3 minutes 30 seconds rest</td> <td>8 times 500m with 3 minutes 30 seconds rest</td>
</tr> </tr>
<tr> <tr>
<td>4x((500m+500m)/5min)</td><td>4 times 1km, but each km is reported as two 500m intervals without rest. Note the nested parentheses.</td> <td>4x((500m+500m)/5min)</td><td>4 times 1km, but each km is reported as two 500m intervals without rest. Note the nested parentheses.</td>
</tr> </tr>
<tr> <tr>
<td>2x500m/500m</td><td>A 2k rowed as 500m "on", 500m "off"</td> <td>2x500m/500m</td><td>A 2k rowed as 500m "on", 500m "off"</td>
</tr> </tr>
</table> </table>
<form enctype="multipart/form-data" action="/rowers/workout/{{ workout.id }}/editintervals" method="post"> <form enctype="multipart/form-data" action="/rowers/workout/{{ workout.id }}/editintervals" method="post">
<table width=100%> <table width=100%>
@@ -99,6 +99,26 @@
<input class="button green" type="submit" value="Update"> <input class="button green" type="submit" value="Update">
</div> </div>
</form> </form>
<h1>Intervals by Power/Pace</h1>
<p>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.
</p>
<form ecntype="multipart/form-data" method="post">
<table>
{{ powerupdateform.as_table }}
</table>
{% csrf_token %}
<div id="formbutton" class="grid_1 prefix_4 suffix_1">
<input class="button green" type="submit" value="Submit">
</div>
</form>
</div> </div>
<div id="advancedplots" class="grid_6 omega"> <div id="advancedplots" class="grid_6 omega">
@@ -132,13 +152,13 @@
</style> </style>
<div id="interactiveplot" class="grid_6 omega"> <div id="interactiveplot" class="grid_6 omega">
{{ the_div |safe }} {{ the_div |safe }}
</div> </div>
</div> </div>
<div id="summary" class="grid_6 omega"> <div id="summary" class="grid_6 omega">
<h1>Updated Summary</h1> <h1>Updated Summary</h1>
<form enctype="multipart/form-data" action="/rowers/workout/{{ workout.id }}/editintervals" method="post"> <form enctype="multipart/form-data" action="/rowers/workout/{{ workout.id }}/editintervals" method="post">
{% csrf_token %} {% csrf_token %}
@@ -159,16 +179,16 @@
</form> </form>
<div class="grid_6 alpha"> <div class="grid_6 alpha">
<p> <p>
<pre> <pre>
{{ intervalstats }} {{ intervalstats }}
</pre> </pre>
</p> </p>
</div> </div>
</div> </div>
<div id="summary" class="grid_6 omega"> <div id="summary" class="grid_6 omega">
<h1>Detailed Summary Edit</h1> <h1>Detailed Summary Edit</h1>
<p>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.</p> <p>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.</p>
<div class="grid_6 alpha"> <div class="grid_6 alpha">
<div class="grid_1 alpha"><strong>#</strong></div> <div class="grid_1 alpha"><strong>#</strong></div>
<div class="grid_1"> <div class="grid_1">
@@ -202,6 +222,6 @@
<input class="button green" type="submit" value="Update"> <input class="button green" type="submit" value="Update">
</div> </div>
</form> </form>
</div>
</div> </div>
{% endblock %} {% endblock %}

View File

@@ -39,7 +39,7 @@ from rowers.forms import (
LandingPageForm,PlannedSessionSelectForm,WorkoutSessionSelectForm, LandingPageForm,PlannedSessionSelectForm,WorkoutSessionSelectForm,
PlannedSessionTeamForm,PlannedSessionTeamMemberForm, PlannedSessionTeamForm,PlannedSessionTeamMemberForm,
VirtualRaceSelectForm,WorkoutRaceSelectForm,CourseSelectForm, VirtualRaceSelectForm,WorkoutRaceSelectForm,CourseSelectForm,
RaceResultFilterForm, RaceResultFilterForm,PowerIntervalUpdateForm
) )
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
@@ -11341,6 +11341,42 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
form = SummaryStringForm(initial=data) form = SummaryStringForm(initial=data)
savebutton = 'savestringform' 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']
try:
pace_secs = pace.seconds+pace.microseconds/1.0e6
except AttributeError:
pace_secs = 120.
if powerorpace == 'power' and power is not None:
try:
rowdata.updateinterval_metric(' Power (watts)',power,mode='larger',
debug=False,smoothwindow=15)
except:
messages.error(request,'Error updating power')
elif powerorpace == 'pace':
try:
velo = 500./pace_secs
rowdata.updateinterval_metric(' AverageBoatSpeed (m/s)',velo,mode='larger',
debug=False,smoothwindow=15)
except:
messages.error(request,'Error updating pace')
intervalstats = rowdata.allstats()
itime,idist,itype = rowdata.intervalstats_values()
nrintervals = len(idist)
savebutton = 'savestringform'
powerupdateform = PowerIntervalUpdateForm(initial=cd)
form = SummaryStringForm()
# we are saving the results obtained from the detailed form # we are saving the results obtained from the detailed form
elif request.method == 'POST' and "savedetailform" in request.POST: elif request.method == 'POST' and "savedetailform" in request.POST:
savebutton = 'savedetailform' savebutton = 'savedetailform'
@@ -11439,6 +11475,7 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
else: else:
form = SummaryStringForm() form = SummaryStringForm()
powerupdateform = PowerIntervalUpdateForm()
initial = {} initial = {}
for i in xrange(nrintervals): for i in xrange(nrintervals):
@@ -11449,12 +11486,12 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
detailform = IntervalUpdateForm(aantal=nrintervals,initial=initial) detailform = IntervalUpdateForm(aantal=nrintervals,initial=initial)
# render page # render page
return render(request, 'summary_edit.html', return render(request, 'summary_edit.html',
{'form':form, {'form':form,
'detailform':detailform, 'detailform':detailform,
'powerupdateform':powerupdateform,
'workout':row, 'workout':row,
'teams':get_my_teams(request.user), 'teams':get_my_teams(request.user),
'intervalstats':intervalstats, 'intervalstats':intervalstats,