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)
|
||||
except ValueError: # pragma: no cover
|
||||
return pd.DataFrame()
|
||||
# df = dd.concat(data,axis=0)
|
||||
|
||||
else:
|
||||
try:
|
||||
|
||||
@@ -6283,7 +6283,15 @@ def thumbnails_set(r, id, favorites):
|
||||
columns += ['time']
|
||||
rowdata = dataprep.getsmallrowdata_db(columns, ids=[id], doclean=True)
|
||||
|
||||
try:
|
||||
rowdata.dropna(axis=1, how='all', inplace=True)
|
||||
except TypeError:
|
||||
return [
|
||||
{'script': "",
|
||||
'div': "",
|
||||
'notes': ""
|
||||
}]
|
||||
|
||||
|
||||
if rowdata.empty:
|
||||
try:
|
||||
@@ -6303,12 +6311,6 @@ def thumbnails_set(r, id, favorites):
|
||||
'notes': ""
|
||||
}]
|
||||
|
||||
# else:
|
||||
# try:
|
||||
# rowdata.sort_values(by='time',ascending=True,inplace=True)
|
||||
# except KeyError:
|
||||
# pass
|
||||
|
||||
lengte = len(rowdata)
|
||||
maxlength = 50
|
||||
if lengte > maxlength:
|
||||
|
||||
@@ -964,6 +964,7 @@ class Rower(models.Model):
|
||||
# Power Zone Data
|
||||
ftp = models.IntegerField(
|
||||
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")
|
||||
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")
|
||||
|
||||
powerzones = PowerZonesField(default=['Rest',
|
||||
'Pwr UT2',
|
||||
'Pwr UT1',
|
||||
'Pwr AT',
|
||||
'Pwr TR',
|
||||
'Pwr AN'])
|
||||
'Active Recovery',
|
||||
'Endurance',
|
||||
'Tempo',
|
||||
'Threshold',
|
||||
'Anaerobic'])
|
||||
|
||||
hrzones = PowerZonesField(default=['Rest',
|
||||
'UT2',
|
||||
@@ -4224,7 +4225,7 @@ class RowerExportForm(ModelForm):
|
||||
class RowerPowerForm(ModelForm):
|
||||
class Meta:
|
||||
model = Rower
|
||||
fields = ['hrftp', 'ftp', 'otwslack']
|
||||
fields = ['hrftp', 'ftp', 'otwslack','cogganzones']
|
||||
|
||||
|
||||
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>
|
||||
|
||||
<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">
|
||||
<p>
|
||||
<h2>Heart Rate Zones</h2>
|
||||
@@ -62,92 +159,6 @@
|
||||
<input type="submit" value="Update Heart Rate Zones">
|
||||
</form>
|
||||
</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>
|
||||
|
||||
|
||||
|
||||
@@ -1039,3 +1039,8 @@ def previousworkout(workout, user):
|
||||
return encoder.encode_hex(ws[0].id)
|
||||
else:
|
||||
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.)
|
||||
ftp = cd['ftp']
|
||||
otwslack = cd['otwslack']
|
||||
cogganzones = cd['cogganzones']
|
||||
|
||||
powerfrac = 100*np.array([r.pw_ut2,
|
||||
r.pw_ut1,
|
||||
r.pw_at,
|
||||
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.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
|
||||
@@ -632,7 +642,10 @@ def rower_prefs_view(request, userid=0, message=""):
|
||||
r.pw_tr = tr
|
||||
r.pw_an = an
|
||||
r.hrftp = hrftp
|
||||
r.otwslack = max(min(otwslack, 50), 0)
|
||||
r.save()
|
||||
powerzonesform = RowerPowerZonesForm(instance=r)
|
||||
|
||||
message = "FTP and/or OTW slack values changed."
|
||||
messages.info(request, message)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user