Private
Public Access
1
0

Merge branch 'release/v7.51'

This commit is contained in:
Sander Roosendaal
2018-09-08 13:13:52 +02:00
6 changed files with 290 additions and 81 deletions
+1 -1
View File
@@ -540,7 +540,7 @@ class TrendFlexModalForm(forms.Form):
initial = types.waterboattype) initial = types.waterboattype)
rankingonly = forms.BooleanField(initial=False, rankingonly = forms.BooleanField(initial=False,
label='Only Ranking Pieces', label='Only Ranking Pieces',
required=True) required=False)
# This form sets options for the summary stats page # This form sets options for the summary stats page
+28 -9
View File
@@ -935,17 +935,31 @@ class TrainingTarget(models.Model):
default=half_year_from_now) default=half_year_from_now)
notes = models.TextField(max_length=300,blank=True) notes = models.TextField(max_length=300,blank=True)
def __unicode__(self):
date = self.date
name = self.name
ownerfirst = self.rower.user.first_name
ownerlast = self.rower.user.last_name
stri = u'{ownerfirst} {ownerlast} {d} {n}'.format(
ownerfirst = ownerfirst,
ownerlast = ownerlast,
d = date.strftime('%Y-%m-%d'),
n = name
)
return stri
class TrainingTargetForm(ModelForm): class TrainingTargetForm(ModelForm):
class Meta: class Meta:
model = TrainingTarget model = TrainingTarget
fields = ['name','date','notes'] fields = ['name','date','notes']
widgets = { widgets = {
'date': SelectDateWidget( 'date': AdminDateWidget()
years=range(
timezone.now().year-1,timezone.now().year+1)),
} }
# SportTracks has a TrainingGoal like this # SportTracks has a TrainingGoal like this
#class TrainingGoal(models.Model): #class TrainingGoal(models.Model):
# rower = models.ForeignKey(Rower) # rower = models.ForeignKey(Rower)
@@ -976,14 +990,19 @@ class TrainingPlanForm(ModelForm):
fields = ['name','target','startdate','enddate'] fields = ['name','target','startdate','enddate']
widgets = { widgets = {
'startdate': SelectDateWidget( 'startdate': AdminDateWidget(),
years=range( 'enddate': AdminDateWidget()
timezone.now().year-1,timezone.now().year+1)),
'enddate': SelectDateWidget(
years=range(
timezone.now().year-1,timezone.now().year+1)),
} }
def __init__(self,*args, **kwargs):
targets = kwargs.pop('targets',None)
super(TrainingPlanForm, self).__init__(*args, **kwargs)
if targets:
targetchoices = [(x.id,x) for x in targets]
targetchoices.append((None,'---'))
self.fields['target'].choices = targetchoices
cycletypechoices = ( cycletypechoices = (
('filler','System Defined'), ('filler','System Defined'),
+117
View File
@@ -0,0 +1,117 @@
{% extends "base.html" %}
{% load staticfiles %}
{% load rowerfilters %}
{% block title %}Rowsandall Training Plans{% endblock %}
{% block scripts %}
{% endblock %}
{% block content %}
<style>
#mypointer {
cursor: pointer;
}
</style>
<div class="grid_12">
<div id="targets_table" class="grid_8 alpha">
<h1>Training Targets</h1>
{% if targets %}
<table width="100%" class="listtable shortpadded">
<thead>
<tr>
<th>Target Date</th>
<th>Name</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
{% for target in targets %}
<tr>
<td> {{ target.date }}</td>
<td> {{ target.name }}</td>
<td> {{ target.notes }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
No training targets found
{% endif %}
</div>
<div class="grid_4 omega">
<div class="grid_4" id="planform">
<h1>Add a target</h1>
<form id="newplanform"
enctype="multipart/form-data" action="" method="post">
<table width=100%>
{{ targetform.as_table }}
</table>
{% csrf_token %}
<div id="formbutton" class="grid_1 prefix_2 suffix_1 omega">
<input class="button green" type="submit" value="Save">
</div>
</form>
</div>
</div>
</div>
<div class="grid_12">
<div id="courses_table" class="grid_8 alpha">
<h1>Plans</h1>
{% if plans %}
<table width="100%" class="listtable shortpadded">
<thead>
<tr>
<th> Start Date</th>
<th> End Date</th>
<th> Name</th>
</tr>
</thead>
<tbody>
{% for plan in plans %}
<tr>
<td> {{ plan.startdate }} </td>
<td> {{ plan.enddate }}</td>
<td> {{ plan.name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p> No plans found </p>
{% endif %}
</div>
<div class="grid_4 omega">
<div class="grid_4" id="planform">
<h1>Add a plan</h1>
<form id="newplanform"
enctype="multipart/form-data" action="" method="post">
<table width=100%>
{{ form.as_table }}
</table>
{% csrf_token %}
<div id="formbutton" class="grid_1 prefix_2 suffix_1 omega">
<input class="button green" type="submit" value="Save">
</div>
</form>
</div>
</div>
</div>
{% endblock %}
+68 -67
View File
@@ -8,7 +8,7 @@
<div class="grid_12 alpha"> <div class="grid_12 alpha">
<h1>Workout Statistics for {{ workout.name }}</h1> <h1>Workout Statistics for {{ workout.name }}</h1>
<p> <p>
This is an experimental page which just lists a bunch of statistics for This page lists a bunch of statistics for
your workout. The mean is of a metric is the mean with equal weight for your workout. The mean is of a metric is the mean with equal weight for
each stroke. The time weighted mean takes into account the stroke each stroke. The time weighted mean takes into account the stroke
duration. duration.
@@ -43,76 +43,77 @@
<span class="tooltiptext">If your data source allows, this will show or hide strokes taken during rest intervals.</span> <span class="tooltiptext">If your data source allows, this will show or hide strokes taken during rest intervals.</span>
</div> </div>
</div> </div>
<div class="grid_4 alpha">
{% if stats %} <div class="grid_12 alpha tooltip">
{% for key, value in stats.items %} <span class="tooltiptext">
<h2>{{ value.verbosename }}</h2> <p>rPower: Equivalent steady state power for the duration of the workout.</p>
<table width="100%" class="listtable"> <p>Heart Rate Drift: Comparing heart rate normalized for average power for the first and second half of the workout</p>
<thead> <p>TRIMP: TRaining IMPact. A way to combine duration and heart rate into a single number.</p>
<tr> <p>rScore: Score based on rPower and workout duration to estimate training effect</p>
<th>Metric</th> <p>rScore (HR): Score based on heart rate, designed to give values comparable to rScore. Used instead of rScore for workouts without power data.</p>
<th>Value</th> </span>
</tr>
</thead>
<tbody>
<tr>
<td>Mean</td><td>{{ value.mean|floatformat:-2 }}</td>
</tr><tr>
<td>Time Weighted Mean</td><td> {{ value.wmean|floatformat:-2 }}</td>
</tr><tr>
<td>Minimum</td><td>{{ value.min|floatformat:-2 }}</td>
</tr><tr>
<td>25&#37;</td><td>{{ value.firstq|floatformat:-2 }}</td>
</tr><tr>
<td>Median</td><td>{{ value.median|floatformat:-2 }}</td>
</tr><tr>
<td>75&#37;</td><td>{{ value.thirdq|floatformat:-2 }}</td>
</tr><tr>
<td>Maximum</td><td>{{ value.max|floatformat:-2 }}</td>
</tr><tr>
<td>Standard Deviation</td><td>{{ value.std|floatformat:-2 }}</td>
</tr>
</tbody>
</table>
{% endfor %}
{% endif %}
</div>
<div class="grid_8 omega">
{% if otherstats %} {% if otherstats %}
<div class="grid_4 alpha"> <div class="grid_6 alpha">
&nbsp; <h2>Workout Metrics</h2>
</div> <table width="100%" class="listtable">
<div class="grid_4 omega tooltip"> <thead>
<span class="tooltiptext"> <tr>
<p>rPower: Equivalent steady state power for the duration of the workout.</p> <th>Metric</th>
<p>Heart Rate Drift: Comparing heart rate normalized for average power for the first and second half of the workout</p> <th>Value</th>
<p>TRIMP: TRaining IMPact. A way to combine duration and heart rate into a single number.</p> <th>Unit</th>
<p>rScore: Score based on rPower and workout duration to estimate training effect</p> </tr>
<p>rScore (HR): Score based on heart rate, designed to give values comparable to rScore. Used instead of rScore for workouts without power data.</p> </thead>
</span> <tbody>
<h2>Other Stats</h2> {% for key, value in otherstats.items %}
<table width="100%" class="listtable"> <tr>
<thead> <td>{{ value.verbose_name }}</td>
<tr> <td>{{ value.value }}</td>
<th>Metric</th> <td>{{ value.unit }}</td>
<th>Value</th> </tr>
<th>Unit</th> {% endfor %}
</tr> </tbody>
</thead> </table>
<tbody>
{% for key, value in otherstats.items %}
<tr>
<td>{{ value.verbose_name }}</td>
<td>{{ value.value }}</td>
<td>{{ value.unit }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div> </div>
{% endif %} {% endif %}
</div>
<div class="grid_8 alpha"> <div class="grid_12 alpha">
{% if stats %}
<h2>Statistics</h2>
<table width="100%" class="listtable">
<thead>
<tr>
<th>Metric</th>
<th>Mean</th>
<th>Time Weighted Mean</th>
<th>Minimum</th>
<th>25&#37;</th>
<th>Median</th>
<th>75&#37;</th>
<th>Maximum</th>
<th>Standard Deviation</th>
</tr>
</thead>
<tbody>
{% for key, value in stats.items %}
<tr>
<td>{{ value.verbosename }}</td>
<td>{{ value.mean|floatformat:-2 }}</td>
<td> {{ value.wmean|floatformat:-2 }}</td>
<td>{{ value.min|floatformat:-2 }}</td>
<td>{{ value.firstq|floatformat:-2 }}</td>
<td>{{ value.median|floatformat:-2 }}</td>
<td>{{ value.thirdq|floatformat:-2 }}</td>
<td>{{ value.max|floatformat:-2 }}</td>
<td>{{ value.std|floatformat:-2 }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
</div>
<div class="grid_12 alpha">
{% if cordict %} {% if cordict %}
<h2> Correlation matrix</h2> <h2> Correlation matrix</h2>
<p>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. <p>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.
+2
View File
@@ -419,6 +419,8 @@ urlpatterns = [
url(r'^workout/compare/(?P<id1>\d+)/(?P<id2>\d+)/(?P<xparam>\w+.*)/(?P<yparam>[\w\ ]+.*)/(?P<plottype>[\w\ ]+.*)$',views.workout_comparison_view2), url(r'^workout/compare/(?P<id1>\d+)/(?P<id2>\d+)/(?P<xparam>\w+.*)/(?P<yparam>[\w\ ]+.*)/(?P<plottype>[\w\ ]+.*)$',views.workout_comparison_view2),
url(r'^workout/compare/(?P<id1>\d+)/(?P<id2>\d+)/(?P<xparam>\w+.*)/(?P<yparam>[\w\ ]+.*)/$',views.workout_comparison_view2), url(r'^workout/compare/(?P<id1>\d+)/(?P<id2>\d+)/(?P<xparam>\w+.*)/(?P<yparam>[\w\ ]+.*)/$',views.workout_comparison_view2),
url(r'^test\_callback',views.rower_process_testcallback), url(r'^test\_callback',views.rower_process_testcallback),
url(r'^createplan$',views.rower_create_trainingplan),
url(r'^createplan/(?P<id>\d+)$',views.rower_create_trainingplan),
url(r'^workout/(?P<id>\d+)/test\_strokedata$',views.strokedataform), url(r'^workout/(?P<id>\d+)/test\_strokedata$',views.strokedataform),
url(r'^sessions/teamcreate$',views.plannedsession_teamcreate_view), url(r'^sessions/teamcreate$',views.plannedsession_teamcreate_view),
+74 -4
View File
@@ -64,7 +64,10 @@ from rowers.forms import (
) )
from rowers.models import ( from rowers.models import (
Workout, User, Rower, WorkoutForm,FavoriteChart, Workout, User, Rower, WorkoutForm,FavoriteChart,
PlannedSession, DeactivateUserForm,DeleteUserForm PlannedSession, DeactivateUserForm,DeleteUserForm,
TrainingPlan,TrainingPlanForm,TrainingTarget,TrainingTargetForm,
TrainingMacroCycle,TrainingMesoCycle,TrainingMicroCycle,
TrainingTarget,TrainingTargetForm,
) )
from rowers.models import ( from rowers.models import (
RowerPowerForm,RowerForm,GraphImage,AdvancedWorkoutForm, RowerPowerForm,RowerForm,GraphImage,AdvancedWorkoutForm,
@@ -5112,6 +5115,10 @@ def team_comparison_select(request,
else: else:
waterboattype = types.waterboattype waterboattype = types.waterboattype
if 'rankingonly' in request.session:
rankingonly = request.session['rankingonly']
else:
rankingonly = False
if 'modalities' in request.session: if 'modalities' in request.session:
modalities = request.session['modalities'] modalities = request.session['modalities']
@@ -5130,8 +5137,6 @@ def team_comparison_select(request,
enddate = dateform.cleaned_data['enddate'] enddate = dateform.cleaned_data['enddate']
startdatestring = startdate.strftime('%Y-%m-%d') startdatestring = startdate.strftime('%Y-%m-%d')
enddatestring = enddate.strftime('%Y-%m-%d') enddatestring = enddate.strftime('%Y-%m-%d')
request.session['startdate'] = startdatestring
request.session['enddate'] = enddatestring
else: else:
dateform = DateRangeForm(initial={ dateform = DateRangeForm(initial={
'startdate':startdate, 'startdate':startdate,
@@ -5153,6 +5158,11 @@ def team_comparison_select(request,
waterboattype = [b[0] for b in types.boattypes] waterboattype = [b[0] for b in types.boattypes]
if 'rankingonly' in modalityform.cleaned_data:
rankingonly = modalityform.cleaned_data['rankingonly']
else:
rankingonly = False
request.session['modalities'] = modalities request.session['modalities'] = modalities
request.session['waterboattype'] = waterboattype request.session['waterboattype'] = waterboattype
@@ -5203,6 +5213,9 @@ def team_comparison_select(request,
startdatetime__lte=enddate, startdatetime__lte=enddate,
workouttype__in=modalities).order_by("-date", "-starttime").exclude(boattype__in=negtypes) workouttype__in=modalities).order_by("-date", "-starttime").exclude(boattype__in=negtypes)
if rankingonly:
workouts = [w for w in workouts if w.rankingpiece]
query = request.GET.get('q') query = request.GET.get('q')
if query: if query:
query_list = query.split() query_list = query.split()
@@ -5224,7 +5237,8 @@ def team_comparison_select(request,
chartform = ChartParamChoiceForm(initial={'teamid':0}) chartform = ChartParamChoiceForm(initial={'teamid':0})
modalityform = TrendFlexModalForm(initial={ modalityform = TrendFlexModalForm(initial={
'modality':modality, 'modality':modality,
'waterboattype':waterboattype 'waterboattype':waterboattype,
'rankingonly':rankingonly,
}) })
@@ -14156,5 +14170,61 @@ def virtualevent_submit_result_view(request,id=0):
'w_form':w_form, 'w_form':w_form,
}) })
@user_passes_test(hasplannedsessions,login_url="/", redirect_field_name=None)
def rower_create_trainingplan(request,id=0):
therower = getrequestrower(request,userid=id)
theuser = therower.user
if request.method == 'POST' and 'date' in request.POST:
targetform = TrainingTargetForm(request.POST)
if targetform.is_valid():
name = targetform.cleaned_data['name']
date = targetform.cleaned_data['date']
notes = targetform.cleaned_data['notes']
t = TrainingTarget(rower=therower,
name=name,
date=date,
notes=notes)
t.save()
elif request.method == 'POST' and 'startdate' in request.POST:
form = TrainingPlanForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
target = form.cleaned_data['target']
startdate = form.cleaned_data['startdate']
enddate = form.cleaned_data['enddate']
p = TrainingPlan(
name=name,
rower=therower,
target=target,
startdate=startdate,
enddate=enddate,
)
p.save()
targets = TrainingTarget.objects.filter(rower=therower).order_by("date")
targetform = TrainingTargetForm()
plans = TrainingPlan.objects.filter(rower=therower).order_by("-startdate")
form = TrainingPlanForm(targets=targets)
return render(request,'trainingplan_create.html',
{
'form':form,
'plans':plans,
'targets':targets,
'targetform':targetform,
})