408 lines
12 KiB
Python
408 lines
12 KiB
Python
# Python
|
|
from django.utils import timezone
|
|
from datetime import datetime
|
|
from datetime import timedelta
|
|
from datetime import date
|
|
import time
|
|
from django.db import IntegrityError
|
|
import uuid
|
|
from django.conf import settings
|
|
|
|
from utils import myqueue
|
|
|
|
import django_rq
|
|
queue = django_rq.get_queue('default')
|
|
queuelow = django_rq.get_queue('low')
|
|
queuehigh = django_rq.get_queue('low')
|
|
|
|
from rowers.models import (
|
|
Rower, Workout,Team,
|
|
GeoCourse, TrainingMicroCycle,TrainingMesoCycle,TrainingMacroCycle,
|
|
TrainingPlan,PlannedSession,
|
|
)
|
|
|
|
import metrics
|
|
import numpy as np
|
|
import dataprep
|
|
import courses
|
|
|
|
# Low Level functions - to be called by higher level methods
|
|
def add_workouts_plannedsession(ws,ps,r):
|
|
result = 0
|
|
comments = []
|
|
errors = []
|
|
|
|
# check if all sessions have same date
|
|
dates = [w.date for w in ws]
|
|
if (not all(d == dates[0] for d in dates)) and ps.sessiontype not in ['challenge','cycletarget']:
|
|
errors.append('For tests and training sessions, selected workouts must all be done on the same date')
|
|
return result,comments,errors
|
|
|
|
if len(ws)>1 and ps.sessiontype == 'test':
|
|
errors.append('For tests, you can only attach one workout')
|
|
return result,comments,errors
|
|
|
|
|
|
|
|
wold = Workout.objects.filter(plannedsession=ps,user=r)
|
|
ids = [w.id for w in wold] + [w.id for w in ws]
|
|
ids = list(set(ids))
|
|
|
|
if len(ids)>1 and ps.sessiontype in ['test','coursetest']:
|
|
errors.append('For tests, you can only attach one workout')
|
|
return result,comments,errors
|
|
|
|
# start adding sessions
|
|
for w in ws:
|
|
if w.date>=ps.startdate and w.date<=ps.enddate:
|
|
w.plannedsession = ps
|
|
w.save()
|
|
result += 1
|
|
comments.append('Attached workout %i to session' % w.id)
|
|
else:
|
|
errors.append('Workout %i did not match session dates' % w.id)
|
|
|
|
return result,comments,errors
|
|
|
|
|
|
def remove_workout_plannedsession(w,ps):
|
|
if w.plannedsession == ps:
|
|
w.plannedsession = None
|
|
w.save()
|
|
return 1
|
|
|
|
return 0
|
|
|
|
def clone_planned_session(ps):
|
|
ps.save()
|
|
ps.pk = None # creates new instance
|
|
ps.save()
|
|
|
|
def timefield_to_seconds_duration(t):
|
|
duration = t.hour*3600.
|
|
duration += t.minute * 60.
|
|
duration += t.second
|
|
duration += t.microsecond/1.e6
|
|
|
|
return duration
|
|
|
|
def get_session_metrics(ps):
|
|
rowers = ps.rower.all()
|
|
rscore = []
|
|
trimp = []
|
|
duration = []
|
|
distance = []
|
|
firstname = []
|
|
lastname = []
|
|
completedate = []
|
|
status = []
|
|
|
|
for r in rowers:
|
|
rscorev = 0
|
|
trimpv = 0
|
|
durationv = 0
|
|
distancev = 0
|
|
completedatev = ''
|
|
statusv = 0
|
|
|
|
ws = Workout.objects.filter(user=r,plannedsession=ps).order_by("date")
|
|
|
|
if len(ws) != 0:
|
|
for w in ws:
|
|
distancev += w.distance
|
|
durationv += timefield_to_seconds_duration(w.duration)
|
|
trimpv += dataprep.workout_trimp(w)
|
|
rscorev += dataprep.workout_rscore(w)[0]
|
|
|
|
ratio,statusv,completiondate = is_session_complete_ws(ws,ps)
|
|
try:
|
|
completedatev = completiondate.strftime('%Y-%m-%d')
|
|
except AttributeError:
|
|
completedatev = ''
|
|
durationv /= 60.
|
|
|
|
|
|
trimp.append(int(trimpv))
|
|
duration.append(int(durationv))
|
|
distance.append(int(distancev))
|
|
rscore.append(int(rscorev))
|
|
firstname.append(r.user.first_name)
|
|
lastname.append(r.user.last_name)
|
|
status.append(statusv)
|
|
completedate.append(completedatev)
|
|
|
|
thedict = {
|
|
'first_name':firstname,
|
|
'last_name':lastname,
|
|
'duration':duration,
|
|
'distance':distance,
|
|
'rscore':rscore,
|
|
'trimp':trimp,
|
|
'completedate':completedate,
|
|
'status':status,
|
|
}
|
|
|
|
return thedict
|
|
|
|
def is_session_complete_ws(ws,ps):
|
|
ws = ws.order_by("date")
|
|
if len(ws)==0:
|
|
today = date.today()
|
|
if today > ps.enddate:
|
|
status = 'missed'
|
|
ratio = 0
|
|
return ratio,status,None
|
|
else:
|
|
return 0,'not done',None
|
|
|
|
value = ps.sessionvalue
|
|
if ps.sessionunit == 'min':
|
|
value *= 60.
|
|
elif ps.sessionunit == 'km':
|
|
value *= 1000.
|
|
|
|
cratiomin = 1
|
|
cratiomax = 1
|
|
if ps.criterium == 'none':
|
|
if ps.sessiontype == 'session':
|
|
cratiomin = 0.8
|
|
cratiomax = 1.2
|
|
else:
|
|
cratiomin = 0.9167
|
|
cratiomax = 1.0833
|
|
|
|
|
|
score = 0
|
|
completiondate = None
|
|
for w in ws:
|
|
if ps.sessionmode == 'distance':
|
|
score += w.distance
|
|
elif ps.sessionmode == 'time':
|
|
durationseconds = timefield_to_seconds_duration(w.duration)
|
|
score += durationseconds
|
|
elif ps.sessionmode == 'TRIMP':
|
|
trimp = dataprep.workout_trimp(w)
|
|
score += trimp
|
|
elif ps.sessionmode == 'rScore':
|
|
rscore = dataprep.workout_rscore(w)[0]
|
|
score += rscore
|
|
if not completiondate and score>=cratiomin*value:
|
|
completiondate = w.date
|
|
|
|
ratio = score/float(value)
|
|
|
|
status = 'partial'
|
|
|
|
if ps.sessiontype in ['session','cycletarget']:
|
|
if ps.criterium == 'exact':
|
|
if ratio == 1.0:
|
|
return ratio,'completed',completiondate
|
|
else:
|
|
if not completiondate:
|
|
completiondate = ws.reverse()[0].date
|
|
return ratio,'partial',completiondate
|
|
elif ps.criterium == 'minimum':
|
|
if ratio >= 1.0:
|
|
return ratio,'completed',completiondate
|
|
else:
|
|
if not completiondate:
|
|
completiondate = ws.reverse()[0].date
|
|
|
|
return ratio,'partial',completiondate
|
|
else:
|
|
if ratio>cratiomin and ratio<cratiomax:
|
|
return ratio,'completed',completiondate
|
|
else:
|
|
completiondate = ws.reverse()[0].date
|
|
return ratio,'partial',completiondate
|
|
elif ps.sessiontype == 'test':
|
|
if ratio==1.0:
|
|
return ratio,'completed',completiondate
|
|
else:
|
|
return ratio,'partial',completiondate
|
|
elif ps.sessiontype == 'challenge':
|
|
if ps.criterium == 'exact':
|
|
if ratio == 1.0:
|
|
return ratio,'completed',completiondate
|
|
else:
|
|
return ratio,'partial',completiondate
|
|
elif ps.criterium == 'minimum':
|
|
if ratio > 1.0:
|
|
return ratio,'completed',completiondate
|
|
else:
|
|
if not completiondate:
|
|
completiondate = ws.reverse()[0].date
|
|
return ratio,'partial',completiondate
|
|
else:
|
|
if not completiondate:
|
|
completiondate = ws.reverse()[0].date
|
|
return ratio,'partial',completiondate
|
|
elif ps.sessiontype == 'coursetest':
|
|
if ps.course:
|
|
(
|
|
coursetime,
|
|
coursemeters,
|
|
coursecompleted
|
|
) = courses.get_time_course(ws,ps.course)
|
|
if coursecompleted:
|
|
return 1.0,'completed',completiondate
|
|
else:
|
|
return ratio,'partial',completiondate
|
|
else:
|
|
if ps.criterium == 'exact':
|
|
if ratio == 1.0:
|
|
return ratio,'completed',completiondate
|
|
else:
|
|
if not completiondate:
|
|
completiondate = ws.reverse()[0].date
|
|
return ratio,'partial',completiondate
|
|
elif ps.criterium == 'minimum':
|
|
if ratio >= 1.0:
|
|
return ratio,'completed',completiondate
|
|
else:
|
|
if not completiondate:
|
|
completiondate = ws.reverse()[0].date
|
|
|
|
return ratio,'partial',completiondate
|
|
else:
|
|
if ratio>cratiomin and ratio<cratiomax:
|
|
return ratio,'completed',completiondate
|
|
else:
|
|
return ratio,'partial',completiondate
|
|
|
|
else:
|
|
if not completiondate:
|
|
completiondate = ws.reverse()[0].date
|
|
return ratio,status,completiondate
|
|
|
|
|
|
def is_session_complete(r,ps):
|
|
status = 'not done'
|
|
|
|
if r not in ps.rower.all():
|
|
return 0,'not assigned',None
|
|
|
|
ws = Workout.objects.filter(user=r,plannedsession=ps)
|
|
|
|
return is_session_complete_ws(ws,ps)
|
|
|
|
|
|
def rank_results(ps):
|
|
return 1
|
|
|
|
def add_team_session(t,ps):
|
|
ps.team.add(t)
|
|
ps.save()
|
|
|
|
return 1
|
|
|
|
def add_rower_session(r,ps):
|
|
ps.rower.add(r)
|
|
ps.save()
|
|
|
|
return 1
|
|
|
|
def remove_team_session(t,ps):
|
|
ps.team.remove(t)
|
|
|
|
return 1
|
|
|
|
def remove_rower_session(r,ps):
|
|
ps.rower.remove(r)
|
|
|
|
return 1
|
|
|
|
def get_dates_timeperiod(timeperiod):
|
|
# set start end date according timeperiod
|
|
if timeperiod=='today':
|
|
startdate=date.today()
|
|
enddate=date.today()
|
|
elif timeperiod=='tomorrow':
|
|
startdate=date.today()+timezone.timedelta(days=1)
|
|
enddate=date.today()+timezone.timedelta(days=1)
|
|
elif timeperiod=='thisweek':
|
|
today = date.today()
|
|
startdate = date.today()-timezone.timedelta(days=today.weekday())
|
|
enddate = startdate+timezone.timedelta(days=6)
|
|
elif timeperiod=='thismonth':
|
|
today = date.today()
|
|
startdate = today.replace(day=1)
|
|
enddate = startdate+timezone.timedelta(days=32)
|
|
enddate = enddate.replace(day=1)
|
|
enddate = enddate-timezone.timedelta(days=1)
|
|
elif timeperiod=='lastweek':
|
|
today = date.today()
|
|
enddate = today-timezone.timedelta(days=today.weekday())-timezone.timedelta(days=1)
|
|
startdate = enddate-timezone.timedelta(days=6)
|
|
elif timeperiod=='nextweek':
|
|
today = date.today()
|
|
startdate = today-timezone.timedelta(days=today.weekday())+timezone.timedelta(days=7)
|
|
enddate = startdate+timezone.timedelta(days=6)
|
|
elif timeperiod=='lastmonth':
|
|
today = date.today()
|
|
startdate = today.replace(day=1)
|
|
startdate = startdate-timezone.timedelta(days=3)
|
|
startdate = startdate.replace(day=1)
|
|
enddate = startdate+timezone.timedelta(days=32)
|
|
enddate = enddate.replace(day=1)
|
|
enddate = enddate-timezone.timedelta(days=1)
|
|
elif timeperiod=='nextmonth':
|
|
today = date.today()
|
|
startdate = today.replace(day=1)
|
|
startdate = startdate+timezone.timedelta(days=32)
|
|
startdate = startdate.replace(day=1)
|
|
enddate = startdate+timezone.timedelta(days=32)
|
|
enddate = enddate.replace(day=1)
|
|
enddate = enddate-timezone.timedelta(days=1)
|
|
else:
|
|
startdate = date.today()
|
|
enddate = date.today()
|
|
|
|
return startdate,enddate
|
|
|
|
def get_sessions_manager(m,teamid=0,startdate=date.today(),
|
|
enddate=date.today()+timezone.timedelta(+1000)):
|
|
if teamid:
|
|
t = Team.objects.get(id=teamid)
|
|
sps = PlannedSession.objects.filter(
|
|
team__in=[t],
|
|
manager=m,
|
|
startdate__lte=enddate,
|
|
enddate__gte=startdate,
|
|
).order_by("startdate","preferreddate","enddate")
|
|
else:
|
|
sps = PlannedSession.objects.filter(
|
|
manager=m,
|
|
startdate__lte=enddate,
|
|
enddate__gte=startdate,
|
|
).order_by("startdate","preferreddate","enddate")
|
|
|
|
return sps
|
|
|
|
def get_sessions(r,startdate=date.today(),
|
|
enddate=date.today()+timezone.timedelta(+1000)):
|
|
|
|
sps = PlannedSession.objects.filter(
|
|
rower__in=[r],
|
|
startdate__lte=enddate,
|
|
enddate__gte=startdate,
|
|
).order_by("startdate","preferreddate","enddate")
|
|
|
|
return sps
|
|
|
|
def get_workouts_session(r,ps):
|
|
ws = Workout.objects.filter(user=r,plannedsession=ps)
|
|
|
|
return ws
|
|
|
|
def update_plannedsession(ps,cd):
|
|
for attr, value in cd.items():
|
|
if attr == 'comment':
|
|
value.replace("\r\n", "
");
|
|
value.replace("\n", "
");
|
|
setattr(ps, attr, value)
|
|
|
|
ps.save()
|
|
|
|
return 1,'Planned Session Updated'
|