diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index 5e383310..f08df2b7 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -839,6 +839,7 @@ def interactive_histoall(theworkouts): plot.xaxis.axis_label = "Power (W)" plot.yaxis.axis_label = "% of strokes" plot.y_range = Range1d(0,1.05*max(hist_norm)) + hover = plot.select(dict(type=HoverTool)) @@ -856,6 +857,7 @@ def interactive_histoall(theworkouts): plot.add_layout(LinearAxis(y_range_name="fraction", axis_label="Cumulative % of strokes"),'right') + plot.sizing_mode = 'scale_width' script, div = components(plot) return [script,div] diff --git a/rowers/templates/cumstats.html b/rowers/templates/cumstats.html index dcc0982b..fbf39f11 100644 --- a/rowers/templates/cumstats.html +++ b/rowers/templates/cumstats.html @@ -1,17 +1,16 @@ -{% extends "base.html" %} +{% extends "newbase.html" %} {% load staticfiles %} {% load rowerfilters %} -{% block title %}Workout Statistics{% endblock %} - -{% block content %} +{% block title %}Rowsandall {% endblock %} +{% block main %} - - - -{{ plotscript |safe }} - - - - - -
Summary for {{ theuser.first_name }} {{ theuser.last_name }} - between {{ startdate|date }} and {{ enddate|date }}
- -Direct link for other Pro users: - https://rowsandall.com/rowers/{{ id }}/cumstats/{{ startdate|date:"Y-m-d" }}/{{ enddate|date:"Y-m-d" }}/p/{{ plotfield }} -
- - +Use this form to select a different date range:
-- Select start and end date for a date range: -
- Plot -
-Summary for {{ theuser.first_name }} {{ theuser.last_name }} + between {{ startdate|date }} and {{ enddate|date }}
+| Metric | -Value | +Mean | +Minimum | +25% | +Median | +75% | +Maximum | +Standard Deviation | |
|---|---|---|---|---|---|---|---|---|---|
| Mean | {{ value.mean|floatformat:-2 }} | -||||||||
| Minimum | {{ value.min|floatformat:-2 }} | -||||||||
| 25% | {{ value.firstq|floatformat:-2 }} | -||||||||
| Median | {{ value.median|floatformat:-2 }} | -||||||||
| 75% | {{ value.thirdq|floatformat:-2 }} | -||||||||
| Maximum | {{ value.max|floatformat:-2 }} | -||||||||
| Standard Deviation | {{ value.std|floatformat:-2 }} | +{{ value.verbosename }} | +{{ value.mean|floatformat:-2 }} | +{{ value.min|floatformat:-2 }} | +{{ value.firstq|floatformat:-2 }} | +{{ value.median|floatformat:-2 }} | +{{ value.thirdq|floatformat:-2 }} | +{{ value.max|floatformat:-2 }} | +{{ value.std|floatformat:-2 }} |
This matrix indicates a positive (+) or negative (-) correlation between two parameters. The Spearman correlation coefficient has values between +1 and -1. Positive correlation between two metrics means that if one metric increases, the other value is also likely to increase. Negative is the opposite. The further from zero, the higher the likelyhood. + + {% endif %} + +
This matrix indicates a positive (+) or negative (-) correlation between two parameters. The Spearman correlation coefficient has values between +1 and -1. Positive correlation between two metrics means that if one metric increases, the other value is also likely to increase. Negative is the opposite. The further from zero, the higher the likelyhood.
-| - {% for key,value in cordict.items %} - | {{ key }} |
- {% endfor %}
-
|---|
| + {% for key,value in cordict.items %} + | {{ key }} |
+ {% endfor %}
+
|---|---|
| {{ key }} | {% for key2,value in thedict.items %} @@ -218,24 +147,43 @@
No erg pieces uploaded yet.
' - - return render(request, 'histoall.html', - {'interactiveplot':script, - 'the_div':div, - 'id':theuser, - 'theuser':u, - 'teams':get_my_teams(request.user), - }) def keyvalue_get_default(key,options,def_options): try: @@ -2976,7 +2887,7 @@ def workout_histo_view(request,id=0): # Histogram for a date/time range -@login_required() +@user_passes_test(ispromember,login_url="/",redirect_field_name=None) def histo(request,theuser=0, startdate=timezone.now()-datetime.timedelta(days=365), enddate=timezone.now(), @@ -7442,14 +7353,13 @@ def instroke_chart(request,id=0,metric=''): return HttpResponseRedirect(url) # Cumulative stats page -@login_required() +@user_passes_test(ispromember,login_url="/",redirect_field_name=None) def cumstats(request,theuser=0, startdate=timezone.now()-datetime.timedelta(days=30), enddate=timezone.now(), deltadays=-1, startdatestring="", enddatestring="", - plotfield='spm', options={ 'includereststrokes':False, 'workouttypes':['rower','dynamic','slides'], @@ -7457,19 +7367,29 @@ def cumstats(request,theuser=0, 'rankingonly':False, }): - if 'options' in request.session: - options = request.session['options'] + r = getrequestrower(request,userid=theuser) + theuser = r.user + + if 'waterboattype' in request.session: + waterboattype = request.session['waterboattype'] + else: + waterboattype = types.waterboattype - try: - workouttypes = options['workouttypes'] - except KeyError: - workouttypes = ['rower','dynamic','slides'] + if 'rankingonly' in request.session: + rankingonly = request.session['rankingonly'] + else: + rankingonly = False - try: - includereststrokes = options['includereststrokes'] - except KeyError: - includereststrokes = False + if 'modalities' in request.session: + modalities = request.session['modalities'] + if len(modalities) > 1: + modality = 'all' + else: + modality = modalities[0] + else: + modalities = [m[0] for m in types.workouttypes] + modality = 'all' try: @@ -7477,12 +7397,16 @@ def cumstats(request,theuser=0, except KeyError: rankingonly = False + try: + includereststrokes = options['includereststrokes'] + except KeyError: + includereststrokes = False + + workstrokesonly = not includereststrokes waterboattype = types.waterboattype - - if deltadays>0: - startdate = enddate-datetime.timedelta(days=int(deltadays)) + if startdatestring != "": startdate = iso8601.parse_date(startdatestring) @@ -7495,33 +7419,13 @@ def cumstats(request,theuser=0, enddate = startdate startdate = s - promember=0 - if theuser == 0: - if 'rowerid' in request.session: - try: - r = Rower.objects.get(id=request.session['rowerid']) - theuser = r.user.id - except Rower.DoesNotExist: - theuser = request.user.id - else: - theuser = request.user.id - - - if not request.user.is_anonymous(): - r = getrower(request.user) - result = request.user.is_authenticated() and ispromember(request.user) - if result: - promember=1 - - if not promember: - return HttpResponseRedirect("/rowers/promembership/") # get all indoor rows of in date range + # process form - if request.method == 'POST' and "daterange" in request.POST: + if request.method == 'POST': form = DateRangeForm(request.POST) - deltaform = DeltaDaysForm(request.POST) - optionsform = StatsOptionsForm() + modalityform = TrendFlexModalForm(request.POST) if form.is_valid(): startdate = form.cleaned_data['startdate'] enddate = form.cleaned_data['enddate'] @@ -7529,111 +7433,118 @@ def cumstats(request,theuser=0, s = enddate enddate = startdate startdate = s - elif request.method == 'POST' and "datedelta" in request.POST: - deltaform = DeltaDaysForm(request.POST) - if deltaform.is_valid(): - deltadays = deltaform.cleaned_data['deltadays'] - if deltadays != 0 and isinstance(deltadays, Number): - enddate = timezone.now() - startdate = enddate-datetime.timedelta(days=deltadays) - if startdate > enddate: - s = enddate - enddate = startdate - startdate = s - form = DateRangeForm(initial={ - 'startdate': startdate, - 'enddate': enddate, - }) - optionsform = StatsOptionsForm() + if modalityform.is_valid(): + modality = modalityform.cleaned_data['modality'] + waterboattype = modalityform.cleaned_data['waterboattype'] + rankingonly = modalityform.cleaned_data['rankingonly'] + if modality == 'all': + modalities = [m[0] for m in types.workouttypes] else: - form = DateRangeForm() - optionsform = StatsOptionsForm() - elif request.method == 'POST' and 'options' in request.POST: - optionsform = StatsOptionsForm(request.POST) - if optionsform.is_valid(): - includereststrokes = optionsform.cleaned_data['includereststrokes'] - workstrokesonly = not includereststrokes - workouttypes = [] - rankingonly = optionsform.cleaned_data['rankingonly'] - waterboattype = optionsform.cleaned_data['waterboattype'] - for type in types.checktypes: - if optionsform.cleaned_data[type]: - workouttypes.append(type) + modalities = [modality] - options = { - 'includereststrokes':includereststrokes, - 'workouttypes':workouttypes, - 'waterboattype':waterboattype, - 'rankingonly':rankingonly, - } - request.session['options'] = options - form = DateRangeForm() - deltaform = DeltaDaysForm() - else: - form = DateRangeForm() - deltaform = DeltaDaysForm() + if modality != 'water': + waterboattype = [b[0] for b in types.boattypes] + + + request.session['modalities'] = modalities + request.session['waterboattype'] = waterboattype + request.session['rankingonly'] = rankingonly + form = DateRangeForm(initial={ + 'startdate': startdate, + 'enddate': enddate, + }) else: form = DateRangeForm(initial={ 'startdate': startdate, 'enddate': enddate, }) - deltaform = DeltaDaysForm() - optionsform = StatsOptionsForm() + includereststrokes = False + + workstrokesonly = not includereststrokes + modalityform = TrendFlexModalForm( + initial={ + 'modality':modality, + 'waterboattype':waterboattype, + 'rankingonly':rankingonly, + } + ) + + negtypes = [] + for b in types.boattypes: + if b[0] not in waterboattype: + negtypes.append(b[0]) + + + + script = '' + div = get_call() + js_resources = '' + css_resources = '' + + options = { + 'modality': modality, + 'theuser': theuser.id, + 'waterboattype':waterboattype, + 'startdatestring':startdatestring, + 'enddatestring':enddatestring, + 'rankingonly':rankingonly, + 'includereststrokes':includereststrokes, + } + + request.session['options'] = options + + + if modality == 'all': + modalities = [m[0] for m in types.workouttypes] + else: + modalities = [modality] + + try: + startdate = iso8601.parse_date(startdatestring) + except ParseError: + startdate = timezone.now()-datetime.timedelta(days=7) try: - r2 = getrower(theuser) - if rankingonly: - rankingpiece = [True] - else: - rankingpiece = [True,False] + enddate = iso8601.parse_date(enddatestring) + except ParseError: + enddate = timezone.now() + + + if enddate < startdate: + s = enddate + enddate = startdate + startdate = s + + promember=0 + if theuser == 0: + theuser = request.user.id + + if not request.user.is_anonymous(): + r = getrower(request.user) + result = request.user.is_authenticated() and ispromember(request.user) + if result: + promember=1 + + r2 = getrower(theuser) + + if rankingonly: + rankingpiece = [True,] + else: + rankingpiece = [True,False] - waterinclude = False + allworkouts = Workout.objects.filter( + user=r2, + workouttype__in=modalities, + boattype__in=waterboattype, + startdatetime__gte=startdate, + startdatetime__lte=enddate, + rankingpiece__in=rankingpiece + ).order_by("-date", "-starttime") - for ttype in types.otwtypes: - if ttype in workouttypes: - waterinclude = True - - if waterinclude: - workoutsw = Workout.objects.filter(user=r2, - startdatetime__gte=startdate, - startdatetime__lte=enddate, - workouttype='water', - boattype__in='waterboattype', - rankingpiece__in=rankingpiece, - ) - workouttypes = [w for w in workouttypes if w != 'water'] - - workoutse = Workout.objects.filter(user=r2, - startdatetime__gte=startdate, - startdatetime__lte=enddate, - workouttype__in=workouttypes, - rankingpiece__in=rankingpiece) - - if waterinclude: - allergworkouts = workoutse | workoutsw - allergworkouts = allergworkouts.distinct().order_by("-date", "-starttime") - else: - allergworkouts = workoutse.order_by("-date","-starttime") - - if waterinclude: - for ttype in types.otwtypes: - workouttypes.append(ttype) - - - - except Rower.DoesNotExist: - allergworkouts = [] - r2=0 - - try: - u = User.objects.get(id=theuser) - except User.DoesNotExist: - u = '' - - ids = [int(workout.id) for workout in allergworkouts] + ids = [int(workout.id) for workout in allworkouts] datemapping = { - w.id:w.date for w in allergworkouts + w.id:w.date for w in allworkouts } @@ -7649,10 +7560,7 @@ def cumstats(request,theuser=0, if datadf.empty: stats = {} - plotfield = 'spm' cordict = {} - div = "No Data found" - script = '' response = render(request, 'cumstats.html', @@ -7660,17 +7568,16 @@ def cumstats(request,theuser=0, 'stats':stats, 'teams':get_my_teams(request.user), 'options':options, + 'active':'nav-analysis', + 'rower':r, 'id':theuser, - 'theuser':u, + 'theuser':theuser, 'startdate':startdate, 'enddate':enddate, 'form':form, 'deltaform':deltaform, - 'optionsform':optionsform, + 'optionsform':modalityform, 'cordict':cordict, - 'plotscript':script, - 'plotdiv':div, - 'plotfield':plotfield, }) request.session['options'] = options @@ -7715,7 +7622,6 @@ def cumstats(request,theuser=0, datadf['workoutid'].replace(datemapping,inplace=True) datadf.rename(columns={"workoutid":"date"},inplace=True) datadf = datadf.sort_values(['date']) - script,div = interactive_boxchart(datadf,plotfield) # set options form correctly initial = {} @@ -7723,32 +7629,22 @@ def cumstats(request,theuser=0, initial['waterboattype'] = waterboattype initial['rankingonly'] = rankingonly - for wtype in types.checktypes: - if wtype in workouttypes: - initial[wtype] = True - else: - initial[wtype] = False - - - optionsform = StatsOptionsForm(initial=initial) response = render(request, 'cumstats.html', { 'stats':stats, 'teams':get_my_teams(request.user), + 'active':'nav-analysis', + 'rower':r, 'options':options, 'id':theuser, - 'theuser':u, + 'theuser':theuser, 'startdate':startdate, 'enddate':enddate, 'form':form, - 'deltaform':deltaform, - 'optionsform':optionsform, + 'optionsform':modalityform, 'cordict':cordict, - 'plotscript':script, - 'plotdiv':div, - 'plotfield':plotfield, }) request.session['options'] = options