diff --git a/rowers/plannedsessions.py b/rowers/plannedsessions.py
index 1f9c708d..6168cb56 100644
--- a/rowers/plannedsessions.py
+++ b/rowers/plannedsessions.py
@@ -16,7 +16,7 @@ queuelow = django_rq.get_queue('low')
queuehigh = django_rq.get_queue('low')
from rowers.models import (
- Rower, Workout,
+ Rower, Workout,Team,
GeoCourse, TrainingMicroCycle,TrainingMesoCycle,TrainingMacroCycle,
TrainingPlan,PlannedSession,
)
@@ -70,9 +70,57 @@ def timefield_to_seconds_duration(t):
duration += t.microsecond/1.e6
return duration
-
+
+def get_session_metrics(ps):
+ rowers = ps.rower.all()
+ rscore = []
+ trimp = []
+ duration = []
+ distance = []
+ firstname = []
+ lastname = []
+
+ for r in rowers:
+ rscorev = 0
+ trimpv = 0
+ durationv = 0
+ distancev = 0
+
+
+ ws = Workout.objects.filter(user=r,plannedsession=ps)
+ 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)
+
+
+ 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)
+
+ thedict = {
+ 'first_name':firstname,
+ 'last_name':lastname,
+ 'duration':duration,
+ 'distance':distance,
+ 'rscore':rscore,
+ 'trimp':trimp
+ }
+
+ return thedict
+
def is_session_complete(r,ps):
status = 'not done'
+
+ if r not in ps.rower.all():
+ return 0,'not assigned'
ws = Workout.objects.filter(user=r,plannedsession=ps)
@@ -208,6 +256,25 @@ def get_dates_timeperiod(timeperiod):
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)):
@@ -219,17 +286,6 @@ def get_sessions(r,startdate=date.today(),
return sps
-def get_sessions_manager(manager,startdate=date.today(),
- enddate=date.today()+timezone.timedelta(+1000)):
-
- sps = PlannedSession.objects.filter(
- manager=manager,
- startdate__lte=enddate,
- enddate__gte=startdate,
- ).order_by("startdate","enddate").exclude(team__isnull=True)
-
- return sps
-
def get_workouts_session(r,ps):
ws = Workout.objects.filter(user=r,plannedsession=ps)
diff --git a/rowers/templates/plannedsessionscoach.html b/rowers/templates/plannedsessionscoach.html
new file mode 100644
index 00000000..8a888c22
--- /dev/null
+++ b/rowers/templates/plannedsessionscoach.html
@@ -0,0 +1,181 @@
+{% extends "base.html" %}
+{% load staticfiles %}
+{% load rowerfilters %}
+
+{% block title %}Planned Sessions{% endblock %}
+
+{% block content %}
+
+ {% include "planningbuttons.html" %}
+
+
+ {% if theteam %}
+
Coach Overview. Team {{ theteam.name }}
+ {% else %}
+ Coach Overview
+ {% endif %}
+
+
+
+
+
+{% if user.is_authenticated and user|is_manager %}
+
+
+{% endif %}
+
+
+
+
+
+ | On or after |
+ On or before |
+ Name |
+ {% for r in rowers %}
+
+ {{ r.user.first_name }} {{ r.user.last_name }}
+ |
+ {% endfor %}
+
+
+
+ {% for key, thedict in statusdict.items %}
+
+ |
+ {{ thedict|lookup:'startdate'|date:"Y-m-d" }}
+ |
+
+ {{ thedict|lookup:'enddate'|date:"Y-m-d" }}
+ |
+
+
+ {{ thedict|lookup:'name' }}
+
+ |
+ {% for r in rowers %}
+
+ {% if thedict|lookup:'results'|lookup:r.id == 'completed' %}
+
+ {% elif thedict|lookup:'results'|lookup:r.id == 'partial' %}
+
+ {% elif thedict|lookup:'results'|lookup:r.id == 'not done' %}
+
+ {% elif thedict|lookup:'results'|lookup:r.id == 'not assigned' %}
+
+ {% else %}
+
+ {% endif %}
+ |
+ {% endfor %}
+
+ {% endfor %}
+
+
+
+ {% if unmatchedworkouts %}
+
Workouts that are not linked to any session
+
+
+
+ | Rower |
+ Date |
+ Time |
+ Name |
+ Type |
+ Distance |
+ Duration |
+ Avg HR |
+ Max HR |
+
+
+
+ {% for workout in unmatchedworkouts %}
+
+ | {{ workout.user.user.first_name }} {{ workout.user.user.last_name }} |
+ {{ workout.date|date:"Y-m-d" }} |
+ {{ workout.starttime|date:"H:i" }} |
+ {% if workout.user.user == user or user == team.manager %}
+ {% if workout.name != '' %}
+
+
+ {{ workout.name }}
+
+ |
+ {% else %}
+
+ No Name
+ |
+ {% endif %}
+ {% else %}
+ {% if workout.name != '' %}
+ {{ workout.name }} |
+ {% else %}
+ No Name |
+ {% endif %}
+ {% endif %}
+ {{ workout.workouttype }} |
+ {{ workout.distance }}m |
+ {{ workout.duration |durationprint:"%H:%M:%S.%f" }} |
+ {{ workout.averagehr }} |
+ {{ workout.maxhr }} |
+
+ {% endfor %}
+
+
+
+
+ {% endif %}
+
+
+
+
+
+
+{% endblock %}
diff --git a/rowers/templates/plannedsessionview.html b/rowers/templates/plannedsessionview.html
index be61c544..b15bbde9 100644
--- a/rowers/templates/plannedsessionview.html
+++ b/rowers/templates/plannedsessionview.html
@@ -9,6 +9,17 @@
{% include "planningbuttons.html" %}
+
+
+ {% if user.is_authenticated and psdict.id.1|is_session_manager:user %}
+
+ Edit Session
+ {% else %}
+
+ {% endif %}
+
+
+
Session {{ psdict.name.1 }}
@@ -22,9 +33,6 @@
{% endfor %}
{% endfor %}
-
Result
-
Status: {{ status }}
-
Percentage complete: {{ ratio }}
Workouts attached
@@ -53,7 +61,38 @@
-
-
+
+
+
+
Result
+
Status: {{ status }}
+
Percentage complete: {{ ratio }}
+
+
+
Stats
+
+
+
+ | Name |
+ Minutes |
+ Meters |
+ rScore |
+ TRIMP |
+
+
+
+ {% for id, value in results.items %}
+
+ | {{ value|lookup:'first_name' }} {{ value|lookup:'last_name' }} |
+ {{ value|lookup:'duration' }} |
+ {{ value|lookup:'distance' }} |
+ {{ value|lookup:'rscore' }} |
+ {{ value|lookup:'trimp' }} |
+
+ {% endfor %}
+
+
+
+
{% endblock %}
diff --git a/rowers/templates/planningbuttons.html b/rowers/templates/planningbuttons.html
index 6f57cfd4..20648d28 100644
--- a/rowers/templates/planningbuttons.html
+++ b/rowers/templates/planningbuttons.html
@@ -32,12 +32,23 @@
{% endif %}
-
+
+
+ {% if user.is_authenticated and user|is_manager %}
+ {% if timeperiod %}
+
Coach Overview
+ {% else %}
+
Coach Overview
{% endif %}
{% else %}
diff --git a/rowers/templatetags/rowerfilters.py b/rowers/templatetags/rowerfilters.py
index bfdf2751..cd9acd8b 100644
--- a/rowers/templatetags/rowerfilters.py
+++ b/rowers/templatetags/rowerfilters.py
@@ -100,6 +100,16 @@ def ualookup(dict, key):
return s
+from rowers.models import PlannedSession
+@register.filter
+def is_session_manager(id,user):
+ try:
+ ps = PlannedSession.objects.get(id=id)
+ except PlannedSession.DoesNotExist:
+ return False
+
+ return ps.manager == user
+
@register.filter(name='times')
def times(number):
return range(number)
diff --git a/rowers/urls.py b/rowers/urls.py
index d502a7d2..b630c026 100644
--- a/rowers/urls.py
+++ b/rowers/urls.py
@@ -448,6 +448,11 @@ urlpatterns = [
views.plannedsessions_manage_view),
url(r'^sessions/manage/(?P
[\w\ ]+.*)$',
views.plannedsessions_manage_view),
+ url(r'^sessions/coach$',views.plannedsessions_coach_view),
+ url(r'^sessions/coach/(?P[\w\ ]+.*)/team/(?P\d+)$',
+ views.plannedsessions_coach_view),
+ url(r'^sessions/coach/(?P[\w\ ]+.*)$',
+ views.plannedsessions_coach_view),
url(r'^sessions/?$',views.plannedsessions_view),
url(r'^sessions/rower/(?P\d+)$',views.plannedsessions_view),
url(r'^sessions/(?P[\w\ ]+.*)/rower/(?P\d+)$',views.plannedsessions_view),
diff --git a/rowers/utils.py b/rowers/utils.py
index 27fad934..cdb92131 100644
--- a/rowers/utils.py
+++ b/rowers/utils.py
@@ -294,6 +294,7 @@ def calculate_age(born):
def my_dict_from_instance(instance,model):
thedict = {}
+ thedict['id'] = instance.id
for attr, value in instance.__dict__.iteritems():
try:
diff --git a/rowers/views.py b/rowers/views.py
index 8dfe64dc..eb9a46bc 100644
--- a/rowers/views.py
+++ b/rowers/views.py
@@ -11854,6 +11854,68 @@ def plannedsession_teamedit_view(request,timeperiod='thisweek',
'plannedsessions':sps,
})
+@user_passes_test(iscoachmember,login_url="/rowers/planmembership/",
+ redirect_field_name=None)
+def plannedsessions_coach_view(request,timeperiod='thisweek',
+ teamid=0):
+
+ startdate,enddate = get_dates_timeperiod(timeperiod)
+
+ if teamid != 0:
+ try:
+ theteam = Team.objects.get(id=teamid)
+ except Team.DoesNotExist:
+ theteam = False
+ else:
+ theteam = False
+
+ sps = get_sessions_manager(request.user,teamid=teamid,
+ enddate=enddate,
+ startdate=startdate)
+
+ rowers = []
+ for ps in sps:
+ rowers += ps.rower.all()
+
+ rowers = list(set(rowers))
+
+ statusdict = {}
+
+ for ps in sps:
+ rowerstatus = {}
+ for r in rowers:
+ ratio, status = is_session_complete(r,ps)
+ rowerstatus[r.id] = status
+ sessiondict = {
+ 'results':rowerstatus,
+ 'name': ps.name,
+ 'startdate': ps.startdate,
+ 'enddate': ps.enddate,
+ }
+ statusdict[ps.id] = sessiondict
+
+ unmatchedworkouts = []
+ for r in rowers:
+ unmatchedworkouts += Workout.objects.filter(
+ user=r,
+ plannedsession=None,
+ date__gte=startdate,date__lte=enddate)
+
+
+ myteams = Team.objects.filter(manager=request.user)
+
+ return render(request,'plannedsessionscoach.html',
+ {
+ 'myteams':myteams,
+ 'plannedsessions':sps,
+ 'statusdict':statusdict,
+ 'timeperiod':timeperiod,
+ 'rowers':rowers,
+ 'theteam':theteam,
+ 'unmatchedworkouts':unmatchedworkouts,
+ 'rower':getrower(request.user)
+ }
+ )
@login_required()
def plannedsessions_view(request,timeperiod='thisweek',rowerid=0):
@@ -12162,6 +12224,7 @@ def plannedsession_view(request,id=0,rowerid=0):
m = getrower(request.user)
+
if not rowerid:
r = m
else:
@@ -12176,8 +12239,11 @@ def plannedsession_view(request,id=0,rowerid=0):
if ps.manager != request.user and r not in ps.rower.all():
raise PermissionDenied("You do not have access to this session")
+ resultsdict = get_session_metrics(ps)
+ resultsdict = pd.DataFrame(resultsdict).transpose().to_dict()
psdict = my_dict_from_instance(ps,PlannedSession)
+ print psdict
ws = get_workouts_session(r,ps)
@@ -12196,7 +12262,8 @@ def plannedsession_view(request,id=0,rowerid=0):
'manager':m,
'rower':r,
'ratio':ratio,
- 'status':status
+ 'status':status,
+ 'results':resultsdict,
}
)
diff --git a/static/css/rowsandall.css b/static/css/rowsandall.css
index 36fe4242..f8d66d68 100644
--- a/static/css/rowsandall.css
+++ b/static/css/rowsandall.css
@@ -139,9 +139,10 @@ cox {
.listtable tbody tr:nth-of-type(even) { background-color: #DDD; }
.listtable thead th {
- font-weight: bold;
+ font-weight: bold;
}
+
.shortpadded td { padding: 3px 3px }
.paddedtable td { padding: 1px 20px }