diff --git a/rowers/templates/oterankings.html b/rowers/templates/oterankings.html
new file mode 100644
index 00000000..9fdc910d
--- /dev/null
+++ b/rowers/templates/oterankings.html
@@ -0,0 +1,232 @@
+{% extends "base.html" %}
+{% load staticfiles %}
+{% load rowerfilters %}
+
+{% block scripts %}
+{% include "monitorjobs.html" %}
+{% endblock %}
+
+{% block title %}Workouts{% endblock %}
+
+{% block content %}
+
+
+
+
+ {{ interactiveplot |safe }}
+
+
+
+
+
+
+
+ {% if theuser %}
+
{{ theuser.first_name }}'s Ranking Pieces
+ {% else %}
+ {{ user.first_name }}'s Ranking Pieces
+ {% endif %}
+
+
+ {% if user.is_authenticated and user|is_manager %}
+
+
+
+
+
+
+
+
+
+
+
Critical Power Plot
+
+ {{ the_div|safe }}
+
+
+
+
+
+
Ranking Piece Results
+
+ {% if rankingworkouts %}
+
+
+
+
+ Distance
+ Duration
+ Avg Power
+ Date
+ Avg HR
+ Max HR
+ Edit
+
+
+
+ {% for workout in rankingworkouts %}
+
+ {{ workout.distance }} m
+ {{ workout.duration |durationprint:"%H:%M:%S.%f" }}
+ {{ avgpower|lookup:workout.id }} W
+ {{ workout.date }}
+ {{ workout.averagehr }}
+ {{ workout.maxhr }}
+
+ {{ workout.name }}
+
+
+
+ {% endfor %}
+
+
+ {% else %}
+
No ranking workouts found
+ {% endif %}
+
+
+
+
+
Pace predictions for Ranking Pieces
+
+
Add non-ranking piece using the form. The piece will be added in the prediction tables below.
+
+
+
+
+
+
+
+ Duration
+ Distance
+ Pace (upper)
+ Power
+ Power (upper)
+
+
+
+ {% for pred in cpredictions %}
+
+ {% for key, value in pred.items %}
+ {% if key == "power" or key == "upper" %}
+ {{ value }} W
+ {% endif %}
+ {% if key == "duration" %}
+ {{ value |deltatimeprint }}
+ {% endif %}
+ {% if key == "distance" %}
+ {{ value }} m
+ {% endif %}
+ {% if key == 'pace' %}
+ {{ value|paceprint }}
+ {% endif %}
+ {% endfor %}
+
+ {% endfor %}
+
+
+
+
+
+
+
+
+ minutes
+
+
+
+
+
+
+
+
+
+{% endblock %}
diff --git a/rowers/views.py b/rowers/views.py
index 8fe5e197..13c9cee9 100644
--- a/rowers/views.py
+++ b/rowers/views.py
@@ -3779,6 +3779,8 @@ def oterankings_view(request,theuser=0,
rankingdurations.append(datetime.time(hour=1))
rankingdurations.append(datetime.time(hour=1,minute=15))
+ rankingdistances = [100,500,1000,2000,5000,6000,10000,21097,42195,100000]
+
thedistances = []
theworkouts = []
thesecs = []
@@ -3874,21 +3876,29 @@ def oterankings_view(request,theuser=0,
form = PredictedPieceForm(request.POST)
clean = form.is_valid()
value = form.cleaned_data['value']
- hourvalue,value = divmod(value,60)
+ hourvalue,tvalue = divmod(value,60)
hourvalue = int(hourvalue)
- minutevalue = int(value)
- value = int(60*(value-minutevalue))
+ minutevalue = int(tvalue)
+ tvalue = int(60*(tvalue-minutevalue))
if hourvalue >= 24:
hourvalue = 23
- rankingdurations.append(datetime.time(minute=minutevalue,
- hour=hourvalue,
- second=value))
+ pieceunit = form.cleaned_data['pieceunit']
+ if pieceunit == 'd':
+ rankingdistances.append(value)
+ else:
+ rankingdurations.append(datetime.time(
+ minute=minutevalue,
+ hour=hourvalue,
+ second=tvalue
+ ))
else:
form = PredictedPieceForm()
cpredictions = []
+
+
for rankingduration in rankingdurations:
t = 3600.*rankingduration.hour
t += 60.*rankingduration.minute
@@ -3900,6 +3910,9 @@ def oterankings_view(request,theuser=0,
pwr = p1[0]/(1+t/p1[2])
pwr += p1[1]/(1+t/p1[3])
+ velo = (pwr/2.8)**(1./3.)
+ p = 500./velo
+ d = t*velo
if pwr <= 0:
pwr = 50.
@@ -3912,16 +3925,78 @@ def oterankings_view(request,theuser=0,
pwr2 = pwr
a = {
+ 'distance':int(d),
'duration':timedeltaconv(t),
'power':int(pwr),
- 'upper':int(pwr2)}
+ 'upper':int(pwr2),
+ 'pace':timedeltaconv(p)}
+
cpredictions.append(a)
- del form.fields["pieceunit"]
+ # initiation - get 10 min power, then use Paul's law
+
+ t_10 = 600.
+ power_10 = p1[0]/(1+t_10/p1[2])
+ power_10 += p1[1]/(1+t_10/p1[3])
+
+ velo_10 = (power_10/2.8)**(1./3.)
+ pace_10 = 500./velo_10
+ distance_10 = t_10*velo_10
+
+ paulslope = 5.
+
+ for rankingdistance in rankingdistances:
+
+ delta = paulslope * np.log(rankingdistance/distance_10)/np.log(2)
+
+
+ p = pace_10+delta
+ velo = 500./p
+ t = rankingdistance/velo
+
+ pwr2 = p1[0]/(1+t/p1[2])
+ pwr2 += p1[1]/(1+t/p1[3])
+ pwr2 *= ratio
+
+ if pwr2 <= 0:
+ pwr2 = 50.
+
+ velo2 = (pwr2/2.8)**(1./3.)
+
+ if np.isnan(velo2) or velo2 <= 0:
+ velo2 = 1.0
+
+ t2 = rankingdistance/velo2
+
+ pwr3 = p1[0]/(1+t2/p1[2])
+ pwr3 += p1[1]/(1+t2/p1[3])
+ pwr3 *= ratio
+
+
+ if pwr3 <= 0:
+ pwr3 = 50.
+
+ velo3 = (pwr3/2.8)**(1./3.)
+ if np.isnan(velo3) or velo3 <= 0:
+ velo3 = 1.0
+
+ t3 = rankingdistance/velo3
+ p3 = 500./velo3
+
+ a = {
+ 'distance':rankingdistance,
+ 'duration':timedeltaconv(t3),
+ 'power':'--',
+ 'upper':int(pwr3),
+ 'pace':timedeltaconv(p3)}
+
+ cpredictions.append(a)
+
+ # del form.fields["pieceunit"]
messages.error(request,message)
- return render(request, 'otwrankings.html',
+ return render(request, 'oterankings.html',
{'rankingworkouts':theworkouts,
'interactiveplot':script,
'the_div':div,
diff --git a/static/img/image.png b/static/img/image.png
new file mode 100644
index 00000000..d6acd417
Binary files /dev/null and b/static/img/image.png differ