from django.utils import timezone import datetime as dt from rowers.models import Workout, VirtualRaceResult, CourseTestResult 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 is_session_complete_ws(ws, ps): ws = ws.order_by("date") if ws.count() == 0: today = timezone.now() if today.date() > ps.enddate: verdict = 'missed' ratio = 0 return ratio, verdict, None else: return 0, 'not done', None value = ps.sessionvalue if ps.sessionunit == 'min': value *= 60. elif ps.sessionunit == 'km': # pragma: no cover value *= 1000. cratiomin = 1 # cratiomax = 1 cratios = { 'better than nothing': 0, 'partial': 0.6, 'on target': 0.8, 'over target': 1.2, 'way over target': 1.5 } if ps.criterium == 'none': if ps.sessiontype == 'session': cratiomin = 0.8 # cratiomax = 1.2 else: cratios['on target'] = 0.9167 cratios['over target'] = 1.0833 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': score += w.trimp elif ps.sessionmode == 'rScore': score += w.rscore if not completiondate and score >= cratiomin*value: completiondate = w.date try: ratio = score/float(int(value)) except ZeroDivisionError: # pragma: no cover ratio = 0 verdict = 'better than nothing' if ps.sessiontype in ['session', 'cycletarget']: if ps.criterium == 'exact': if ratio == 1.0: return ratio, 'on target', completiondate else: if not completiondate: # pragma: no cover completiondate = ws.reverse()[0].date return ratio, 'partial', completiondate elif ps.criterium == 'minimum': # pragma: no cover if ratio >= 1.0: return ratio, 'on target', completiondate else: if not completiondate: completiondate = ws.reverse()[0].date return ratio, 'partial', completiondate else: thevalue = 0 for key, value in cratios.items(): if ratio > value and value > thevalue: verdict = key thevalue = value completiondate = ws.reverse()[0].date return ratio, verdict, completiondate elif ps.sessiontype == 'test': if ratio == 1.0: return ratio, 'on target', completiondate else: return ratio, 'partial', completiondate elif ps.sessiontype == 'challenge': if ps.criterium == 'exact': if ratio == 1.0: return ratio, 'on target', completiondate else: return ratio, 'partial', completiondate elif ps.criterium == 'minimum': # pragma: no cover if ratio > 1.0: return ratio, 'on target', completiondate else: if not completiondate: completiondate = ws.reverse()[0].date return ratio, 'partial', completiondate else: if not completiondate: # pragma: no cover completiondate = ws.reverse()[0].date return ratio, 'partial', completiondate elif ps.sessiontype == 'race': # pragma: no cover vs = VirtualRaceResult.objects.filter(race=ps) wids = [w.id for w in ws] for record in vs: if record.workoutid in wids: if record.coursecompleted: ratio = record.distance/ps.sessionvalue return ratio, 'on target', completiondate else: ratio = record.distance/ps.sessionvalue return ratio, 'partial', completiondate return (0, 'partial', None) elif ps.sessiontype in ['fastest_time', 'fastest_distance']: # pragma: no cover vs = CourseTestResult.objects.filter( plannedsession=ps, userid=ws[0].user.user.id) completiondate = ws.reverse()[0].date wids = [w.id for w in ws] for record in vs: if record.workoutid in wids: if record.coursecompleted: ratio = 1 return ratio, 'on target', completiondate else: return 0, 'partial', completiondate if ws: record = CourseTestResult( userid=ws[0].user.id, plannedsession=ps, workoutid=ws[0].id, duration=dt.time(0, 0), coursecompleted=False ) record.save() return (0, 'not done', None) elif ps.sessiontype == 'coursetest': # pragma: no cover vs = CourseTestResult.objects.filter(plannedsession=ps) wids = [w.id for w in ws] for record in vs: if record.workoutid in wids: if record.coursecompleted: ratio = record.distance/float(ps.sessionvalue) return ratio, 'on target', completiondate else: ratio = record.distance/float(ps.sessionvalue) return ratio, 'partial', completiondate else: # pragma: no cover if not completiondate: completiondate = ws.reverse()[0].date return ratio, verdict, completiondate return 0, 'not done', None def is_session_complete(r, ps): if r not in ps.rower.all(): # pragma: no cover return 0, 'not assigned', None ws = Workout.objects.filter(user=r, plannedsession=ps) return is_session_complete_ws(ws, ps)