Merge branch 'release/v14.98'
This commit is contained in:
33541
coverage.xml
Normal file
33541
coverage.xml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1102,6 +1102,62 @@ def workout_goldmedalstandard(workout):
|
|||||||
else:
|
else:
|
||||||
return 0,0
|
return 0,0
|
||||||
|
|
||||||
|
def check_marker(workout):
|
||||||
|
r = workout.user
|
||||||
|
gmstandard,gmseconds = workout_goldmedalstandard(workout)
|
||||||
|
if gmseconds<60:
|
||||||
|
return None
|
||||||
|
|
||||||
|
dd = arrow.get(workout.date).datetime-datetime.timedelta(days=r.kfit)
|
||||||
|
ws = Workout.objects.filter(date__gte=dd,
|
||||||
|
date__lte=workout.date,
|
||||||
|
user=r,duplicate=False,
|
||||||
|
workouttype__in=mytypes.rowtypes,
|
||||||
|
).order_by("date")
|
||||||
|
ids = []
|
||||||
|
gms = []
|
||||||
|
for w in ws:
|
||||||
|
gmstandard,gmseconds = workout_goldmedalstandard(w)
|
||||||
|
if gmseconds>60:
|
||||||
|
ids.append(w.id)
|
||||||
|
gms.append(gmstandard)
|
||||||
|
|
||||||
|
df = pd.DataFrame({
|
||||||
|
'id':ids,
|
||||||
|
'gms':gms,
|
||||||
|
})
|
||||||
|
|
||||||
|
if df.empty:
|
||||||
|
workout.ranking = True
|
||||||
|
workout.save()
|
||||||
|
return workout
|
||||||
|
|
||||||
|
indexmax = df['gms'].idxmax()
|
||||||
|
theid = df.loc[indexmax,'id']
|
||||||
|
|
||||||
|
wmax = Workout.objects.get(id=theid)
|
||||||
|
gms_max = wmax.goldmedalstandard
|
||||||
|
|
||||||
|
# check if equal, bigger, or smaller than previous
|
||||||
|
if not wmax.rankingpiece:
|
||||||
|
rankingworkouts = ws.filter(rankingpiece=True)
|
||||||
|
if len(rankingworkouts) == 0:
|
||||||
|
wmax.rankingpiece = True
|
||||||
|
wmax.save()
|
||||||
|
return wmax
|
||||||
|
|
||||||
|
lastranking = rankingworkouts[len(rankingworkouts)-1]
|
||||||
|
if lastranking.goldmedalstandard+0.2 < wmax.goldmedalstandard:
|
||||||
|
wmax.rankingpiece = True
|
||||||
|
wmax.save()
|
||||||
|
return wmax
|
||||||
|
else:
|
||||||
|
return wmax
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def calculate_goldmedalstandard(rower,workout,recurrance=True):
|
def calculate_goldmedalstandard(rower,workout,recurrance=True):
|
||||||
cpfile = 'media/cpdata_{id}.parquet.gz'.format(id=workout.id)
|
cpfile = 'media/cpdata_{id}.parquet.gz'.format(id=workout.id)
|
||||||
try:
|
try:
|
||||||
@@ -1187,28 +1243,30 @@ def fetchcp_new(rower,workouts):
|
|||||||
try:
|
try:
|
||||||
df = pd.read_parquet(cpfile)
|
df = pd.read_parquet(cpfile)
|
||||||
df['workout'] = str(workout)
|
df['workout'] = str(workout)
|
||||||
|
df['url'] = workout.url()
|
||||||
data.append(df)
|
data.append(df)
|
||||||
except:
|
except:
|
||||||
# CP data file doesn't exist yet. has to be created
|
# CP data file doesn't exist yet. has to be created
|
||||||
df, delta, cpvalues = setcp(workout)
|
df, delta, cpvalues = setcp(workout)
|
||||||
df['workout'] = str(workout)
|
df['workout'] = str(workout)
|
||||||
|
df['url'] = workout.url()
|
||||||
data.append(df)
|
data.append(df)
|
||||||
|
|
||||||
|
|
||||||
if len(data) == 0:
|
if len(data) == 0:
|
||||||
return pd.Series(),pd.Series(),0,pd.Series()
|
return pd.Series(),pd.Series(),0,pd.Series(),pd.Series()
|
||||||
if len(data)>1:
|
if len(data)>1:
|
||||||
df = pd.concat(data,axis=0)
|
df = pd.concat(data,axis=0)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
df = df[df['cp'] == df.groupby(['delta'])['cp'].transform('max')]
|
df = df[df['cp'] == df.groupby(['delta'])['cp'].transform('max')]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pd.Series(),pd.Series(),0,pd.DataFrame()
|
pd.Series(),pd.Series(),0,pd.Series(),pd.Series()
|
||||||
|
|
||||||
|
|
||||||
df = df.sort_values(['delta']).reset_index()
|
df = df.sort_values(['delta']).reset_index()
|
||||||
|
|
||||||
return df['delta'],df['cp'],0,df['workout']
|
return df['delta'],df['cp'],0,df['workout'],df['url']
|
||||||
|
|
||||||
def setcp(workout,background=False,recurrance=True):
|
def setcp(workout,background=False,recurrance=True):
|
||||||
filename = 'media/cpdata_{id}.parquet.gz'.format(id=workout.id)
|
filename = 'media/cpdata_{id}.parquet.gz'.format(id=workout.id)
|
||||||
@@ -1264,7 +1322,7 @@ def update_rolling_cp(r,types,mode='water'):
|
|||||||
user = r
|
user = r
|
||||||
)
|
)
|
||||||
|
|
||||||
delta, cp, avgpower, workoutnames = fetchcp_new(r,workouts)
|
delta, cp, avgpower, workoutnames,urls = fetchcp_new(r,workouts)
|
||||||
|
|
||||||
powerdf = pd.DataFrame({
|
powerdf = pd.DataFrame({
|
||||||
'Delta':delta,
|
'Delta':delta,
|
||||||
@@ -1470,6 +1528,9 @@ def checkbreakthrough(w, r):
|
|||||||
|
|
||||||
# submit email task to send email about breakthrough workout
|
# submit email task to send email about breakthrough workout
|
||||||
if isbreakthrough:
|
if isbreakthrough:
|
||||||
|
if not w.duplicate:
|
||||||
|
w.rankingpiece = True
|
||||||
|
w.save()
|
||||||
if r.getemailnotifications and not r.emailbounced:
|
if r.getemailnotifications and not r.emailbounced:
|
||||||
job = myqueue(queuehigh,handle_sendemail_breakthrough,
|
job = myqueue(queuehigh,handle_sendemail_breakthrough,
|
||||||
w.id,
|
w.id,
|
||||||
@@ -1480,6 +1541,9 @@ def checkbreakthrough(w, r):
|
|||||||
|
|
||||||
# submit email task to send email about breakthrough workout
|
# submit email task to send email about breakthrough workout
|
||||||
if ishard:
|
if ishard:
|
||||||
|
if not w.duplicate:
|
||||||
|
w.rankingpiece = True
|
||||||
|
w.save()
|
||||||
if r.getemailnotifications and not r.emailbounced:
|
if r.getemailnotifications and not r.emailbounced:
|
||||||
job = myqueue(queuehigh,handle_sendemail_hard,
|
job = myqueue(queuehigh,handle_sendemail_hard,
|
||||||
w.id,
|
w.id,
|
||||||
@@ -1724,6 +1788,8 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower',
|
|||||||
|
|
||||||
# check for duplicate start times and duration
|
# check for duplicate start times and duration
|
||||||
duplicate = checkduplicates(r,workoutdate,workoutstartdatetime,workoutenddatetime)
|
duplicate = checkduplicates(r,workoutdate,workoutstartdatetime,workoutenddatetime)
|
||||||
|
if duplicate:
|
||||||
|
rankingpiece = False
|
||||||
|
|
||||||
# test title length
|
# test title length
|
||||||
if title is not None and len(title)>140:
|
if title is not None and len(title)>140:
|
||||||
@@ -1771,6 +1837,7 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower',
|
|||||||
job = myqueue(queuehigh,handle_calctrimp,w.id,f2,r.ftp,r.sex,r.hrftp,r.max,r.rest)
|
job = myqueue(queuehigh,handle_calctrimp,w.id,f2,r.ftp,r.sex,r.hrftp,r.max,r.rest)
|
||||||
|
|
||||||
isbreakthrough, ishard = checkbreakthrough(w, r)
|
isbreakthrough, ishard = checkbreakthrough(w, r)
|
||||||
|
marker = check_marker(w)
|
||||||
|
|
||||||
return (w.id, message)
|
return (w.id, message)
|
||||||
|
|
||||||
|
|||||||
@@ -721,14 +721,14 @@ class PerformanceManagerForm(forms.Form):
|
|||||||
label='End Date')
|
label='End Date')
|
||||||
|
|
||||||
metricchoices = (
|
metricchoices = (
|
||||||
('trimp','Use Heart Rate Data'),
|
('hrtss','Use Heart Rate Data'),
|
||||||
('rscore','Use Power and Heart Rate Data'),
|
('rscore','Use Power and Heart Rate Data'),
|
||||||
)
|
)
|
||||||
|
|
||||||
metricchoice = forms.ChoiceField(
|
metricchoice = forms.ChoiceField(
|
||||||
required=True,
|
required=True,
|
||||||
choices=metricchoices,
|
choices=metricchoices,
|
||||||
initial='trimp',
|
initial='hrtss',
|
||||||
label='Data',
|
label='Data',
|
||||||
widget=forms.RadioSelect
|
widget=forms.RadioSelect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ from pandas.core.groupby.groupby import DataError
|
|||||||
|
|
||||||
def newtestpower(x):
|
def newtestpower(x):
|
||||||
try:
|
try:
|
||||||
if abs(x['testpower'] - x['testdup']) < 0.2:
|
if abs(x['testpower'] - x['testdup']) <= 0.2:
|
||||||
return np.nan
|
return np.nan
|
||||||
except (AttributeError,TypeError):
|
except (AttributeError,TypeError):
|
||||||
return np.nan
|
return np.nan
|
||||||
@@ -132,6 +132,14 @@ def newtestpowerdate(x):
|
|||||||
|
|
||||||
return x['date']
|
return x['date']
|
||||||
|
|
||||||
|
def workoutname(id):
|
||||||
|
try:
|
||||||
|
w = Workout.objects.get(id=id)
|
||||||
|
except Workout.DoesNotExist:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
return str(w)
|
||||||
|
|
||||||
def all_goldmedalstandards(workouts,startdate,enddate):
|
def all_goldmedalstandards(workouts,startdate,enddate):
|
||||||
dates = []
|
dates = []
|
||||||
testpowers = []
|
testpowers = []
|
||||||
@@ -182,34 +190,21 @@ def build_goldmedalstandards(workouts,kfitness):
|
|||||||
|
|
||||||
df.sort_values(['workoutdt'],inplace=True)
|
df.sort_values(['workoutdt'],inplace=True)
|
||||||
|
|
||||||
#for id, row in df.iterrows():
|
|
||||||
# d = row['workoutdt']
|
|
||||||
# dd = d-datetime.timedelta(days=90)
|
|
||||||
# mask = df['workoutdt']>dd
|
|
||||||
# mask2 = df['workoutdt']<=d
|
|
||||||
# df2 = df.where(mask & mask2)
|
|
||||||
# powertest = df2['goldmedalstandard'].max()
|
|
||||||
# idx = df2['goldmedalstandard'].argmax()
|
|
||||||
# durationtest = df2['goldmedalduration'].values[idx]
|
|
||||||
# dates.append(d)
|
|
||||||
# testpower.append(powertest)
|
|
||||||
# testduration.append(durationtest)
|
|
||||||
# fatigues.append(np.nan)
|
|
||||||
# fitnesses.append(np.nan)
|
|
||||||
|
|
||||||
for w in workouts:
|
for w in workouts:
|
||||||
ids = [w.id for w in workouts.filter(date__gte=w.date-datetime.timedelta(days=42),
|
ids = [ww.id for ww in workouts.filter(date__gte=w.date-datetime.timedelta(days=42),
|
||||||
date__lte=w.date)]
|
date__lte=w.date)]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
powerdf = df[df['workout'].isin(ids)]
|
powerdf = df[df['workout'].isin(ids)]
|
||||||
indexmax = powerdf['goldmedalstandard'].idxmax()
|
indexmax = powerdf['goldmedalstandard'].idxmax()
|
||||||
theid = powerdf.loc[indexmax,'workout']
|
theid = powerdf.loc[indexmax,'workout']
|
||||||
powertest = powerdf['goldmedalstandard'].max()
|
powertest = powerdf['goldmedalstandard'].max()
|
||||||
durationtest = powerdf.loc[indexmax,'goldmedalduration']
|
durationtest = powerdf.loc[indexmax,'goldmedalduration']
|
||||||
|
|
||||||
|
w2 = Workout.objects.get(id=theid)
|
||||||
dates.append(arrow.get(w.date).datetime)
|
dates.append(arrow.get(w2.date).datetime)
|
||||||
if powertest > 0:
|
if powertest > 0:
|
||||||
testpower.append(powertest)
|
testpower.append(powertest)
|
||||||
testduration.append(durationtest)
|
testduration.append(durationtest)
|
||||||
@@ -1756,34 +1751,26 @@ def getfatigues(
|
|||||||
lambda_c = 2/(kfitness+1)
|
lambda_c = 2/(kfitness+1)
|
||||||
nrdays = (enddate-startdate).days
|
nrdays = (enddate-startdate).days
|
||||||
|
|
||||||
factor = 1.0
|
|
||||||
if metricchoice == 'rscore':
|
|
||||||
factor = 2.0
|
|
||||||
|
|
||||||
for i in range(nrdays+1):
|
for i in range(nrdays+1):
|
||||||
date = startdate+datetime.timedelta(days=i)
|
date = startdate+datetime.timedelta(days=i)
|
||||||
ws = Workout.objects.filter(user=user.rower,date=date,duplicate=False)
|
ws = Workout.objects.filter(user=user.rower,date=date,duplicate=False)
|
||||||
weight = 0
|
weight = 0
|
||||||
|
|
||||||
for w in ws:
|
for w in ws:
|
||||||
if getattr(w,metricchoice) > 0:
|
if getattr(w,metricchoice) > 0:
|
||||||
weight += factor*getattr(w,metricchoice)
|
weight += getattr(w,metricchoice)
|
||||||
if getattr(w,metricchoice) <= 0:
|
if getattr(w,metricchoice) <= 0:
|
||||||
if metricchoice == 'rscore' and w.hrtss > 0:
|
if metricchoice == 'rscore' and w.hrtss > 0:
|
||||||
weight+= factor*w.hrtss
|
weight+= w.hrtss
|
||||||
elif metricchoice == 'rscore' and w.hrtss <= 0:
|
else:
|
||||||
trimp,hrtss = dataprep.workout_trimp(w)
|
trimp,hrtss = dataprep.workout_trimp(w)
|
||||||
rscore,normp = dataprep.workout_rscore(w)
|
rscore,normp = dataprep.workout_rscore(w)
|
||||||
if w.rpe and w.rpe > 0:
|
if w.rpe and w.rpe > 0:
|
||||||
dd = 3600*w.duration.hour+60*w.duration.minute+w.duration.second
|
dd = 3600*w.duration.hour+60*w.duration.minute+w.duration.second
|
||||||
dd = dd/3600
|
dd = dd/3600
|
||||||
weight += factor*rpetotss[w.rpe]*dd
|
weight += rpetotss[w.rpe]*dd
|
||||||
elif metricchoice == 'trimp' and w.trimp <= 0:
|
|
||||||
trimp,hrtss = dataprep.workout_trimp(w)
|
|
||||||
rscore,normp = dataprep.workout_rscore(w)
|
|
||||||
if w.rpe and w.rpe > 0:
|
|
||||||
dd = 3600*w.duration.hour+60*w.duration.minute+w.duration.second
|
|
||||||
dd = dd/3600
|
|
||||||
weight += 2*rpetotss[w.rpe]*dd
|
|
||||||
|
|
||||||
impulses.append(weight)
|
impulses.append(weight)
|
||||||
|
|
||||||
@@ -1808,15 +1795,18 @@ def goldmedalscorechart(user,startdate=None,enddate=None):
|
|||||||
|
|
||||||
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'
|
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'
|
||||||
|
|
||||||
|
# marker workouts
|
||||||
workouts = Workout.objects.filter(user=user.rower,date__gte=startdate,
|
workouts = Workout.objects.filter(user=user.rower,date__gte=startdate,
|
||||||
date__lte=enddate,
|
date__lte=enddate,
|
||||||
workouttype__in=mytypes.rowtypes,
|
workouttype__in=mytypes.rowtypes,
|
||||||
duplicate=False)
|
duplicate=False).order_by('date')
|
||||||
|
|
||||||
# marker workouts
|
markerworkouts = workouts.filter(rankingpiece=True)
|
||||||
dates,testpower,testduration,fatigues,fitnesses,impulses, outids = build_goldmedalstandards(
|
outids = [w.id for w in markerworkouts]
|
||||||
workouts,42
|
dates = [arrow.get(w.date).datetime for w in markerworkouts]
|
||||||
)
|
testpower = [w.goldmedalstandard if w.rankingpiece else np.nan for w in markerworkouts]
|
||||||
|
|
||||||
|
testduration = [w.goldmedalseconds if w.rankingpiece else 0 for w in markerworkouts]
|
||||||
|
|
||||||
df = pd.DataFrame({
|
df = pd.DataFrame({
|
||||||
'id':outids,
|
'id':outids,
|
||||||
@@ -1826,8 +1816,8 @@ def goldmedalscorechart(user,startdate=None,enddate=None):
|
|||||||
})
|
})
|
||||||
df.sort_values(['date'],inplace=True)
|
df.sort_values(['date'],inplace=True)
|
||||||
|
|
||||||
df['testdup'] = df['testpower'].shift(1)
|
#df['testdup'] = df['testpower'].shift(1)
|
||||||
df['testpower'] = df.apply(lambda x: newtestpower(x),axis=1)
|
#df['testpower'] = df.apply(lambda x: newtestpower(x),axis=1)
|
||||||
#df['date'] = df.apply(lambda x: newtestpowerdate(x), axis=1)
|
#df['date'] = df.apply(lambda x: newtestpowerdate(x), axis=1)
|
||||||
|
|
||||||
|
|
||||||
@@ -1842,6 +1832,7 @@ def goldmedalscorechart(user,startdate=None,enddate=None):
|
|||||||
|
|
||||||
# all workouts
|
# all workouts
|
||||||
alldates,alltestpower,allduration = all_goldmedalstandards(workouts,startdate,enddate)
|
alldates,alltestpower,allduration = all_goldmedalstandards(workouts,startdate,enddate)
|
||||||
|
allids = [w.id for w in workouts]
|
||||||
|
|
||||||
nrdays = (enddate-startdate).days
|
nrdays = (enddate-startdate).days
|
||||||
|
|
||||||
@@ -1850,6 +1841,7 @@ def goldmedalscorechart(user,startdate=None,enddate=None):
|
|||||||
score = []
|
score = []
|
||||||
markerduration = []
|
markerduration = []
|
||||||
duration = []
|
duration = []
|
||||||
|
workoutid = []
|
||||||
|
|
||||||
previous = 0
|
previous = 0
|
||||||
|
|
||||||
@@ -1863,6 +1855,7 @@ def goldmedalscorechart(user,startdate=None,enddate=None):
|
|||||||
markerduration.append(testduration[i])
|
markerduration.append(testduration[i])
|
||||||
score.append(np.nan)
|
score.append(np.nan)
|
||||||
duration.append(np.nan)
|
duration.append(np.nan)
|
||||||
|
workoutid.append(id)
|
||||||
|
|
||||||
for i in range(len(alldates)):
|
for i in range(len(alldates)):
|
||||||
td.append(arrow.get(alldates[i]).datetime)
|
td.append(arrow.get(alldates[i]).datetime)
|
||||||
@@ -1870,6 +1863,7 @@ def goldmedalscorechart(user,startdate=None,enddate=None):
|
|||||||
score.append(alltestpower[i])
|
score.append(alltestpower[i])
|
||||||
markerduration.append(np.nan)
|
markerduration.append(np.nan)
|
||||||
duration.append(allduration[i])
|
duration.append(allduration[i])
|
||||||
|
workoutid.append(allids[i])
|
||||||
|
|
||||||
for i in range(nrdays+1):
|
for i in range(nrdays+1):
|
||||||
td.append(arrow.get(startdate+datetime.timedelta(days=i)).datetime)
|
td.append(arrow.get(startdate+datetime.timedelta(days=i)).datetime)
|
||||||
@@ -1877,6 +1871,7 @@ def goldmedalscorechart(user,startdate=None,enddate=None):
|
|||||||
score.append(np.nan)
|
score.append(np.nan)
|
||||||
markerduration.append(np.nan)
|
markerduration.append(np.nan)
|
||||||
duration.append(np.nan)
|
duration.append(np.nan)
|
||||||
|
workoutid.append(0)
|
||||||
|
|
||||||
|
|
||||||
df = pd.DataFrame({
|
df = pd.DataFrame({
|
||||||
@@ -1885,6 +1880,7 @@ def goldmedalscorechart(user,startdate=None,enddate=None):
|
|||||||
'score':score,
|
'score':score,
|
||||||
'duration':duration,
|
'duration':duration,
|
||||||
'date':td,
|
'date':td,
|
||||||
|
'id':workoutid,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@@ -1893,6 +1889,9 @@ def goldmedalscorechart(user,startdate=None,enddate=None):
|
|||||||
df = df.groupby(['date']).max()
|
df = df.groupby(['date']).max()
|
||||||
df['date'] = df.index.values
|
df['date'] = df.index.values
|
||||||
|
|
||||||
|
df['url'] = df['id'].apply(lambda x:settings.SITE_URL+'/rowers/workout/{id}/'.format(id=encoder.encode_hex(x)))
|
||||||
|
df['workout'] = df['id'].apply(lambda x:workoutname(x))
|
||||||
|
|
||||||
|
|
||||||
source = ColumnDataSource(
|
source = ColumnDataSource(
|
||||||
data = dict(
|
data = dict(
|
||||||
@@ -1902,6 +1901,8 @@ def goldmedalscorechart(user,startdate=None,enddate=None):
|
|||||||
duration = df['duration'].apply(lambda x:totaltime_sec_to_string(x,shorten=True)),
|
duration = df['duration'].apply(lambda x:totaltime_sec_to_string(x,shorten=True)),
|
||||||
date = df['date'],
|
date = df['date'],
|
||||||
fdate = df['date'].map(lambda x: x.strftime('%d-%m-%Y')),
|
fdate = df['date'].map(lambda x: x.strftime('%d-%m-%Y')),
|
||||||
|
url = df['url'],
|
||||||
|
workout = df['workout']
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1961,8 +1962,12 @@ def goldmedalscorechart(user,startdate=None,enddate=None):
|
|||||||
('Score','@score{int}'),
|
('Score','@score{int}'),
|
||||||
('Duration', '@duration'),
|
('Duration', '@duration'),
|
||||||
('Date','@fdate'),
|
('Date','@fdate'),
|
||||||
|
('Workout','@workout')
|
||||||
])
|
])
|
||||||
|
|
||||||
|
taptool = plot.select(type=TapTool)
|
||||||
|
taptool.callback = OpenURL(url='@url')
|
||||||
|
|
||||||
script, div = components(plot)
|
script, div = components(plot)
|
||||||
|
|
||||||
return script, div,outids
|
return script, div,outids
|
||||||
@@ -1994,42 +1999,20 @@ def performance_chart(user,startdate=None,enddate=None,kfitness=42,kfatigue=7,
|
|||||||
|
|
||||||
outids = []
|
outids = []
|
||||||
|
|
||||||
if showtests:
|
|
||||||
workouts = Workout.objects.filter(user=user.rower,date__gte=startdate,
|
|
||||||
date__lte=enddate,
|
|
||||||
workouttype__in=mytypes.rowtypes,
|
|
||||||
duplicate=False)
|
|
||||||
dates,testpower,testduration,fatigues,fitnesses,impulses, outids = build_goldmedalstandards(
|
|
||||||
workouts,kfitness
|
|
||||||
)
|
|
||||||
|
|
||||||
df = pd.DataFrame({
|
workouts = Workout.objects.filter(user=user.rower,date__gte=startdate,
|
||||||
'id': outids,
|
date__lte=enddate,
|
||||||
'date':dates,
|
workouttype__in=mytypes.rowtypes,
|
||||||
'testpower':testpower,
|
duplicate=False).order_by('date')
|
||||||
'testduration':testduration,
|
|
||||||
'fatigue':fatigues,
|
|
||||||
'fitness':fitnesses,
|
|
||||||
'impulse':impulses,
|
|
||||||
})
|
|
||||||
df.sort_values(['date'],inplace=True)
|
|
||||||
df['testdup'] = df['testpower'].shift(1)
|
|
||||||
df['testpower'] = df.apply(lambda x: newtestpower(x),axis=1)
|
|
||||||
df['id'] = df.apply(lambda x: newtestpowerid(x),axis=1)
|
|
||||||
|
|
||||||
#try:
|
markerworkouts = workouts.filter(rankingpiece=True)
|
||||||
# df['testpower'].iloc[-1] = df['testdup'].iloc[-1]
|
outids = [w.id for w in markerworkouts]
|
||||||
#except IndexError:
|
dates = [arrow.get(w.date).datetime for w in workouts]
|
||||||
# pass
|
testpower = [w.goldmedalstandard if w.rankingpiece else np.nan for w in workouts]
|
||||||
|
impulses = [np.nan for w in workouts]
|
||||||
|
testduration = [w.goldmedalseconds if w.rankingpiece else 0 for w in workouts]
|
||||||
dates = [d for d in df['date']]
|
fitnesses = [np.nan for w in workouts]
|
||||||
testpower = df['testpower'].values.tolist()
|
fatigues = [np.nan for w in workouts]
|
||||||
fatigues = df['fatigue'].values.tolist()
|
|
||||||
fitnesses = df['fitness'].values.tolist()
|
|
||||||
testduration = df['testduration'].values.tolist()
|
|
||||||
impulses = df['impulse'].tolist()
|
|
||||||
outids = df['id'].unique()
|
|
||||||
|
|
||||||
fatigues,fitnesses,dates,testpower,testduration,impulses = getfatigues(fatigues,
|
fatigues,fitnesses,dates,testpower,testduration,impulses = getfatigues(fatigues,
|
||||||
fitnesses,
|
fitnesses,
|
||||||
@@ -2041,7 +2024,6 @@ def performance_chart(user,startdate=None,enddate=None,kfitness=42,kfatigue=7,
|
|||||||
kfatigue,kfitness)
|
kfatigue,kfitness)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
df = pd.DataFrame({
|
df = pd.DataFrame({
|
||||||
'date':dates,
|
'date':dates,
|
||||||
'testpower':testpower,
|
'testpower':testpower,
|
||||||
@@ -3914,6 +3896,8 @@ def interactive_otwcpchart(powerdf,promember=0,rowername="",r=None,cpfit='data',
|
|||||||
deltas = fitt.apply(lambda x: timedeltaconv(x))
|
deltas = fitt.apply(lambda x: timedeltaconv(x))
|
||||||
ftime = niceformat(deltas)
|
ftime = niceformat(deltas)
|
||||||
workouts = powerdf['workout']
|
workouts = powerdf['workout']
|
||||||
|
urls = powerdf['url']
|
||||||
|
|
||||||
|
|
||||||
sourcecomplex = ColumnDataSource(
|
sourcecomplex = ColumnDataSource(
|
||||||
data = dict(
|
data = dict(
|
||||||
@@ -3922,6 +3906,7 @@ def interactive_otwcpchart(powerdf,promember=0,rowername="",r=None,cpfit='data',
|
|||||||
duration = fitt/60.,
|
duration = fitt/60.,
|
||||||
ftime = ftime,
|
ftime = ftime,
|
||||||
workout = workouts,
|
workout = workouts,
|
||||||
|
url = urls,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -3985,6 +3970,9 @@ def interactive_otwcpchart(powerdf,promember=0,rowername="",r=None,cpfit='data',
|
|||||||
|
|
||||||
hover.mode = 'mouse'
|
hover.mode = 'mouse'
|
||||||
|
|
||||||
|
taptool = plot.select(type=TapTool)
|
||||||
|
taptool.callback = OpenURL(url='@url')
|
||||||
|
|
||||||
plot.line('duration','CP',source=sourcecomplex,legend_label="CP Model",
|
plot.line('duration','CP',source=sourcecomplex,legend_label="CP Model",
|
||||||
color='green')
|
color='green')
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import datetime
|
|||||||
#from rules.contrib.models import RulesModel
|
#from rules.contrib.models import RulesModel
|
||||||
|
|
||||||
from rowers.rower_rules import *
|
from rowers.rower_rules import *
|
||||||
|
from rowers.opaque import encoder
|
||||||
|
|
||||||
from rowers.rows import validate_file_extension
|
from rowers.rows import validate_file_extension
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
@@ -2992,6 +2993,13 @@ class Workout(models.Model):
|
|||||||
duplicate = models.BooleanField(default=False,verbose_name='Duplicate Workout')
|
duplicate = models.BooleanField(default=False,verbose_name='Duplicate Workout')
|
||||||
impeller = models.BooleanField(default=False,verbose_name='Impeller')
|
impeller = models.BooleanField(default=False,verbose_name='Impeller')
|
||||||
|
|
||||||
|
def url(self):
|
||||||
|
str = '/rowers/workout/{id}/'.format(
|
||||||
|
id = encoder.encode_hex(self.id)
|
||||||
|
)
|
||||||
|
url = settings.SITE_URL+str
|
||||||
|
return url
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
user = self.user
|
user = self.user
|
||||||
if self.notes is not None and len(self.notes)>1000:
|
if self.notes is not None and len(self.notes)>1000:
|
||||||
|
|||||||
@@ -80,6 +80,8 @@
|
|||||||
|
|
||||||
<ul class="main-content">
|
<ul class="main-content">
|
||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
|
<p>Hover over the workout to see details, click on the workout to open in a
|
||||||
|
separate page.</p>
|
||||||
<div id="id_chart">
|
<div id="id_chart">
|
||||||
{{ the_div|safe }}
|
{{ the_div|safe }}
|
||||||
</div>
|
</div>
|
||||||
@@ -129,6 +131,9 @@
|
|||||||
</table>
|
</table>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<li class="grid_4">
|
||||||
|
<a href="/rowers/createmarkerworkouts/user/{{ rower.user.id }}/">Automatically generate marker workouts</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -182,6 +182,9 @@
|
|||||||
</table>
|
</table>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<li class="grid_4">
|
||||||
|
<a href="/rowers/createmarkerworkouts/user/{{ rower.user.id }}/">Automatically generate marker workouts</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -355,6 +355,10 @@ urlpatterns = [
|
|||||||
re_path(r'^fitness-fit/$',views.fitness_from_cp_view,name='fitness_from_cp_view'),
|
re_path(r'^fitness-fit/$',views.fitness_from_cp_view,name='fitness_from_cp_view'),
|
||||||
re_path(r'^fitness-fit/user/(?P<userid>\d+)/$',views.fitness_from_cp_view,name='fitness_from_cp_view'),
|
re_path(r'^fitness-fit/user/(?P<userid>\d+)/$',views.fitness_from_cp_view,name='fitness_from_cp_view'),
|
||||||
re_path(r'^fitness-fit/user/(?P<userid>\d+)/(?P<mode>\w+.*)/$',views.fitness_from_cp_view,name='fitness_from_cp_view'),
|
re_path(r'^fitness-fit/user/(?P<userid>\d+)/(?P<mode>\w+.*)/$',views.fitness_from_cp_view,name='fitness_from_cp_view'),
|
||||||
|
re_path(r'^createmarkerworkouts/user/(?P<userid>\d+)/$',views.create_marker_workouts_view,
|
||||||
|
name='create_marker_workouts_view'),
|
||||||
|
re_path(r'^createmarkerworkouts/$',views.create_marker_workouts_view,
|
||||||
|
name='create_marker_workouts_view'),
|
||||||
re_path(r'^goldmedalscores/$',views.goldmedalscores_view,name='goldmedalscores_view'),
|
re_path(r'^goldmedalscores/$',views.goldmedalscores_view,name='goldmedalscores_view'),
|
||||||
re_path(r'^goldmedalscores/user/(?P<userid>\d+)/$',views.goldmedalscores_view,name='goldmedalscores_view'),
|
re_path(r'^goldmedalscores/user/(?P<userid>\d+)/$',views.goldmedalscores_view,name='goldmedalscores_view'),
|
||||||
re_path(r'^goldmedalscores/user/(?P<userid>\d+)/(?P<mode>\w+.*)/$',views.goldmedalscores_view,name='goldmedalscores_view'),
|
re_path(r'^goldmedalscores/user/(?P<userid>\d+)/(?P<mode>\w+.*)/$',views.goldmedalscores_view,name='goldmedalscores_view'),
|
||||||
|
|||||||
@@ -525,12 +525,13 @@ def cpdata(workouts, options):
|
|||||||
|
|
||||||
|
|
||||||
ids = [w.id for w in workouts]
|
ids = [w.id for w in workouts]
|
||||||
delta, cpvalue, avgpower,workoutnames = dataprep.fetchcp_new(r,workouts)
|
delta, cpvalue, avgpower,workoutnames,urls = dataprep.fetchcp_new(r,workouts)
|
||||||
|
|
||||||
powerdf = pd.DataFrame({
|
powerdf = pd.DataFrame({
|
||||||
'Delta':delta,
|
'Delta':delta,
|
||||||
'CP':cpvalue,
|
'CP':cpvalue,
|
||||||
'workout':workoutnames,
|
'workout':workoutnames,
|
||||||
|
'url':urls,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@@ -1543,6 +1544,29 @@ def fitnessmetric_view(request,userid=0,mode='rower',
|
|||||||
'form':form,
|
'form':form,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@user_passes_test(ispromember, login_url="/rowers/paidplans",
|
||||||
|
message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality",
|
||||||
|
redirect_field_name=None)
|
||||||
|
def create_marker_workouts_view(request,userid=0,
|
||||||
|
startdate=timezone.now()-timezone.timedelta(days=365),
|
||||||
|
enddate=timezone.now()):
|
||||||
|
therower = getrequestrower(request,userid=userid)
|
||||||
|
theuser = therower.user
|
||||||
|
|
||||||
|
workouts = Workout.objects.filter(user=theuser.rower,date__gte=startdate,
|
||||||
|
date__lte=enddate,
|
||||||
|
workouttype__in=mytypes.rowtypes,
|
||||||
|
duplicate=False).order_by('date')
|
||||||
|
|
||||||
|
for workout in workouts:
|
||||||
|
w2 = dataprep.check_marker(workout)
|
||||||
|
|
||||||
|
url = reverse('goldmedalscores_view',
|
||||||
|
kwargs={
|
||||||
|
'userid':userid,
|
||||||
|
})
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
@user_passes_test(ispromember, login_url="/rowers/paidplans",
|
@user_passes_test(ispromember, login_url="/rowers/paidplans",
|
||||||
message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality",
|
message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality",
|
||||||
redirect_field_name=None)
|
redirect_field_name=None)
|
||||||
|
|||||||
Reference in New Issue
Block a user