Private
Public Access
1
0

adding apprimxate_rscore

This commit is contained in:
Sander Roosendaal
2021-05-03 11:04:27 +02:00
parent 7078842242
commit a379c92a9c
7 changed files with 158 additions and 79 deletions

View File

@@ -43,7 +43,7 @@ def get_contacts(rower):
return r['id'] return r['id']
return None return None # pragma: no cover
# this should be triggered on braintree payment # this should be triggered on braintree payment
def create_contact(rower): def create_contact(rower):

View File

@@ -2357,6 +2357,7 @@ class PlannedSession(models.Model):
approximate_distance = models.IntegerField(default=0,verbose_name='Approximate Distance') approximate_distance = models.IntegerField(default=0,verbose_name='Approximate Distance')
approximate_duration = models.IntegerField(default=0,verbose_name='Approximate Duration') approximate_duration = models.IntegerField(default=0,verbose_name='Approximate Duration')
approximate_rscore = models.IntegerField(default=0,verbose_name='Approximate rScore')
max_nr_of_workouts = models.IntegerField( max_nr_of_workouts = models.IntegerField(
default=0,verbose_name='Maximum number of workouts' default=0,verbose_name='Maximum number of workouts'
@@ -2508,14 +2509,17 @@ class PlannedSession(models.Model):
# calculate approximate distance # calculate approximate distance
if self.steps: if self.steps:
sdict, totalmeters, totalseconds = ps_dict_order(self.steps) sdict, totalmeters, totalseconds, totalrscore = ps_dict_order(self.steps)
self.approximate_distance = int(totalmeters) self.approximate_distance = int(totalmeters)
self.approximate_duration = int(totalseconds/60.) self.approximate_duration = int(totalseconds/60.)
self.approximate_rscore = int(totalrscore)
self.criterium = 'none' self.criterium = 'none'
if self.sessionmode == 'time': if self.sessionmode == 'time':
self.sessionvalue = self.approximate_duration self.sessionvalue = self.approximate_duration
elif self.sessionmode == 'distance': # pragma: no cover elif self.sessionmode == 'distance': # pragma: no cover
self.sessionvalue = self.approximate_distance self.sessionvalue = self.approximate_distance
elif self.sessionmode == 'rscore': # pragma: no cover
self.sessionvalue = self.approximate_rscore
super(PlannedSession,self).save(*args, **kwargs) super(PlannedSession,self).save(*args, **kwargs)

View File

@@ -86,7 +86,7 @@ from rowers.tasks import (
from rowers.utils import totaltime_sec_to_string from rowers.utils import totaltime_sec_to_string
def ps_dict_get_description(d,short=False): # pragma: no cover def ps_dict_get_description(d,short=False): # pragma: no cover
sdict,totalmeters,totalseconds = ps_dict_order(d,short=short) sdict,totalmeters,totalseconds,totalrscore = ps_dict_order(d,short=short)
s = '' s = ''
for item in sdict: for item in sdict:
s += item['string']+'\n' s += item['string']+'\n'
@@ -94,7 +94,7 @@ def ps_dict_get_description(d,short=False): # pragma: no cover
return s return s
def ps_dict_get_description_html(d,short=False): def ps_dict_get_description_html(d,short=False):
sdict,totalmeters,totalseconds = ps_dict_order(d,short=short) sdict,totalmeters,totalseconds,totalrscore = ps_dict_order(d,short=short)
s = '<ul>' s = '<ul>'

View File

@@ -144,7 +144,7 @@ def createsporttracksworkoutdata(w):
duration += w.duration.minute*60 duration += w.duration.minute*60
duration += w.duration.second duration += w.duration.second
duration += +1.0e-6*w.duration.microsecond duration += +1.0e-6*w.duration.microsecond
except AttributeError: except AttributeError: # pragma: no cover
return 0 return 0
# adding diff, trying to see if this is valid # adding diff, trying to see if this is valid

View File

@@ -1912,6 +1912,24 @@ description: ""
response = download_fit(request,filename=self.ps_trimp.fitfile) response = download_fit(request,filename=self.ps_trimp.fitfile)
self.assertTrue('File not found' in context.exception) self.assertTrue('File not found' in context.exception)
@patch('rowers.garmin_stuff.requests.post', side_effect=mocked_requests)
@patch('rowers.utils.requests.post', side_effect=mocked_requests)
@patch('rowers.garmin_stuff.OAuth1Session', side_effect=MockOAuth1Session)
def test_plannedsession_steps_power(self,mockpost,mock_post,MockOAuth1Session):
self.ps_trimp.interval_string = '30min@200W'
self.ps_trimp.save()
self.assertEqual(self.ps_trimp.approximate_rscore,50)
@patch('rowers.garmin_stuff.requests.post', side_effect=mocked_requests)
@patch('rowers.utils.requests.post', side_effect=mocked_requests)
@patch('rowers.garmin_stuff.OAuth1Session', side_effect=MockOAuth1Session)
def test_plannedsession_steps_spm(self,mockpost,mock_post,MockOAuth1Session):
self.ps_trimp.interval_string = '60min@18spm'
self.ps_trimp.save()
self.assertEqual(self.ps_trimp.approximate_rscore,72)
def test_plannedsessions_dateform_view(self): def test_plannedsessions_dateform_view(self):
login = self.c.login(username=self.u.username, password=self.password) login = self.c.login(username=self.u.username, password=self.password)

View File

@@ -585,13 +585,14 @@ def steps_write_fit(steps):
return filename return filename
def step_to_time_dist(step,avgspeed = 3.7): def step_to_time_dist(step,avgspeed = 3.2,ftp=200,ftspm=25,ftv=3.7):
seconds = 0 seconds = 0
distance = 0 distance = 0
rscore = 0
durationtype = step['durationType'] durationtype = step['durationType']
if step['durationValue'] == 0: # pragma: no cover if step['durationValue'] == 0: # pragma: no cover
return 0,0 return 0,0,0
try: try:
targettype = step['targetType'] targettype = step['targetType']
@@ -607,39 +608,125 @@ def step_to_time_dist(step,avgspeed = 3.7):
if targettype == 'Speed': if targettype == 'Speed':
value = step['targetValue'] value = step.get('targetValue',0)
valuelow = step['targetValueLow'] valuelow = step.get('targetValueLow',0)
valuehigh = step['targetValueHigh'] valuehigh = step.get('targetValueHigh',0)
velomid = 0.
if value != 0: # pragma: no cover if value != 0:
distance = seconds*value distance = seconds*value/1000.
velomid = value/1000.
elif valuelow != 0 and valuehigh != 0: # pragma: no cover elif valuelow != 0 and valuehigh != 0: # pragma: no cover
distance = seconds*(valuelow+valuehigh)/2. distance = seconds*(valuelow+valuehigh)/2.
velomid = (valuelow+valuehigh)/2000.
return seconds,distance veloratio = (velomid/ftv)**(3.0)
rscoreperhour = 100.*veloratio
rscore = rscoreperhour*seconds/3600.
if targettype == 'Power':
value = step.get('targetValue',0)
valuelow = step.get('targetValueLow',0)
valuehigh = step.get('targetValueHigh',0)
if value != 0:
if value < 10 and value > 0: # pragma: no cover
targetpower = ftp*0.6
elif value > 10 and value < 1000: # pragma: no cover
targetpower = value*ftp/100.
elif value > 1000:
targetpower = value-1000
avgspeed = ftv*(targetpower/ftp)**(1./3.)
distance = avgspeed*seconds
avgpower = targetpower
if valuelow != 0 and valuehigh != 0: # pragma: no cover
avgpower = (valuelow+valuehigh)/2.
avgspeed = ftv*(avgspeed/ftv)**(1./3.)
distance = avgspeed*seconds
rscore = 100.*(avgpower/ftp)*seconds/3600.
if targettype == 'Cadence':
value = step.get('targetValue',0)
valuelow = step.get('targetValueLow',0)
valuehigh = step.get('targetValueHigh',0)
if value != 0:
avgpower = ftp*value/ftspm
if valuelow != 0 and valuehigh != 0: # pragma: no cover
avgspm = (valuelow+valuehigh)/2.
avgpower = ftp*avgspm/ftspm
rscore = 100*(avgpower/ftp)*seconds/3600.
return seconds,distance,rscore
elif durationtype == 'Distance': # pragma: no cover elif durationtype == 'Distance': # pragma: no cover
value = step['durationValue'] value = step['durationValue']
distance = value/100. distance = value/100.
seconds = distance/avgspeed seconds = distance/avgspeed
if targettype == 'Speed': if targettype == 'Speed':
value = step['targetValue'] value = step.get('targetValue',0)
valuelow = step['targetValueLow'] valuelow = step.get('targetValueLow',0)
valuehigh = step['targetValueHigh'] valuehigh = step.get('targetValueHigh',0)
velomid = 0
if value != 0: # pragma: no cover if value != 0: # pragma: no cover
seconds = distance/value seconds = distance/value
velomid = value/1000.
elif valuelow != 0 and valuehigh != 0: # pragma: no cover elif valuelow != 0 and valuehigh != 0: # pragma: no cover
midspeed = (valuelow+valuehigh)/2. velomid = (valuelow+valuehigh)/2000.
seconds = distance/midspeed seconds = distance/velomid
return seconds, distance veloratio = (velomid/ftv)**(3.0)
rscoreperhour = 100.*veloratio
rscore = rscoreperhour*seconds/3600.
if targettype == 'Power':
value = step.get('targetValue',0)
valuelow = step.get('targetValueLow',0)
valuehigh = step.get('targetValueHigh',0)
if value != 0:
if value < 10 and value > 0:
targetpower = ftp*0.6
elif value > 10 and value < 1000:
targetpower = value*ftp/100.
elif value > 1000:
targetpower = value-1000
avgspeed = ftv*(targetpower/ftp)**(1./3.)
seconds = distance/avgspeed
avgpower = targetpower
if valuelow != 0 and valuehigh != 0:
avgpower = (valuelow+valuehigh)/2.
avgspeed = ftv*(avgspeed/ftv)**(1./3.)
seconds = distance/avgspeed
rscore = 100.*(avgpower/ftp)*seconds/3600.
if targettype == 'Cadence':
value = step.get('targetValue',0)
valuelow = step.get('targetValueLow',0)
valuehigh = step.get('targetValueHigh',0)
if value != 0:
avgpower = ftp*value/ftspm
if valuelow != 0 and valuehigh != 0:
avgspm = (valuelow+valuehigh)/2.
avgpower = ftp*avgspm/ftspm
rscore = 100*(avgpower/ftp)*seconds/3600.
return seconds, distance, rscore
elif durationtype in ['PowerLessThan','PowerGreaterThan','HrLessThan','HrGreaterThan']: # pragma: no cover elif durationtype in ['PowerLessThan','PowerGreaterThan','HrLessThan','HrGreaterThan']: # pragma: no cover
seconds = 600 seconds = 600
distance = seconds*avgspeed distance = seconds*avgspeed
return seconds,distance veloratio = (avgspeed/ftv)**(3.0)
rscoreperhour = 100.*veloratio
rscore = rscoreperhour*seconds/3600.
return seconds,distance return seconds,distance,rscore
return seconds,distance, rscore
def get_step_type(step): # pragma: no cover def get_step_type(step): # pragma: no cover
t = 'WorkoutStep' t = 'WorkoutStep'
@@ -677,7 +764,7 @@ def ps_dict_order_dict(d,short=False):
sdicts = [] sdicts = []
for step in steps: for step in steps:
sstring, type, stepID, repeatID, repeatValue = step_to_string(step,short=short) sstring, type, stepID, repeatID, repeatValue = step_to_string(step,short=short)
seconds, meters = step_to_time_dist(step) seconds, meters,rscore = step_to_time_dist(step)
sdict = { sdict = {
'type':type, 'type':type,
@@ -698,7 +785,7 @@ def ps_dict_order(d,short=False):
for step in steps: for step in steps:
sstring, type, stepID, repeatID, repeatValue = step_to_string(step,short=short) sstring, type, stepID, repeatID, repeatValue = step_to_string(step,short=short)
seconds, meters = step_to_time_dist(step) seconds, meters,rscore = step_to_time_dist(step)
sdict[stepID] = { sdict[stepID] = {
'string':sstring, 'string':sstring,
@@ -708,6 +795,7 @@ def ps_dict_order(d,short=False):
'repeatValue': repeatValue, 'repeatValue': repeatValue,
'seconds': seconds, 'seconds': seconds,
'meters': meters, 'meters': meters,
'rscore': rscore,
} }
@@ -715,7 +803,7 @@ def ps_dict_order(d,short=False):
for step in steps: for step in steps:
sstring, type, stepID, repeatID, repeatValue = step_to_string(step,short=short) sstring, type, stepID, repeatID, repeatValue = step_to_string(step,short=short)
seconds, meters = step_to_time_dist(step) seconds, meters, rscore = step_to_time_dist(step)
sdict[stepID] = { sdict[stepID] = {
'string':sstring, 'string':sstring,
@@ -725,6 +813,7 @@ def ps_dict_order(d,short=False):
'repeatValue': repeatValue, 'repeatValue': repeatValue,
'seconds': seconds, 'seconds': seconds,
'meters': meters, 'meters': meters,
'rscore': rscore,
} }
sdict2 = collections.OrderedDict(reversed(list(sdict.items()))) sdict2 = collections.OrderedDict(reversed(list(sdict.items())))
@@ -736,6 +825,7 @@ def ps_dict_order(d,short=False):
spaces = '' spaces = ''
totalmeters = 0 totalmeters = 0
totalseconds = 0 totalseconds = 0
totalrscore = 0
factor = 1 factor = 1
for key, item in sdict2.items(): for key, item in sdict2.items():
@@ -750,6 +840,7 @@ def ps_dict_order(d,short=False):
sdict3.append(item) sdict3.append(item)
totalmeters += factor*item['meters'] totalmeters += factor*item['meters']
totalseconds += factor*item['seconds'] totalseconds += factor*item['seconds']
totalrscore += factor*item['rscore']
if len(holduntil)>0 and item['stepID'] <= holduntil[-1]: if len(holduntil)>0 and item['stepID'] <= holduntil[-1]:
if item['stepID'] == holduntil[-1]: if item['stepID'] == holduntil[-1]:
sdict3.append(hold.pop()) sdict3.append(hold.pop())
@@ -772,7 +863,7 @@ def ps_dict_order(d,short=False):
sdict = list(reversed(sdict3)) sdict = list(reversed(sdict3))
return sdict,totalmeters,totalseconds return sdict,totalmeters,totalseconds,totalrscore
def step_to_string(step,short=False): def step_to_string(step,short=False):
type = 'Step' type = 'Step'
@@ -827,7 +918,7 @@ def step_to_string(step,short=False):
duration = 'until HR>{v}'.format(v=value/100) duration = 'until HR>{v}'.format(v=value/100)
elif durationtype == 'PowerLessThan': # pragma: no cover elif durationtype == 'PowerLessThan': # pragma: no cover
value = step['durationValue'] value = step['durationValue']
targetvalue = step['targetvalue'] targetvalue = step.get('targetValue',0)
if value <= 1000: if value <= 1000:
duration = 'Repeat until Power is less than {targetvalue} % of FTP'.format( duration = 'Repeat until Power is less than {targetvalue} % of FTP'.format(
targetvalue=targetvalue targetvalue=targetvalue
@@ -842,7 +933,7 @@ def step_to_string(step,short=False):
'until < {targetvalue} W'.format(targetvalue=targetvalue-1000) 'until < {targetvalue} W'.format(targetvalue=targetvalue-1000)
elif durationtype == 'PowerGreaterThan': # pragma: no cover elif durationtype == 'PowerGreaterThan': # pragma: no cover
value = step['durationValue'] value = step['durationValue']
targetvalue = step['targetvalue'] targetvalue = step.get('targetValue',0)
if value <= 1000: if value <= 1000:
duration = 'Repeat until Power is greater than {targetvalue} % of FTP'.format( duration = 'Repeat until Power is greater than {targetvalue} % of FTP'.format(
targetvalue=targetvalue targetvalue=targetvalue
@@ -860,10 +951,10 @@ def step_to_string(step,short=False):
ntimes = ': {v}x'.format(v=step['targetValue']) ntimes = ': {v}x'.format(v=step['targetValue'])
repeatID = step['durationValue'] repeatID = step['durationValue']
duration =ntimes duration =ntimes
repeatValue = step['targetValue'] repeatValue = step.get('targetValue',0)
elif durationtype == 'RepeatUntilHrGreaterThan': # pragma: no cover elif durationtype == 'RepeatUntilHrGreaterThan': # pragma: no cover
type = 'RepeatStep' type = 'RepeatStep'
targetvalue = step['targetValue'] targetvalue = step.get('targetValue',0)
if targetvalue <= 100: if targetvalue <= 100:
duration = 'Repeat until Heart Rate is greater than {targetvalue} % of max'.format( duration = 'Repeat until Heart Rate is greater than {targetvalue} % of max'.format(
targetvalue=targetvalue targetvalue=targetvalue
@@ -879,7 +970,7 @@ def step_to_string(step,short=False):
repeatID = step['durationValue'] repeatID = step['durationValue']
elif durationtype == 'RepeatUntilHrLessThan': # pragma: no cover elif durationtype == 'RepeatUntilHrLessThan': # pragma: no cover
type = 'RepeatStep' type = 'RepeatStep'
targetvalue = step['targetValue'] targetvalue = step.get('targetValue',0)
if targetvalue <= 100: if targetvalue <= 100:
duration = 'Repeat until Heart Rate is less than {targetvalue} % of max'.format( duration = 'Repeat until Heart Rate is less than {targetvalue} % of max'.format(
targetvalue=targetvalue targetvalue=targetvalue
@@ -903,18 +994,9 @@ def step_to_string(step,short=False):
targettype = None targettype = None
if targettype == 'HeartRate': # pragma: no cover if targettype == 'HeartRate': # pragma: no cover
try: value = step.get('targetValue',0)
value = step['targetValue'] valuelow = step.get('targetValueLow',0)
except KeyError: valuehigh = step.get('targetValueHigh',0)
value = 0
try:
valuelow = step['targetValueLow']
except KeyError:
valuelow = 0
try:
valuehigh = step['targetValueHigh']
except KeyError:
valuehigh = 0
if value < 10 and value>0: if value < 10 and value>0:
target = '@ HR zone {v}'.format(v=value) target = '@ HR zone {v}'.format(v=value)
@@ -930,18 +1012,9 @@ def step_to_string(step,short=False):
h = valuehigh - 100, h = valuehigh - 100,
) )
elif targettype == 'Power': # pragma: no cover elif targettype == 'Power': # pragma: no cover
try: value = step.get('targetValue',0)
value = step['targetValue'] valuelow = step.get('targetValueLow',0)
except KeyError: valuehigh = step.get('targetValueHigh',0)
value = 0
try:
valuelow = step['targetValueLow']
except KeyError:
valuelow = 0
try:
valuehigh = step['targetValueHigh']
except KeyError:
valuehigh = 0
if value < 10 and value>0: if value < 10 and value>0:
target = '@ Power zone {v}'.format(v=value) target = '@ Power zone {v}'.format(v=value)
@@ -961,18 +1034,10 @@ def step_to_string(step,short=False):
h = valuehigh-1000, h = valuehigh-1000,
) )
elif targettype == 'Speed': # pragma: no cover elif targettype == 'Speed': # pragma: no cover
try:
value = step['targetValue'] value = step.get('targetValue',0)
except KeyError: valuelow = step.get('targetValueLow',0)
value = 0 valuehigh = step.get('targetValueHigh',0)
try:
valuelow = step['targetValueLow']
except KeyError:
valuelow = 0
try:
valuehigh = step['targetValueHigh']
except KeyError:
valuehigh = 0
if value != 0: if value != 0:
v = value/1000. v = value/1000.
@@ -1004,18 +1069,9 @@ def step_to_string(step,short=False):
ph = pacestringhigh, ph = pacestringhigh,
) )
elif targettype == 'Cadence': # pragma: no cover elif targettype == 'Cadence': # pragma: no cover
try: value = step.get('targetValue',0)
value = step['targetValue'] valuelow = step.get('targetValueLow',0)
except KeyError: valuehigh = step.get('targetValueHigh',0)
value = 0
try:
valuelow = step['targetValueLow']
except KeyError:
valuelow = 0
try:
valuehigh = step['targetValueHigh']
except KeyError:
valuehigh = 0
if value != 0: if value != 0:
target = '@ {v} SPM'.format(v=value) target = '@ {v} SPM'.format(v=value)

View File

@@ -2380,6 +2380,7 @@ def plannedsession_view(request,id=0,userid=0):
'sessionmode','criterium', 'sessionmode','criterium',
'sessionvalue','sessionunit', 'sessionvalue','sessionunit',
'approximate_distance','approximate_duration', 'approximate_distance','approximate_duration',
'approximate_rscore',
'comment', 'comment',
], ],
'workouts': ws, 'workouts': ws,