From cde3eaf60595ccf8d193a20e5262c7824aefdcea Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Thu, 6 Jul 2017 09:57:20 +0200
Subject: [PATCH] start of multiflex
---
rowers/interactiveplots.py | 20 ++++
rowers/templates/analysis.html | 14 ++-
rowers/templates/user_multiflex_select.html | 118 ++++++++++++++++++++
rowers/urls.py | 4 +
rowers/views.py | 91 +++++++++++++++
5 files changed, 246 insertions(+), 1 deletion(-)
create mode 100644 rowers/templates/user_multiflex_select.html
diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py
index e8b5ec77..a8e3f38a 100644
--- a/rowers/interactiveplots.py
+++ b/rowers/interactiveplots.py
@@ -69,7 +69,27 @@ watermarkw = 184
watermarkh = 35
watermarkanchor = 'bottom_right'
+def errorbar(fig, x, y, xerr=None, yerr=None, color='red',
+ point_kwargs={}, error_kwargs={}):
+ fig.circle(x, y, color=color, **point_kwargs)
+
+ if xerr:
+ x_err_x = []
+ x_err_y = []
+ for px, py, err in zip(x, y, xerr):
+ x_err_x.append((px - err, px + err))
+ x_err_y.append((py, py))
+ fig.multi_line(x_err_x, x_err_y, color=color, **error_kwargs)
+
+ if yerr:
+ y_err_x = []
+ y_err_y = []
+ for px, py, err in zip(x, y, yerr):
+ y_err_x.append((px, px))
+ y_err_y.append((py - err, py + err))
+ fig.multi_line(y_err_x, y_err_y, color=color, **error_kwargs)
+
def tailwind(bearing,vwind,winddir):
""" Calculates head-on head/tailwind in direction of rowing
diff --git a/rowers/templates/analysis.html b/rowers/templates/analysis.html
index 4eae9987..2aeca53a 100644
--- a/rowers/templates/analysis.html
+++ b/rowers/templates/analysis.html
@@ -95,7 +95,7 @@
Analyse power vs piece duration to make predictions.
-
+
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
Multi Compare
@@ -107,6 +107,18 @@
Compare many workouts
+
+
+ {% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
+ Multi Flex
+ {% else %}
+ Multi Flex
+ {% endif %}
+
+
+ Select workouts and make X-Y charts of averages over various metrics
+
+
diff --git a/rowers/templates/user_multiflex_select.html b/rowers/templates/user_multiflex_select.html
new file mode 100644
index 00000000..2033faf9
--- /dev/null
+++ b/rowers/templates/user_multiflex_select.html
@@ -0,0 +1,118 @@
+{% extends "base.html" %}
+{% load staticfiles %}
+{% load rowerfilters %}
+
+{% block title %}Workouts{% endblock %}
+
+{% block content %}
+
+
+
+ {% if team %}
+
+ {% include "teambuttons.html" with teamid=team.id team=team %}
+
+{% endif %}
+
+
+ {% if theuser %}
+
{{ theuser.first_name }}'s Workouts
+ {% else %}
+ {{ user.first_name }}'s Workouts
+ {% endif %}
+
+
+ {% if user.is_authenticated and user|is_manager %}
+
+
+
+
+
+
+
+
+{% endblock %}
diff --git a/rowers/urls.py b/rowers/urls.py
index edf1f23d..9c415836 100644
--- a/rowers/urls.py
+++ b/rowers/urls.py
@@ -129,6 +129,10 @@ urlpatterns = [
url(r'^user-boxplot-select/user/(?P
\d+)/$',views.user_boxplot_select),
url(r'^user-boxplot-select/(?P\w+.*)/(?P\w+.*)$',views.user_boxplot_select),
url(r'^user-boxplot-select/$',views.user_boxplot_select),
+ url(r'^user-multiflex-select/user/(?P\d+)/(?P\w+.*)/(?P\w+.*)$',views.user_multiflex_select),
+ url(r'^user-multiflex-select/user/(?P\d+)/$',views.user_multiflex_select),
+ url(r'^user-multiflex-select/(?P\w+.*)/(?P\w+.*)$',views.user_multiflex_select),
+ url(r'^user-multiflex-select/$',views.user_multiflex_select),
url(r'^list-graphs/$',views.graphs_view),
url(r'^(?P\d+)/ote-bests/(?P\w+.*)/(?P\w+.*)$',views.rankings_view),
url(r'^(?P\d+)/ote-bests/(?P\d+)$',views.rankings_view),
diff --git a/rowers/views.py b/rowers/views.py
index a1f76391..63562b39 100644
--- a/rowers/views.py
+++ b/rowers/views.py
@@ -3324,6 +3324,97 @@ def multi_compare_view(request):
url = reverse(workouts_view)
return HttpResponseRedirect(url)
+# Box plots
+@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
+def user_multiflex_select(request,
+ startdatestring="",
+ enddatestring="",
+ message='',
+ successmessage='',
+ startdate=timezone.now()-datetime.timedelta(days=30),
+ enddate=timezone.now()+datetime.timedelta(days=1),
+ userid=0):
+
+ if userid == 0:
+ user = request.user
+ else:
+ user = User.objects.get(id=userid)
+
+
+ r = getrower(user)
+
+ if 'startdate' in request.session:
+ startdate = iso8601.parse_date(request.session['startdate'])
+
+
+ if 'enddate' in request.session:
+ enddate = iso8601.parse_date(request.session['enddate'])
+
+
+ if request.method == 'POST':
+ dateform = DateRangeForm(request.POST)
+ if dateform.is_valid():
+ startdate = dateform.cleaned_data['startdate']
+ enddate = dateform.cleaned_data['enddate']
+ else:
+ dateform = DateRangeForm(initial={
+ 'startdate':startdate,
+ 'enddate':enddate,
+ })
+
+ startdate = datetime.datetime.combine(startdate,datetime.time())
+ enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59))
+ enddate = enddate+datetime.timedelta(days=1)
+
+ if startdatestring:
+ startdate = iso8601.parse_date(startdatestring)
+ if enddatestring:
+ enddate = iso8601.parse_date(enddatestring)
+
+ if enddate < startdate:
+ s = enddate
+ enddate = startdate
+ startdate = s
+
+
+ workouts = Workout.objects.filter(user=r,
+ startdatetime__gte=startdate,
+ startdatetime__lte=enddate).order_by("-date", "-starttime")
+
+ query = request.GET.get('q')
+ if query:
+ query_list = query.split()
+ workouts = workouts.filter(
+ reduce(operator.and_,
+ (Q(name__icontains=q) for q in query_list)) |
+ reduce(operator.and_,
+ (Q(notes__icontains=q) for q in query_list))
+ )
+
+ form = WorkoutMultipleCompareForm()
+ form.fields["workouts"].queryset = workouts
+
+ chartform = BoxPlotChoiceForm()
+
+ messages.info(request,successmessage)
+ messages.error(request,message)
+
+ startdatestring = startdate.strftime('%Y-%m-%d')
+ enddatestring = enddate.strftime('%Y-%m-%d')
+ request.session['startdate'] = startdatestring
+ request.session['enddate'] = enddatestring
+
+ return render(request, 'user_boxplot_select.html',
+ {'workouts': workouts,
+ 'dateform':dateform,
+ 'startdate':startdate,
+ 'enddate':enddate,
+ 'theuser':user,
+ 'form':form,
+ 'chartform':chartform,
+ 'teams':get_my_teams(request.user),
+ })
+
# Box plots
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def user_boxplot_select(request,