diff --git a/rowers/plannedsessions.py b/rowers/plannedsessions.py index aaf15c23..713e4145 100644 --- a/rowers/plannedsessions.py +++ b/rowers/plannedsessions.py @@ -104,7 +104,8 @@ def get_session_metrics(ps): completedatev = '' statusv = 0 - ws = Workout.objects.filter(user=r,plannedsession=ps) + ws = Workout.objects.filter(user=r,plannedsession=ps).order_by("date") + if len(ws) != 0: for w in ws: distancev += w.distance @@ -112,8 +113,11 @@ def get_session_metrics(ps): trimpv += dataprep.workout_trimp(w) rscorev += dataprep.workout_rscore(w)[0] - ratio,statusv = is_session_complete_ws(ws,ps) - completedatev = ws[0].date.strftime('%Y-%m-%d') + 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)) @@ -139,16 +143,35 @@ def get_session_metrics(ps): 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 + return ratio,status,None else: - return 0,'not done' + 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 @@ -161,12 +184,8 @@ def is_session_complete_ws(ws,ps): elif ps.sessionmode == 'rScore': rscore = dataprep.workout_rscore(w)[0] score += rscore - - value = ps.sessionvalue - if ps.sessionunit == 'min': - value *= 60. - elif ps.sessionunit == 'km': - value *= 1000. + if not completiondate and score>=cratiomin*value: + completiondate = w.date ratio = score/float(value) @@ -175,49 +194,47 @@ def is_session_complete_ws(ws,ps): if ps.sessiontype in ['session','cycletarget']: if ps.criterium == 'exact': if ratio == 1.0: - return ratio,'completed' + return ratio,'completed',completiondate else: - return ratio,'partial' + return ratio,'partial',completiondate elif ps.criterium == 'minimum': if ratio >= 1.0: - return ratio,'completed' + return ratio,'completed',completiondate else: - return ratio,'partial' + return ratio,'partial',completiondate else: - if ratio>0.8 and ratio<1.2 and ps.sessiontype=='session': - return ratio,'completed' - elif ratio>0.9167 and ratio<1.0833 and ps.sessiontype=='cycletarget': - return ratio,'completed' + if ratio>cratiomin and ratio 1.0: - return ratio,'completed' + return ratio,'completed',completiondate else: - return ratio,'partial' + return ratio,'partial',completiondate else: - return ratio,'partial' + return ratio,'partial',completiondate else: - return ratio,status + return ratio,status,completiondate def is_session_complete(r,ps): status = 'not done' if r not in ps.rower.all(): - return 0,'not assigned' + return 0,'not assigned',None ws = Workout.objects.filter(user=r,plannedsession=ps) diff --git a/rowers/templates/plannedsession_multicreate.html b/rowers/templates/plannedsession_multicreate.html index d1be9b95..5abb9384 100644 --- a/rowers/templates/plannedsession_multicreate.html +++ b/rowers/templates/plannedsession_multicreate.html @@ -92,10 +92,14 @@ {% endfor %} - Add More + Add More +
+ +
+ {% endblock %} @@ -117,34 +121,72 @@ $( myrow ).find('*[id*=sessionmode]').change(function() { if (this.value == 'TRIMP') { $( myrow ).find("*[id*=sessionunit]").prop('value','None'); + $('#id_guidance').html("

TRIMP has no unit

"); } if (this.value == 'distance') { $( myrow ).find("*[id*=sessionunit]").prop('value','m'); + $('#id_guidance').html("

Distance: Set value to meters

"); } if (this.value == 'time') { $( myrow ).find("*[id*=sessionunit]").prop('value','min'); + $('#id_guidance').html("

Time: Set value to minutes

"); } if (this.value == 'rScore') { $( myrow ).find("*[id*=sessionunit]").prop('value','None'); + $('#id_guidance').html("

rScore has no unit

"); + } }); + $( myrow ).find('*[id*=sessionunit]').change(function() { if (this.value == 'km') { $( myrow ).find("*[id*=sessionmode]").prop('value','distance'); + $('#id_guidance').html("

Mode was set to distance

"); } if (this.value == 'm') { $( myrow ).find("*[id*=sessionmode]").prop('value','distance'); + $('#id_guidance').html("

Mode was set to distance

"); } if (this.value == 'None') { $( myrow ).find("*[id*=sessionmode]").prop('value','rScore'); + $('#id_guidance').html("

Mode was set to rScore

"); } if (this.value == 'min') { $( myrow ).find("*[id*=sessionmode]").prop('value','time'); + $('#id_guidance').html("

Mode was set to time

"); } }); + + $( myrow ).find('*[id*=sessiontype]').change(function() { + if (this.value == 'session') { + $( myrow ).find("*[id*=criterium]").prop("value","none"); + $('#id_guidance').html("

For Training Sessions, the default criterium is 'Approximately'

"); + } + + if (this.value == 'challenge') { + $( myrow ).find("*[id*=criterium]").prop("value","minimum"); + $('#id_guidance').html("

For Challenges, the default criterium is 'At Least'

"); + } + + if (this.value == 'cycletarget') { + $( myrow ).find("*[id*=criterium]").prop("value","none"); + $('#id_guidance').html("

For Cycle Targets, the default criterium is 'Approximately'

"); + } + + if (this.value == 'test') { + $( myrow ).find("*[id*=criterium]").prop("value","exact"); + $( myrow ).find("*[id*=sessionmode]").prop("value","distance"); + $( myrow ).find("*[id*=sessionunit]").prop("value","m"); + $('#id_guidance').html("

Set mode to distance. For Mandatory Tests, only distance or time are allowed.

For Mandatory Tests, the only criterium is 'Exactly'

"); + } + }); + + + }); + }); diff --git a/rowers/templates/plannedsessioncreate.html b/rowers/templates/plannedsessioncreate.html index 6a03f149..b99a9860 100644 --- a/rowers/templates/plannedsessioncreate.html +++ b/rowers/templates/plannedsessioncreate.html @@ -124,6 +124,9 @@ +
+ +
{% endblock %} {% block scripts %} @@ -134,16 +137,20 @@ if (this.value == 'TRIMP') { $("td #id_sessionunit").prop("value","None"); + $('#id_guidance').html("

TRIMP has no unit

"); } if (this.value == 'distance') { $("td #id_sessionunit").prop("value","m"); + $('#id_guidance').html("

Distance: Set value to meters

"); } if (this.value == 'time') { $("td #id_sessionunit").prop("value","min"); + $('#id_guidance').html("

Time: Set value to minutes

"); } if (this.value == 'rScore') { $("td #id_sessionunit").prop("value","None"); + $('#id_guidance').html("

rScore has no unit

"); } }); @@ -152,18 +159,22 @@ if (this.value == 'session') { $("td #id_criterium").prop("value","none"); + $('#id_guidance').html("

For Training Sessions, the default criterium is 'Approximately'

"); } if (this.value == 'test') { $("td #id_criterium").prop("value","exact"); $("td #id_sessionmode").prop("value","distance"); $("td #id_sessionunit").prop("value","m"); + $('#id_guidance').html("

Set mode to distance. For Mandatory Tests, only distance or time are allowed.

For Mandatory Tests, the only criterium is 'Exactly'

"); } if (this.value == 'challenge') { $("td #id_criterium").prop("value","minimum"); + $('#id_guidance').html("

For Challenges, the default criterium is 'At Least'

"); } if (this.value == 'cycletarget') { $("td #id_criterium").prop("value","none"); + $('#id_guidance').html("

For Cycle Targets, the default criterium is 'Approximately'

"); } } @@ -174,21 +185,27 @@ if (this.value == 'm') { $("td #id_sessionmode").prop("value","distance"); + $('#id_guidance').html("

Mode was set to distance

"); } if (this.value == 'km') { $("td #id_sessionmode").prop("value","distance"); + $('#id_guidance').html("

Mode was set to distance

"); } if (this.value == 'None') { $("td #id_sessionmode").prop("value","rScore"); + $('#id_guidance').html("

Mode was set to rScore

"); } if (this.value == 'min') { $("td #id_sessionmode").prop("value","time"); + $('#id_guidance').html("

Mode was set to time

"); } } ); + + }); diff --git a/rowers/templates/plannedsessionedit.html b/rowers/templates/plannedsessionedit.html index 9021105f..9d82ed58 100644 --- a/rowers/templates/plannedsessionedit.html +++ b/rowers/templates/plannedsessionedit.html @@ -124,6 +124,10 @@
+
+ +
+ @@ -139,16 +143,20 @@ if (this.value == 'TRIMP') { $("td #id_sessionunit").prop("value","None"); + $('#id_guidance').html("

TRIMP has no unit

"); } if (this.value == 'distance') { $("td #id_sessionunit").prop("value","m"); + $('#id_guidance').html("

Distance: Set value to meters

"); } if (this.value == 'time') { $("td #id_sessionunit").prop("value","min"); + $('#id_guidance').html("

Time: Set value to minutes

"); } if (this.value == 'rScore') { $("td #id_sessionunit").prop("value","None"); + $('#id_guidance').html("

rScore has no unit

"); } }); @@ -157,18 +165,22 @@ if (this.value == 'session') { $("td #id_criterium").prop("value","none"); + $('#id_guidance').html("

For Training Sessions, the default criterium is 'Approximately'

"); } if (this.value == 'test') { $("td #id_criterium").prop("value","exact"); $("td #id_sessionmode").prop("value","distance"); $("td #id_sessionunit").prop("value","m"); + $('#id_guidance').html("

Set mode to distance. For Mandatory Tests, only distance or time are allowed.

For Mandatory Tests, the only criterium is 'Exactly'

"); } if (this.value == 'challenge') { $("td #id_criterium").prop("value","minimum"); + $('#id_guidance').html("

For Challenges, the default criterium is 'At Least'

"); } if (this.value == 'cycletarget') { $("td #id_criterium").prop("value","none"); + $('#id_guidance').html("

For Cycle Targets, the default criterium is 'Approximately'

"); } } @@ -179,15 +191,19 @@ if (this.value == 'm') { $("td #id_sessionmode").prop("value","distance"); + $('#id_guidance').html("

Mode was set to distance

"); } if (this.value == 'km') { $("td #id_sessionmode").prop("value","distance"); + $('#id_guidance').html("

Mode was set to distance

"); } if (this.value == 'None') { $("td #id_sessionmode").prop("value","rScore"); + $('#id_guidance').html("

Mode was set to rScore

"); } if (this.value == 'min') { $("td #id_sessionmode").prop("value","time"); + $('#id_guidance').html("

Mode was set to time

"); } } @@ -199,4 +215,5 @@ }); + {% endblock %} diff --git a/rowers/templates/plannedsessionscoach.html b/rowers/templates/plannedsessionscoach.html index 3cbe30ce..e9047273 100644 --- a/rowers/templates/plannedsessionscoach.html +++ b/rowers/templates/plannedsessionscoach.html @@ -92,7 +92,11 @@ + {% if thedict|lookup:'name' %} {{ thedict|lookup:'name' }} + {% else %} + Unnamed Session + {% endif %} {% for r in rowers %} diff --git a/rowers/templates/plannedsessionteamcreate.html b/rowers/templates/plannedsessionteamcreate.html index 24169c2e..bbe17b60 100644 --- a/rowers/templates/plannedsessionteamcreate.html +++ b/rowers/templates/plannedsessionteamcreate.html @@ -116,6 +116,9 @@ +
+ +
{% endblock %} @@ -123,69 +126,84 @@ {% block scripts %} + {% endblock %} diff --git a/rowers/templates/plannedsessionteamedit.html b/rowers/templates/plannedsessionteamedit.html index 0dbf27b6..4987af67 100644 --- a/rowers/templates/plannedsessionteamedit.html +++ b/rowers/templates/plannedsessionteamedit.html @@ -131,8 +131,12 @@
- - + +
+ +
+ + {% endblock %} @@ -144,16 +148,20 @@ if (this.value == 'TRIMP') { $("td #id_sessionunit").prop("value","None"); + $('#id_guidance').html("

TRIMP has no unit

"); } if (this.value == 'distance') { $("td #id_sessionunit").prop("value","m"); + $('#id_guidance').html("

Distance: Set value to meters

"); } if (this.value == 'time') { $("td #id_sessionunit").prop("value","min"); + $('#id_guidance').html("

Time: Set value to minutes

"); } if (this.value == 'rScore') { $("td #id_sessionunit").prop("value","None"); + $('#id_guidance').html("

rScore has no unit

"); } }); @@ -162,18 +170,22 @@ if (this.value == 'session') { $("td #id_criterium").prop("value","none"); + $('#id_guidance').html("

For Training Sessions, the default criterium is 'Approximately'

"); } if (this.value == 'test') { $("td #id_criterium").prop("value","exact"); $("td #id_sessionmode").prop("value","distance"); $("td #id_sessionunit").prop("value","m"); + $('#id_guidance').html("

Set mode to distance. For Mandatory Tests, only distance or time are allowed.

For Mandatory Tests, the only criterium is 'Exactly'

"); } if (this.value == 'challenge') { $("td #id_criterium").prop("value","minimum"); + $('#id_guidance').html("

For Challenges, the default criterium is 'At Least'

"); } if (this.value == 'cycletarget') { $("td #id_criterium").prop("value","none"); + $('#id_guidance').html("

For Cycle Targets, the default criterium is 'Approximately'

"); } } @@ -184,15 +196,19 @@ if (this.value == 'm') { $("td #id_sessionmode").prop("value","distance"); + $('#id_guidance').html("

Mode was set to distance

"); } if (this.value == 'km') { $("td #id_sessionmode").prop("value","distance"); + $('#id_guidance').html("

Mode was set to distance

"); } if (this.value == 'None') { $("td #id_sessionmode").prop("value","rScore"); + $('#id_guidance').html("

Mode was set to rScore

"); } if (this.value == 'min') { $("td #id_sessionmode").prop("value","time"); + $('#id_guidance').html("

Mode was set to time

"); } } diff --git a/rowers/views.py b/rowers/views.py index 9fb0e830..02d7f365 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -11844,7 +11844,7 @@ def plannedsession_teamcreate_view(request,timeperiod='thisweek', 'teamform':sessionteamselectform, 'timeperiod':timeperiod, 'plannedsessions':sps, - 'rower':r, + 'rower':getrower(request.user), }) # Manager edits sessions for entire team @@ -11991,7 +11991,7 @@ def plannedsessions_coach_view(request,timeperiod='thisweek', for ps in sps: rowerstatus = {} for r in rowers: - ratio, status = is_session_complete(r,ps) + ratio, status,completiondate = is_session_complete(r,ps) rowerstatus[r.id] = status sessiondict = { 'results':rowerstatus, @@ -12046,15 +12046,11 @@ def plannedsessions_view(request,timeperiod='thisweek',rowerid=0): completiondate = {} for ps in sps: - ratio,status = is_session_complete(r,ps) + ratio,status,cdate = is_session_complete(r,ps) actualvalue[ps.id] = int(ps.sessionvalue*ratio) completeness[ps.id] = status ws = Workout.objects.filter(user=r,plannedsession=ps) - if len(ws): - date = min([w.date for w in ws]) - completiondate[ps.id] = date - else: - completiondate[ps.id] = '' + completiondate[ps.id] = cdate unmatchedworkouts = Workout.objects.filter( user=r, @@ -12361,7 +12357,7 @@ def plannedsession_view(request,id=0,rowerid=0, ws = get_workouts_session(r,ps) - ratio,status = is_session_complete(r,ps) + ratio,status,completiondate = is_session_complete(r,ps) ratio = int(100.*ratio) @@ -12391,7 +12387,7 @@ def plannedsession_view(request,id=0,rowerid=0, 'psdict': psdict, 'attrs':[ 'name','startdate','enddate','sessiontype', - 'sessionmode', + 'sessionmode','criterium', 'sessionvalue','sessionunit' ], 'workouts': ws, diff --git a/static/admin/js/plannedsessions.js b/static/admin/js/plannedsessions.js new file mode 100644 index 00000000..93944405 --- /dev/null +++ b/static/admin/js/plannedsessions.js @@ -0,0 +1,77 @@ + + + $(document).ready(function(){ + $("td #id_sessionmode").change(function() { + + if (this.value == 'TRIMP') { + $("td #id_sessionunit").prop("value","None"); + $('#id_guidance').html("

TRIMP has no unit

"); + } + if (this.value == 'distance') { + $("td #id_sessionunit").prop("value","m"); + $('#id_guidance').html("

Distance: Set value to meters

"); + } + if (this.value == 'time') { + $("td #id_sessionunit").prop("value","min"); + $('#id_guidance').html("

Time: Set value to minutes

"); + } + + if (this.value == 'rScore') { + $("td #id_sessionunit").prop("value","None"); + $('#id_guidance').html("

rScore has no unit

"); + } + + }); + + $("td #id_sessiontype").change(function() { + + if (this.value == 'session') { + $("td #id_criterium").prop("value","none"); + $('#id_guidance').html("

For Training Sessions, the default criterium is 'Approximately'

"); + } + if (this.value == 'test') { + $("td #id_criterium").prop("value","exact"); + $("td #id_sessionmode").prop("value","distance"); + $("td #id_sessionunit").prop("value","m"); + $('#id_guidance').html("

Set mode to distance. For Mandatory Tests, only distance or time are allowed.

For Mandatory Tests, the only criterium is 'Exactly'

"); + } + if (this.value == 'challenge') { + $("td #id_criterium").prop("value","minimum"); + $('#id_guidance').html("

For Challenges, the default criterium is 'At Least'

"); + } + + if (this.value == 'cycletarget') { + $("td #id_criterium").prop("value","none"); + $('#id_guidance').html("

For Cycle Targets, the default criterium is 'Approximately'

"); + } + + } + + ); + + $("td #id_sessionunit").change(function() { + + if (this.value == 'm') { + $("td #id_sessionmode").prop("value","distance"); + $('#id_guidance').html("

Mode was set to distance

"); + } + if (this.value == 'km') { + $("td #id_sessionmode").prop("value","distance"); + $('#id_guidance').html("

Mode was set to distance

"); + } + if (this.value == 'None') { + $("td #id_sessionmode").prop("value","rScore"); + $('#id_guidance').html("

Mode was set to rScore

"); + } + if (this.value == 'min') { + $("td #id_sessionmode").prop("value","time"); + $('#id_guidance').html("

Mode was set to time

"); + } + + } + + ); + + + + }); diff --git a/static/js/plannedsessions.js b/static/js/plannedsessions.js new file mode 100644 index 00000000..93944405 --- /dev/null +++ b/static/js/plannedsessions.js @@ -0,0 +1,77 @@ + + + $(document).ready(function(){ + $("td #id_sessionmode").change(function() { + + if (this.value == 'TRIMP') { + $("td #id_sessionunit").prop("value","None"); + $('#id_guidance').html("

TRIMP has no unit

"); + } + if (this.value == 'distance') { + $("td #id_sessionunit").prop("value","m"); + $('#id_guidance').html("

Distance: Set value to meters

"); + } + if (this.value == 'time') { + $("td #id_sessionunit").prop("value","min"); + $('#id_guidance').html("

Time: Set value to minutes

"); + } + + if (this.value == 'rScore') { + $("td #id_sessionunit").prop("value","None"); + $('#id_guidance').html("

rScore has no unit

"); + } + + }); + + $("td #id_sessiontype").change(function() { + + if (this.value == 'session') { + $("td #id_criterium").prop("value","none"); + $('#id_guidance').html("

For Training Sessions, the default criterium is 'Approximately'

"); + } + if (this.value == 'test') { + $("td #id_criterium").prop("value","exact"); + $("td #id_sessionmode").prop("value","distance"); + $("td #id_sessionunit").prop("value","m"); + $('#id_guidance').html("

Set mode to distance. For Mandatory Tests, only distance or time are allowed.

For Mandatory Tests, the only criterium is 'Exactly'

"); + } + if (this.value == 'challenge') { + $("td #id_criterium").prop("value","minimum"); + $('#id_guidance').html("

For Challenges, the default criterium is 'At Least'

"); + } + + if (this.value == 'cycletarget') { + $("td #id_criterium").prop("value","none"); + $('#id_guidance').html("

For Cycle Targets, the default criterium is 'Approximately'

"); + } + + } + + ); + + $("td #id_sessionunit").change(function() { + + if (this.value == 'm') { + $("td #id_sessionmode").prop("value","distance"); + $('#id_guidance').html("

Mode was set to distance

"); + } + if (this.value == 'km') { + $("td #id_sessionmode").prop("value","distance"); + $('#id_guidance').html("

Mode was set to distance

"); + } + if (this.value == 'None') { + $("td #id_sessionmode").prop("value","rScore"); + $('#id_guidance').html("

Mode was set to rScore

"); + } + if (this.value == 'min') { + $("td #id_sessionmode").prop("value","time"); + $('#id_guidance').html("

Mode was set to time

"); + } + + } + + ); + + + + });