139 lines
3.7 KiB
Python
139 lines
3.7 KiB
Python
import polars as pl
|
|
import datetime
|
|
import arrow
|
|
import numpy as np
|
|
|
|
from rowers.dataprep import rscore_approx
|
|
|
|
from rowers.models import Rower, Workout
|
|
|
|
def weightfromrecord(row,metricchoice):
|
|
vv = row[metricchoice][0]
|
|
if vv > 0:
|
|
return vv
|
|
if metricchoice == 'rscore': # pragma: no cover
|
|
return rscore_approx(row)
|
|
|
|
return 0 # pragma: no cover
|
|
|
|
|
|
def getfatigues(df, fatigues, fitnesses, dates, impulses, startdate, kfatigue, kfitness,actualfitness=0, actualfatigue=0):
|
|
fatigue = actualfatigue
|
|
fitness = actualfitness
|
|
impulses = []
|
|
|
|
for f in fatigues:
|
|
impulses.append(0)
|
|
|
|
lambda_a = 2/(kfatigue+1)
|
|
lambda_c = 2/(kfitness+1)
|
|
|
|
enddate = datetime.date.today()
|
|
nrdays = (enddate - startdate).days
|
|
|
|
for i in range(nrdays+1):
|
|
date = startdate + datetime.timedelta(days=i)
|
|
datekey = date.strftime('%Y-%m-%d')
|
|
weight = 0
|
|
|
|
try:
|
|
df2 = df.filter(pl.col('date') == date)
|
|
if type(df2) == pl.Series:
|
|
weight += weightfromrecord(df2, 'rscore')
|
|
else:
|
|
for row in df2.iter_slices(n_rows=1):
|
|
weight += weightfromrecord(row, 'rscore')
|
|
except KeyError:
|
|
pass
|
|
|
|
impulses.append(weight)
|
|
|
|
fatigue = (1 - lambda_a) * fatigue + lambda_a * weight
|
|
fitness = (1 - lambda_c) * fitness + lambda_c * weight
|
|
|
|
fatigues.append(fatigue)
|
|
fitnesses.append(fitness)
|
|
dates.append(arrow.get(date).datetime)
|
|
|
|
return fatigues, fitnesses, dates, impulses
|
|
|
|
def calculate_fitness(rower, reset=False):
|
|
try:
|
|
w_last = Workout.objects.get(id=rower.last_workout)
|
|
datetime_last = w_last.startdatetime
|
|
except Workout.DoesNotExist:
|
|
w_last = None
|
|
datetime_last = datetime.datetime.now() - datetime.timedelta(days=90)
|
|
|
|
if reset:
|
|
rower.last_workout = 0
|
|
rower.actualfit = 0
|
|
rower.actualfatigue = 0
|
|
rower.save()
|
|
datetime_last = datetime.datetime.now() - datetime.timedelta(days=90)
|
|
|
|
workouts = Workout.objects.filter(user=rower, startdatetime__gt=datetime_last,
|
|
duplicate=False).order_by('date').exclude(id=rower.last_workout)
|
|
|
|
kfitness = rower.kfit
|
|
kfatigue = rower.kfatigue
|
|
actualfitness = rower.actualfit
|
|
actualfatigue = rower.actualfatigue
|
|
|
|
records = []
|
|
|
|
for w in workouts:
|
|
dd = {
|
|
'date': w.date,
|
|
'trimp': w.trimp,
|
|
'rscore': w.rscore,
|
|
'hrtss':w.hrtss,
|
|
'duration': w.duration,
|
|
'id': w.id,
|
|
'rpe': w.rpe,
|
|
}
|
|
records.append(dd)
|
|
|
|
df = pl.from_records(records)
|
|
if df.is_empty():
|
|
return actualfitness, actualfatigue
|
|
|
|
dates = [arrow.get(w.date).datetime for w in workouts]
|
|
impulses = [np.nan for w in workouts]
|
|
fitnesses = [np.nan for w in workouts]
|
|
fatigues = [np.nan for w in workouts]
|
|
|
|
|
|
|
|
fatigues, fitnesses, dates, impulses = getfatigues(
|
|
df,
|
|
fatigues,
|
|
fitnesses,
|
|
dates,
|
|
impulses,
|
|
datetime.date.today()-datetime.timedelta(days=90),
|
|
kfatigue, kfitness,
|
|
actualfitness=actualfitness,
|
|
actualfatigue=actualfatigue,
|
|
)
|
|
|
|
df = pl.DataFrame({
|
|
'date': dates,
|
|
'fatigue': fatigues,
|
|
'fitness': fitnesses,
|
|
'impulse': impulses,
|
|
})
|
|
|
|
endfitness = fitnesses[-1]
|
|
endfatigue = fatigues[-1]
|
|
|
|
if workouts:
|
|
enddate = workouts.last().date
|
|
rower.last_workout = workouts.last().id
|
|
rower.actualfit = int(endfitness)
|
|
rower.actualfatigue = int(endfatigue)
|
|
rower.save()
|
|
|
|
return endfitness, endfatigue
|
|
|