Private
Public Access
1
0

adding OTW power slack

This commit is contained in:
Sander Roosendaal
2017-05-18 15:23:09 +02:00
parent 9578be77c0
commit 40313f9680
3 changed files with 83 additions and 22 deletions

View File

@@ -173,6 +173,7 @@ class Rower(models.Model):
# Power Zone Data
ftp = models.IntegerField(default=226,verbose_name="Functional Threshold Power")
otwslack = models.IntegerField(default=15,verbose_name="OTW Power slack")
pw_ut2 = models.IntegerField(default=124,verbose_name="UT2 Power")
pw_ut1 = models.IntegerField(default=171,verbose_name="UT1 Power")
@@ -576,7 +577,7 @@ class AdvancedWorkoutForm(ModelForm):
class RowerPowerForm(ModelForm):
class Meta:
model = Rower
fields = ['ftp']
fields = ['ftp','otwslack']
# Form to set rower's Power zones, including test routines
# to enable consistency

View File

@@ -7,6 +7,7 @@
<div class="grid_6 alpha">
<p>
<h2>Heart Rate Zones</h2>
<p>Set your heart rate zones with this form.</p>
{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
@@ -27,6 +28,8 @@
<div class="grid_6 omega">
<p>
<h2>Power Zones</h2>
<p>The power zones are defined relative to power as measured by the
indoor rower.</p>
<form enctype="multipart/form-data" action="" method="post">
{% if powerzonesform.errors %}
<p style="color: red;">
@@ -127,10 +130,15 @@
</div>
<div class="grid_6 omega">
<p>
<h2>Functional Threshold Power</h2>
<h2>Functional Threshold Power and OTW Slack</h2>
<p>Use this form to quickly change your zones based on the power of a
recent
full out 60 minutes effort. It will update all zones defined above.</p>
full out 60 minutes effort on the ergometer.
It will update all zones defined above.</p>
<p>The OTW Power Slack is the percentage drop of your On-the-water
rowing power
vs the erg power. Typical values are around 15%. This will lower
the power zones for your OTW workouts.</p>
<form enctype="multipart/form-data" action="" method="post">
<table>
{{ powerform.as_table }}

View File

@@ -4394,6 +4394,10 @@ def cumstats(request,theuser=0,
def workout_stats_view(request,id=0,message="",successmessage=""):
r = Rower.objects.get(user=request.user)
try:
w = Workout.objects.get(id=id)
except Workout.DoesNotExist:
raise Http404("Workout doesn't exist")
workstrokesonly = True
if request.method == 'POST' and 'workstrokesonly' in request.POST:
@@ -4462,9 +4466,13 @@ def workout_stats_view(request,id=0,message="",successmessage=""):
pwr4 = datadf['power']**(4)
normp = (pwr4.mean())**(0.25)
if not np.isnan(normp):
intensityfactor = datadf['power'].mean()/float(r.ftp)
intensityfactor = normp/float(r.ftp)
tss = 100.*((duration*normp*intensityfactor)/(3600.*r.ftp))
ftp = float(r.ftp)
if w.workouttype == 'water':
ftp = ftp*(100.-r.otwslack)/100.
intensityfactor = datadf['power'].mean()/float(ftp)
intensityfactor = normp/float(ftp)
tss = 100.*((duration*normp*intensityfactor)/(3600.*ftp))
if not np.isnan(tss):
otherstats['tss'] = {
@@ -5299,6 +5307,10 @@ def workout_add_otw_powerplot_view(request,id):
r.pw_tr,r.pw_an])/r.ftp
ftp = r.ftp
if w.workouttype == 'water':
ftp = ftp*(100.-r.otwslack)/100.
hrpwrdata = {
'hrmax':r.max,
'hrut2':r.ut2,
@@ -5306,7 +5318,7 @@ def workout_add_otw_powerplot_view(request,id):
'hrat':r.at,
'hrtr':r.tr,
'hran':r.an,
'ftp':r.ftp,
'ftp':ftp,
'powerperc':serialize_list(powerperc),
'powerzones':serialize_list(r.powerzones),
}
@@ -5356,6 +5368,9 @@ def workout_add_piechart_view(request,id):
r.pw_at,
r.pw_tr,r.pw_an])/r.ftp
ftp = float(r.ftp)
if w.workouttype == 'water':
ftp = ftp*(100.-r.otwslack)/100.
hrpwrdata = {
'hrmax':r.max,
@@ -5364,7 +5379,7 @@ def workout_add_piechart_view(request,id):
'hrat':r.at,
'hrtr':r.tr,
'hran':r.an,
'ftp':r.ftp,
'ftp':ftp,
'powerperc':serialize_list(powerperc),
'powerzones':serialize_list(r.powerzones),
}
@@ -5414,6 +5429,9 @@ def workout_add_power_piechart_view(request,id):
r.pw_at,
r.pw_tr,r.pw_an])/r.ftp
ftp = float(r.ftp)
if w.workouttype == 'water':
ftp = ftp*(100.-r.otwslack)/100.
hrpwrdata = {
'hrmax':r.max,
@@ -5422,7 +5440,7 @@ def workout_add_power_piechart_view(request,id):
'hrat':r.at,
'hrtr':r.tr,
'hran':r.an,
'ftp':r.ftp,
'ftp':ftp,
'powerperc':serialize_list(powerperc),
'powerzones':serialize_list(r.powerzones),
}
@@ -5469,6 +5487,9 @@ def workout_add_timeplot_view(request,id):
r.pw_at,
r.pw_tr,r.pw_an])/r.ftp
ftp = float(r.ftp)
if w.workouttype == 'water':
ftp = ftp*(100.-r.otwslack)/100.
hrpwrdata = {
'hrmax':r.max,
@@ -5477,7 +5498,7 @@ def workout_add_timeplot_view(request,id):
'hrat':r.at,
'hrtr':r.tr,
'hran':r.an,
'ftp':r.ftp,
'ftp':ftp,
'powerperc':serialize_list(powerperc),
'powerzones':serialize_list(r.powerzones),
}
@@ -5526,6 +5547,9 @@ def workout_add_distanceplot_view(request,id):
r.pw_at,
r.pw_tr,r.pw_an])/r.ftp
ftp = float(r.ftp)
if w.workouttype == 'water':
ftp = ftp*(100.-r.otwslack)/100.
hrpwrdata = {
'hrmax':r.max,
@@ -5534,7 +5558,7 @@ def workout_add_distanceplot_view(request,id):
'hrat':r.at,
'hrtr':r.tr,
'hran':r.an,
'ftp':r.ftp,
'ftp':ftp,
'powerperc':serialize_list(powerperc),
'powerzones':serialize_list(r.powerzones),
}
@@ -5581,6 +5605,9 @@ def workout_add_distanceplot2_view(request,id):
r.pw_at,
r.pw_tr,r.pw_an])/r.ftp
ftp = float(r.ftp)
if w.workouttype == 'water':
ftp = ftp*(100.-r.otwslack)/100.
hrpwrdata = {
'hrmax':r.max,
@@ -5589,7 +5616,7 @@ def workout_add_distanceplot2_view(request,id):
'hrat':r.at,
'hrtr':r.tr,
'hran':r.an,
'ftp':r.ftp,
'ftp':ftp,
'powerperc':serialize_list(powerperc),
'powerzones':serialize_list(r.powerzones),
}
@@ -5638,6 +5665,9 @@ def workout_add_timeplot2_view(request,id):
r.pw_at,
r.pw_tr,r.pw_an])/r.ftp
ftp = float(r.ftp)
if w.workouttype == 'water':
ftp = ftp*(100.-r.otwslack)/100.
hrpwrdata = {
'hrmax':r.max,
@@ -5646,7 +5676,7 @@ def workout_add_timeplot2_view(request,id):
'hrat':r.at,
'hrtr':r.tr,
'hran':r.an,
'ftp':r.ftp,
'ftp':ftp,
'powerperc':serialize_list(powerperc),
'powerzones':serialize_list(r.powerzones),
}
@@ -6387,6 +6417,10 @@ def workout_upload_view(request,
r.pw_at,
r.pw_tr,r.pw_an])/r.ftp
ftp = float(r.ftp)
if w.workouttype == 'water':
ftp = ftp*(100.-r.otwslack)/100.
hrpwrdata = {
'hrmax':r.max,
'hrut2':r.ut2,
@@ -6394,7 +6428,7 @@ def workout_upload_view(request,
'hrat':r.at,
'hrtr':r.tr,
'hran':r.an,
'ftp':r.ftp,
'ftp':ftp,
'powerperc':serialize_list(powerperc),
'powerzones':serialize_list(r.powerzones),
}
@@ -6631,6 +6665,10 @@ def team_workout_upload_view(request,message="",
r.pw_at,
r.pw_tr,r.pw_an])/r.ftp
ftp = float(r.ftp)
if w.workouttype == 'water':
ftp = ftp*(100.-r.otwslack)/100.
hrpwrdata = {
'hrmax':r.max,
'hrut2':r.ut2,
@@ -6638,7 +6676,7 @@ def team_workout_upload_view(request,message="",
'hrat':r.at,
'hrtr':r.tr,
'hran':r.an,
'ftp':r.ftp,
'ftp':ftp,
'powerperc':serialize_list(powerperc),
'powerzones':serialize_list(r.powerzones),
}
@@ -6840,9 +6878,13 @@ def workout_summary_restore_view(request,id,message="",successmessage=""):
r.pw_at,
r.pw_tr,r.pw_an])/r.ftp
ftp = float(r.ftp)
if row.workouttype == 'water':
ftp = ftp*(100.-r.otwslack)/100.
rr = rrower(hrmax=r.max,hrut2=r.ut2,
hrut1=r.ut1,hrat=r.at,
hrtr=r.tr,hran=r.an,ftp=r.ftp,
hrtr=r.tr,hran=r.an,ftp=ftp,
powerperc=powerperc,powerzones=r.powerzones)
rowdata = rdata(f1,rower=rr)
if rowdata == 0:
@@ -6951,9 +6993,13 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
r.pw_at,
r.pw_tr,r.pw_an])/r.ftp
ftp = float(r.ftp)
if row.workouttype == 'water':
ftp = ftp*(100.-r.otwslack)/100.
rr = rrower(hrmax=r.max,hrut2=r.ut2,
hrut1=r.ut1,hrat=r.at,
hrtr=r.tr,hran=r.an,ftp=r.ftp,
hrtr=r.tr,hran=r.an,ftp=ftp,
powerperc=powerperc,powerzones=r.powerzones)
rowdata = rdata(f1,rower=rr)
if rowdata == 0:
@@ -7272,6 +7318,7 @@ def rower_edit_view(request,message=""):
if powerform.is_valid():
cd = powerform.cleaned_data
ftp = cd['ftp']
otwslack = cd['otwslack']
try:
r = Rower.objects.get(user=request.user)
powerfrac = 100*np.array([r.pw_ut2,
@@ -7279,6 +7326,7 @@ def rower_edit_view(request,message=""):
r.pw_at,
r.pw_tr,r.pw_an])/r.ftp
r.ftp = max(min(ftp,650),50)
r.otwslack = max(min(otwslack,50),0)
ut2,ut1,at,tr,an = (r.ftp*powerfrac/100.).astype(int)
r.pw_ut2 = ut2
r.pw_ut1 = ut1
@@ -7286,7 +7334,7 @@ def rower_edit_view(request,message=""):
r.pw_tr = tr
r.pw_an = an
r.save()
message = "Functional Threshold Value Changed"
message = "FTP and/or OTW slack values changed."
messages.info(request,message)
url = reverse(rower_edit_view)
response = HttpResponseRedirect(url)
@@ -7635,9 +7683,13 @@ def strokedatajson(request,id):
r.pw_at,
r.pw_tr,r.pw_an])/r.ftp
ftp = float(r.ftp)
if row.workouttype == 'water':
ftp = ftp*(100.-r.otwslack)/100.
rr = rrower(hrmax=r.max,hrut2=r.ut2,
hrut1=r.ut1,hrat=r.at,
hrtr=r.tr,hran=r.an,ftp=r.ftp,
hrtr=r.tr,hran=r.an,ftp=ftp,
powerperc=powerperc,powerzones=r.powerzones)
rowdata = rdata(row.csvfilename,rower=rr).df