Private
Public Access
1
0
Files
rowsandall/rowers/fitness.py
2025-06-02 20:24:46 +02:00

143 lines
3.8 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)
if not datetime_last:
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