monitoring ftp
This commit is contained in:
@@ -721,23 +721,33 @@ def update_rolling_cp(r, types, mode='water'):
|
|||||||
powerdf.drop_duplicates(subset='Delta', keep='first', inplace=True)
|
powerdf.drop_duplicates(subset='Delta', keep='first', inplace=True)
|
||||||
|
|
||||||
res2 = datautils.cpfit(powerdf)
|
res2 = datautils.cpfit(powerdf)
|
||||||
|
p1 = res2[0]
|
||||||
|
# calculate FTP
|
||||||
|
hourseconds = 3600.
|
||||||
|
pwr = p1[0]/(1+hourseconds/p1[2])
|
||||||
|
pwr += p1[1]/(1+hourseconds/p1[3])
|
||||||
|
|
||||||
if len(powerdf) != 0:
|
if len(powerdf) != 0:
|
||||||
if mode == 'water':
|
if mode == 'water':
|
||||||
p1 = res2[0]
|
|
||||||
r.p0 = p1[0]
|
r.p0 = p1[0]
|
||||||
r.p1 = p1[1]
|
r.p1 = p1[1]
|
||||||
r.p2 = p1[2]
|
r.p2 = p1[2]
|
||||||
r.p3 = p1[3]
|
r.p3 = p1[3]
|
||||||
r.cpratio = res2[3]
|
r.cpratio = res2[3]
|
||||||
r.save()
|
r.save()
|
||||||
|
if pwr > r.ftp*(100.-r.otwslack)/100. and r.getemailnotifications and not r.emailbounced:
|
||||||
|
_ = myqueue(queuehigh, handle_sendemail_newftp(r,pwr,'water'))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
p1 = res2[0]
|
|
||||||
r.ep0 = p1[0]
|
r.ep0 = p1[0]
|
||||||
r.ep1 = p1[1]
|
r.ep1 = p1[1]
|
||||||
r.ep2 = p1[2]
|
r.ep2 = p1[2]
|
||||||
r.ep3 = p1[3]
|
r.ep3 = p1[3]
|
||||||
r.ecpratio = res2[3]
|
r.ecpratio = res2[3]
|
||||||
r.save()
|
r.save()
|
||||||
|
if pwr > r.ftp and r.getemailnotifications and not r.emailbounced:
|
||||||
|
_ = myqueue(queuehigh, handle_sendemail_newftp(r,pwr,'water'))
|
||||||
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -4237,9 +4237,21 @@ class SimpleRowerPowerForm(ModelForm):
|
|||||||
return super(SimpleRowerPowerForm, self).save(*args, **kwargs)
|
return super(SimpleRowerPowerForm, self).save(*args, **kwargs)
|
||||||
|
|
||||||
class RowerPowerForm(ModelForm):
|
class RowerPowerForm(ModelForm):
|
||||||
|
otwftp = forms.IntegerField(initial=0,required=False, label='FTP on water')
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Rower
|
model = Rower
|
||||||
fields = ['hrftp', 'ftp', 'otwslack','cogganzones']
|
fields = ['hrftp', 'ftp','cogganzones']
|
||||||
|
|
||||||
|
field_order = ['hrftp', 'ftp', 'otwftp', 'cogganzones']
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(RowerPowerForm, self).__init__(*args, **kwargs)
|
||||||
|
self.initial['otwftp'] = int((1-0.01*self.instance.otwslack)*self.instance.ftp)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
otwslack = -100.*(self.cleaned_data['otwftp']-self.cleaned_data['ftp'])/(self.cleaned_data['ftp'])
|
||||||
|
self.instance.otwslack = otwslack
|
||||||
|
return super(RowerPowerForm, self).save(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class RowerCPForm(ModelForm):
|
class RowerCPForm(ModelForm):
|
||||||
|
|||||||
@@ -1712,6 +1712,24 @@ def handle_sendemail_expired(useremail, userfirstname, userlastname, expireddate
|
|||||||
d, cc=['support@rowsandall.com'], **kwargs)
|
d, cc=['support@rowsandall.com'], **kwargs)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
@app.task
|
||||||
|
def handle_sendemail_newftp(power,rower,mode, **kwargs):
|
||||||
|
subject = "You may want to update your FTP on rowsandall.com"
|
||||||
|
from_email = 'Rowsandall <info@rowsandall.com>'
|
||||||
|
|
||||||
|
d = {
|
||||||
|
'first_name': rower.user.first_name,
|
||||||
|
'last_name': rower.user.last_name,
|
||||||
|
'siteurl': siteurl,
|
||||||
|
'ftp': r.ftp,
|
||||||
|
'newftp': power,
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = send_template_email(from_email, [r.user.email],
|
||||||
|
subject, 'newftpemail.html',
|
||||||
|
d, **kwargs)
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
@app.task
|
@app.task
|
||||||
def handle_sendemail_breakthrough(workoutid, useremail,
|
def handle_sendemail_breakthrough(workoutid, useremail,
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
{% load rowerfilters %}
|
{% load rowerfilters %}
|
||||||
<h1><a href="/rowers/me/edit/">Profile</a></h1>
|
<h1><a href="/rowers/me/edit/">Profile</a></h1>
|
||||||
<ul class="cd-accordion-menu animated">
|
<ul class="cd-accordion-menu animated">
|
||||||
<li id="manage-prefs">
|
<li id="manage-prefs-simple">
|
||||||
<a href="/rowers/me/preferences/">
|
<a href="/rowers/me/prefs/">
|
||||||
<i class="fas fa-cog fa-fw"></i> Zones & Fitness
|
<i class="fas fa-sliders-v-square fa-fw"></i> Threshold
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li id="manage-impex">
|
<li id="manage-impex">
|
||||||
@@ -27,6 +27,11 @@
|
|||||||
<i class="fas fa-tachometer-alt-slow fa-fw"></i> Manage Workflow
|
<i class="fas fa-tachometer-alt-slow fa-fw"></i> Manage Workflow
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li id="manage-prefs">
|
||||||
|
<a href="/rowers/me/preferences/">
|
||||||
|
<i class="fas fa-cog fa-fw"></i> Zones & Fitness, detailed
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
{% if user.is_authenticated and user.is_staff %}
|
{% if user.is_authenticated and user.is_staff %}
|
||||||
<li id="manage-transactions">
|
<li id="manage-transactions">
|
||||||
<a href="/rowers/me/transactions/">
|
<a href="/rowers/me/transactions/">
|
||||||
|
|||||||
@@ -17,6 +17,19 @@
|
|||||||
<input type="submit" value="Update">
|
<input type="submit" value="Update">
|
||||||
</form>
|
</form>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="grid_2">
|
||||||
|
<p>
|
||||||
|
The Functional Threshold Power (FTP) is the power you can hold
|
||||||
|
for an hour all out. If you haven't done a full out hour, you
|
||||||
|
can also take a full out 20 minutes effort and take 95% of it.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If you do not row with a power meter on the water, the FTP on
|
||||||
|
water is irrelevant. If you do not know your 20 minute or full
|
||||||
|
hour full out power value on the water, take 85% of your indoor
|
||||||
|
rowing value.
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ class UserPreferencesTest(TestCase):
|
|||||||
form_data = {
|
form_data = {
|
||||||
'hrftp': 160,
|
'hrftp': 160,
|
||||||
'ftp':230,
|
'ftp':230,
|
||||||
'otwslack':14
|
'otwftp':224
|
||||||
}
|
}
|
||||||
|
|
||||||
form = RowerPowerForm(form_data)
|
form = RowerPowerForm(form_data)
|
||||||
|
|||||||
@@ -242,6 +242,7 @@ from rowers.rows import handle_uploaded_file, handle_uploaded_image
|
|||||||
from rowers.plannedsessions import *
|
from rowers.plannedsessions import *
|
||||||
from rowers.tasks import handle_makeplot, handle_otwsetpower, handle_sendemailtcx, handle_sendemailcsv
|
from rowers.tasks import handle_makeplot, handle_otwsetpower, handle_sendemailtcx, handle_sendemailcsv
|
||||||
from rowers.tasks import (
|
from rowers.tasks import (
|
||||||
|
handle_sendemail_newftp,
|
||||||
instroke_static,
|
instroke_static,
|
||||||
fetch_rojabo_session,
|
fetch_rojabo_session,
|
||||||
handle_sendemail_unrecognized, handle_sendemailnewcomment,
|
handle_sendemail_unrecognized, handle_sendemailnewcomment,
|
||||||
|
|||||||
@@ -650,14 +650,13 @@ def rower_prefs_view(request, userid=0, message=""):
|
|||||||
successmessage = "Your Heart Rate data were changed"
|
successmessage = "Your Heart Rate data were changed"
|
||||||
messages.info(request, successmessage)
|
messages.info(request, successmessage)
|
||||||
elif request.method == 'POST' and "ftp" in request.POST:
|
elif request.method == 'POST' and "ftp" in request.POST:
|
||||||
powerform = RowerPowerForm(request.POST)
|
powerform = RowerPowerForm(request.POST, instance=r)
|
||||||
if powerform.is_valid():
|
if powerform.is_valid():
|
||||||
|
powerform.save(commit=True)
|
||||||
cd = powerform.cleaned_data
|
cd = powerform.cleaned_data
|
||||||
hrftp = cd['hrftp']
|
hrftp = cd['hrftp']
|
||||||
if hrftp == 0: # pragma: no cover
|
if hrftp == 0: # pragma: no cover
|
||||||
hrftp = int((r.an+r.tr)/2.)
|
hrftp = int((r.an+r.tr)/2.)
|
||||||
ftp = cd['ftp']
|
|
||||||
otwslack = cd['otwslack']
|
|
||||||
cogganzones = cd['cogganzones']
|
cogganzones = cd['cogganzones']
|
||||||
|
|
||||||
powerfrac = 100*np.array([r.pw_ut2,
|
powerfrac = 100*np.array([r.pw_ut2,
|
||||||
@@ -674,7 +673,6 @@ def rower_prefs_view(request, userid=0, message=""):
|
|||||||
'Anaerobic']
|
'Anaerobic']
|
||||||
r.powerzones = powerzones
|
r.powerzones = powerzones
|
||||||
|
|
||||||
r.ftp = max(min(ftp, 650), 50)
|
|
||||||
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
|
||||||
@@ -682,7 +680,6 @@ 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)
|
powerzonesform = RowerPowerZonesForm(instance=r)
|
||||||
|
|
||||||
|
|||||||
@@ -156,7 +156,7 @@
|
|||||||
</li>
|
</li>
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
<li>
|
<li>
|
||||||
<a href="/rowers/me/preferences/" title="Profile">
|
<a href="/rowers/me/prefs/" title="Profile">
|
||||||
{% if user.rower.rowerplan == 'pro' %}
|
{% if user.rower.rowerplan == 'pro' %}
|
||||||
<i class="fas fa-user-ninja "></i>
|
<i class="fas fa-user-ninja "></i>
|
||||||
{% elif 'coach' in user.rower.rowerplan %}
|
{% elif 'coach' in user.rower.rowerplan %}
|
||||||
|
|||||||
Reference in New Issue
Block a user