Private
Public Access
1
0
Files
rowsandall/rowers/plannedsessions.py
2018-02-23 11:06:58 +01:00

404 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:
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()
enddate = today-timezone.timedelta(days=today.weekday())-timezone.timedelta(days=1)+timezone.timedelta(days=7)
startdate = enddate-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","enddate")
else:
sps = PlannedSession.objects.filter(
manager=m,
startdate__lte=enddate,
enddate__gte=startdate,
).order_by("startdate","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","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():
setattr(ps, attr, value)
ps.save()
return 1,'Planned Session Updated'