better power zones
This commit is contained in:
@@ -1259,7 +1259,6 @@ def getsmallrowdata_db(columns, ids=[], doclean=True, workstrokesonly=True, comp
|
|||||||
df = pd.concat(data, axis=0)
|
df = pd.concat(data, axis=0)
|
||||||
except ValueError: # pragma: no cover
|
except ValueError: # pragma: no cover
|
||||||
return pd.DataFrame()
|
return pd.DataFrame()
|
||||||
# df = dd.concat(data,axis=0)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -6283,7 +6283,15 @@ def thumbnails_set(r, id, favorites):
|
|||||||
columns += ['time']
|
columns += ['time']
|
||||||
rowdata = dataprep.getsmallrowdata_db(columns, ids=[id], doclean=True)
|
rowdata = dataprep.getsmallrowdata_db(columns, ids=[id], doclean=True)
|
||||||
|
|
||||||
rowdata.dropna(axis=1, how='all', inplace=True)
|
try:
|
||||||
|
rowdata.dropna(axis=1, how='all', inplace=True)
|
||||||
|
except TypeError:
|
||||||
|
return [
|
||||||
|
{'script': "",
|
||||||
|
'div': "",
|
||||||
|
'notes': ""
|
||||||
|
}]
|
||||||
|
|
||||||
|
|
||||||
if rowdata.empty:
|
if rowdata.empty:
|
||||||
try:
|
try:
|
||||||
@@ -6303,12 +6311,6 @@ def thumbnails_set(r, id, favorites):
|
|||||||
'notes': ""
|
'notes': ""
|
||||||
}]
|
}]
|
||||||
|
|
||||||
# else:
|
|
||||||
# try:
|
|
||||||
# rowdata.sort_values(by='time',ascending=True,inplace=True)
|
|
||||||
# except KeyError:
|
|
||||||
# pass
|
|
||||||
|
|
||||||
lengte = len(rowdata)
|
lengte = len(rowdata)
|
||||||
maxlength = 50
|
maxlength = 50
|
||||||
if lengte > maxlength:
|
if lengte > maxlength:
|
||||||
|
|||||||
@@ -964,6 +964,7 @@ class Rower(models.Model):
|
|||||||
# Power Zone Data
|
# Power Zone Data
|
||||||
ftp = models.IntegerField(
|
ftp = models.IntegerField(
|
||||||
default=226, verbose_name="Functional Threshold Power")
|
default=226, verbose_name="Functional Threshold Power")
|
||||||
|
cogganzones = models.BooleanField(verbose_name='Use Default Power Zones',default=True)
|
||||||
|
|
||||||
p0 = models.FloatField(default=1.0, verbose_name="CP p1")
|
p0 = models.FloatField(default=1.0, verbose_name="CP p1")
|
||||||
p1 = models.FloatField(default=1.0, verbose_name="CP p2")
|
p1 = models.FloatField(default=1.0, verbose_name="CP p2")
|
||||||
@@ -997,11 +998,11 @@ class Rower(models.Model):
|
|||||||
pw_an = models.IntegerField(default=273, verbose_name="AN Power")
|
pw_an = models.IntegerField(default=273, verbose_name="AN Power")
|
||||||
|
|
||||||
powerzones = PowerZonesField(default=['Rest',
|
powerzones = PowerZonesField(default=['Rest',
|
||||||
'Pwr UT2',
|
'Active Recovery',
|
||||||
'Pwr UT1',
|
'Endurance',
|
||||||
'Pwr AT',
|
'Tempo',
|
||||||
'Pwr TR',
|
'Threshold',
|
||||||
'Pwr AN'])
|
'Anaerobic'])
|
||||||
|
|
||||||
hrzones = PowerZonesField(default=['Rest',
|
hrzones = PowerZonesField(default=['Rest',
|
||||||
'UT2',
|
'UT2',
|
||||||
@@ -4224,7 +4225,7 @@ class RowerExportForm(ModelForm):
|
|||||||
class RowerPowerForm(ModelForm):
|
class RowerPowerForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Rower
|
model = Rower
|
||||||
fields = ['hrftp', 'ftp', 'otwslack']
|
fields = ['hrftp', 'ftp', 'otwslack','cogganzones']
|
||||||
|
|
||||||
|
|
||||||
class RowerCPForm(ModelForm):
|
class RowerCPForm(ModelForm):
|
||||||
|
|||||||
@@ -10,6 +10,103 @@
|
|||||||
<p><a href="http://analytics.rowsandall.com/2017/11/02/rowsandall-settings-page-tutorial/">Need help? Click to read the tutorial</a></p>
|
<p><a href="http://analytics.rowsandall.com/2017/11/02/rowsandall-settings-page-tutorial/">Need help? Click to read the tutorial</a></p>
|
||||||
|
|
||||||
<ul class="main-content">
|
<ul class="main-content">
|
||||||
|
<li class="grid_2">
|
||||||
|
<form enctype="multipart/form-data" action="" method="post">
|
||||||
|
<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 on the ergometer. It
|
||||||
|
will update all zones defined.</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>
|
||||||
|
<p>If you use default power zones, we will use the namees and
|
||||||
|
values as defined by
|
||||||
|
<a href="https://www.trainingpeaks.com/blog/power-training-levels/" target="_">Coggan</a>.</p>
|
||||||
|
<table>
|
||||||
|
{{ powerform.as_table }}
|
||||||
|
</table>
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="submit" value="Update">
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
<li class="grid_2">
|
||||||
|
<h2>Power Zones</h2>
|
||||||
|
<p>Use this form if you want to rename and redefine your power
|
||||||
|
zones independent of the value of FTP. We recommend, however, that
|
||||||
|
you leave these values as they are and only change the FTP and OTW
|
||||||
|
slack values.</p>
|
||||||
|
<form enctype="multipart/form-data" action="" method="post">
|
||||||
|
{% if powerzonesform.errors %}
|
||||||
|
<p style="color: red;">
|
||||||
|
Please correct the error{{ powerzonesform.errors|pluralize }} below.
|
||||||
|
{{ powerzonesform.non_field_errors }}
|
||||||
|
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>ID </th><th>Zone Name</th><th>Lower Boundary (Watt) </th><th>Lower Boundary (Watt)</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th></th><th></th><th>Indoor</th><th>OTW</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>1</td><td>{{ powerzonesform.ut3name }}</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>2</td><td>{{ powerzonesform.ut2name }}</td>
|
||||||
|
<td>{{ powerzonesform.pw_ut2 }}</td>
|
||||||
|
<td>{{ user.rower.pw_ut2|otwslack:user }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>3</td><td>{{ powerzonesform.ut1name }}</td>
|
||||||
|
<td>{{ powerzonesform.pw_ut1 }}</td>
|
||||||
|
<td>{{ user.rower.pw_ut1|otwslack:user }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>4</td><td>{{ powerzonesform.atname }}</td>
|
||||||
|
<td>{{ powerzonesform.pw_at }}</td>
|
||||||
|
<td>{{ user.rower.pw_at|otwslack:user }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>5</td><td>{{ powerzonesform.trname }}</td>
|
||||||
|
<td>{{ powerzonesform.pw_tr }}</td>
|
||||||
|
<td>{{ user.rower.pw_tr|otwslack:user }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>6</td><td>{{ powerzonesform.anname }}</td>
|
||||||
|
<td>{{ powerzonesform.pw_an }}</td>
|
||||||
|
<td>{{ user.rower.pw_an|otwslack:user }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="grid_2 prefix_2 suffix_2">
|
||||||
|
<input type="submit" value="Update Power Zones">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
<li class="grid_2">
|
||||||
|
<form enctype="multipart/form-data" action="" method="post">
|
||||||
|
<h2>Fitness and Performance Manager Settings</h2>
|
||||||
|
<p>Use this form to change the parameters affecting your performance management.</p>
|
||||||
|
<p>A shorter range for the CP calculations
|
||||||
|
will give you notifications of fitness improvements more often,
|
||||||
|
but will also quickly forget those breakthrough workouts. Shorter decay
|
||||||
|
time constants for the performance manager will model a quicker building up
|
||||||
|
of fitness and a faster recovery. Recommended values are 42 days (fitness)
|
||||||
|
and 7 days (fatigue).</p>
|
||||||
|
<table>
|
||||||
|
{{ cpform.as_table }}
|
||||||
|
</table>
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="submit" value="Update">
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
<p>
|
<p>
|
||||||
<h2>Heart Rate Zones</h2>
|
<h2>Heart Rate Zones</h2>
|
||||||
@@ -22,7 +119,7 @@
|
|||||||
</p>
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>ID</th><th>Zone Name</th><th>Lower Boundary (BPM)</th>
|
<th>ID</th><th>Zone Name</th><th>Lower Boundary (BPM)</th>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -52,7 +149,7 @@
|
|||||||
<td>6</td><td>{{ form.hranname }}</td>
|
<td>6</td><td>{{ form.hranname }}</td>
|
||||||
<td>{{ form.an }}</td>
|
<td>{{ form.an }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>7</td><td>{{ form.hrmaxname }}</td>
|
<td>7</td><td>{{ form.hrmaxname }}</td>
|
||||||
<td>{{ form.max }}</td>
|
<td>{{ form.max }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -62,92 +159,6 @@
|
|||||||
<input type="submit" value="Update Heart Rate Zones">
|
<input type="submit" value="Update Heart Rate Zones">
|
||||||
</form>
|
</form>
|
||||||
</li>
|
</li>
|
||||||
<li class="grid_2">
|
|
||||||
<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;">
|
|
||||||
Please correct the error{{ powerzonesform.errors|pluralize }} below.
|
|
||||||
{{ powerzonesform.non_field_errors }}
|
|
||||||
|
|
||||||
</p>
|
|
||||||
{% endif %}
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>ID</th><th>Zone Name</th><th>Lower Boundary (Watt)</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>1</td><td>{{ powerzonesform.ut3name }}</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>2</td><td>{{ powerzonesform.ut2name }}</td>
|
|
||||||
<td>{{ powerzonesform.pw_ut2 }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>3</td><td>{{ powerzonesform.ut1name }}</td>
|
|
||||||
<td>{{ powerzonesform.pw_ut1 }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>4</td><td>{{ powerzonesform.atname }}</td>
|
|
||||||
<td>{{ powerzonesform.pw_at }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>5</td><td>{{ powerzonesform.trname }}</td>
|
|
||||||
<td>{{ powerzonesform.pw_tr }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>6</td><td>{{ powerzonesform.anname }}</td>
|
|
||||||
<td>{{ powerzonesform.pw_an }}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
{% csrf_token %}
|
|
||||||
<div class="grid_2 prefix_2 suffix_2">
|
|
||||||
<input type="submit" value="Update Power Zones">
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</li>
|
|
||||||
<li class="grid_2">
|
|
||||||
<form enctype="multipart/form-data" action="" method="post">
|
|
||||||
<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 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>
|
|
||||||
<table>
|
|
||||||
{{ powerform.as_table }}
|
|
||||||
</table>
|
|
||||||
{% csrf_token %}
|
|
||||||
<input type="submit" value="Update">
|
|
||||||
</form>
|
|
||||||
</li>
|
|
||||||
<li class="grid_2">
|
|
||||||
<form enctype="multipart/form-data" action="" method="post">
|
|
||||||
<h2>Fitness and Performance Manager Settings</h2>
|
|
||||||
<p>Use this form to change the parameters affecting your performance management.</p>
|
|
||||||
<p>A shorter range for the CP calculations
|
|
||||||
will give you notifications of fitness improvements more often,
|
|
||||||
but will also quickly forget those breakthrough workouts. Shorter decay
|
|
||||||
time constants for the performance manager will model a quicker building up
|
|
||||||
of fitness and a faster recovery. Recommended values are 42 days (fitness)
|
|
||||||
and 7 days (fatigue).</p>
|
|
||||||
<table>
|
|
||||||
{{ cpform.as_table }}
|
|
||||||
</table>
|
|
||||||
{% csrf_token %}
|
|
||||||
<input type="submit" value="Update">
|
|
||||||
</form>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1039,3 +1039,8 @@ def previousworkout(workout, user):
|
|||||||
return encoder.encode_hex(ws[0].id)
|
return encoder.encode_hex(ws[0].id)
|
||||||
else:
|
else:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
@register.filter
|
||||||
|
def otwslack(value, user):
|
||||||
|
r = Rower.objects.get(user=user)
|
||||||
|
return int(value*(100.-r.otwslack)/100.)
|
||||||
|
|||||||
@@ -618,13 +618,23 @@ def rower_prefs_view(request, userid=0, message=""):
|
|||||||
hrftp = int((r.an+r.tr)/2.)
|
hrftp = int((r.an+r.tr)/2.)
|
||||||
ftp = cd['ftp']
|
ftp = cd['ftp']
|
||||||
otwslack = cd['otwslack']
|
otwslack = cd['otwslack']
|
||||||
|
cogganzones = cd['cogganzones']
|
||||||
|
|
||||||
powerfrac = 100*np.array([r.pw_ut2,
|
powerfrac = 100*np.array([r.pw_ut2,
|
||||||
r.pw_ut1,
|
r.pw_ut1,
|
||||||
r.pw_at,
|
r.pw_at,
|
||||||
r.pw_tr, r.pw_an])/r.ftp
|
r.pw_tr, r.pw_an])/r.ftp
|
||||||
|
if cogganzones:
|
||||||
|
powerfrac = np.array([55.,75.,90.,105.,120.])
|
||||||
|
powerzones = ['Rest',
|
||||||
|
'Active Recovery',
|
||||||
|
'Endurance',
|
||||||
|
'Tempo',
|
||||||
|
'Threshold',
|
||||||
|
'Anaerobic']
|
||||||
|
r.powerzones = powerzones
|
||||||
|
|
||||||
r.ftp = max(min(ftp, 650), 50)
|
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)
|
ut2, ut1, at, tr, an = (r.ftp*powerfrac/100.).astype(int)
|
||||||
r.pw_ut2 = ut2
|
r.pw_ut2 = ut2
|
||||||
r.pw_ut1 = ut1
|
r.pw_ut1 = ut1
|
||||||
@@ -632,7 +642,10 @@ def rower_prefs_view(request, userid=0, message=""):
|
|||||||
r.pw_tr = tr
|
r.pw_tr = tr
|
||||||
r.pw_an = an
|
r.pw_an = an
|
||||||
r.hrftp = hrftp
|
r.hrftp = hrftp
|
||||||
|
r.otwslack = max(min(otwslack, 50), 0)
|
||||||
r.save()
|
r.save()
|
||||||
|
powerzonesform = RowerPowerZonesForm(instance=r)
|
||||||
|
|
||||||
message = "FTP and/or OTW slack values changed."
|
message = "FTP and/or OTW slack values changed."
|
||||||
messages.info(request, message)
|
messages.info(request, message)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user