first version analyses collection
This commit is contained in:
@@ -150,6 +150,7 @@ class InstantPlanSelectForm(forms.Form):
|
||||
|
||||
# Instroke Metrics interactive chart form
|
||||
class InstrokeForm(forms.Form):
|
||||
name = forms.CharField(initial="", max_length=200,required=False)
|
||||
metric = forms.ChoiceField(label='metric',choices=(('a','a'),('b','b')))
|
||||
individual_curves = forms.BooleanField(label='individual curves',initial=False,
|
||||
required=False)
|
||||
@@ -159,6 +160,9 @@ class InstrokeForm(forms.Form):
|
||||
required=False, initial=0, widget=forms.HiddenInput())
|
||||
activeminutesmax = forms.IntegerField(
|
||||
required=False, initial=0, widget=forms.HiddenInput())
|
||||
notes = forms.CharField(required=False,
|
||||
max_length=200, label='Notes',
|
||||
widget=forms.Textarea)
|
||||
|
||||
def __init__(self, *args, **kwargs): # pragma: no cover
|
||||
choices = kwargs.pop('choices', [])
|
||||
|
||||
@@ -4080,7 +4080,8 @@ def interactive_streamchart(id=0, promember=0):
|
||||
|
||||
def instroke_interactive_chart(df,metric, workout, spm_min, spm_max,
|
||||
activeminutesmin, activeminutesmax,
|
||||
individual_curves):
|
||||
individual_curves,
|
||||
name='',notes=''):
|
||||
|
||||
|
||||
df_pos = (df+abs(df))/2.
|
||||
@@ -4184,6 +4185,24 @@ def instroke_interactive_chart(df,metric, workout, spm_min, spm_max,
|
||||
plot.add_layout(label)
|
||||
plot.add_layout(label2)
|
||||
|
||||
if name:
|
||||
namelabel = Label(x=50, y=480, x_units='screen', y_units='screen',
|
||||
text=name,
|
||||
background_fill_alpha=0.7,
|
||||
background_fill_color='white',
|
||||
text_color='black',
|
||||
)
|
||||
plot.add_layout(namelabel)
|
||||
|
||||
if notes:
|
||||
noteslabel = Label(x=50, y=50, x_units='screen', y_units='screen',
|
||||
text=notes,
|
||||
background_fill_alpha=0.7,
|
||||
background_fill_color='white',
|
||||
text_color='black',
|
||||
)
|
||||
plot.add_layout(noteslabel)
|
||||
|
||||
if individual_curves:
|
||||
for index,row in df.iterrows():
|
||||
plot.line(xvals,row,color='lightgray',line_width=1)
|
||||
|
||||
@@ -4969,10 +4969,12 @@ class ShareKey(models.Model):
|
||||
|
||||
class InStrokeAnalysis(models.Model):
|
||||
workout = models.ForeignKey(Workout, on_delete=models.CASCADE)
|
||||
rower = models.ForeignKey(Rower, on_delete=models.CASCADE)
|
||||
metric = models.CharField(max_length=140, blank=True, null=True)
|
||||
name = models.CharField(max_length=150, blank=True, null=True)
|
||||
date = models.DateField(blank=True, null=True)
|
||||
notes = models.TextField(blank=True)
|
||||
start_second = models.IntegerField(default=0)
|
||||
end_second = models.IntegerField(default=3600)
|
||||
min_spm = models.IntegerField(default=10)
|
||||
max_spm = models.IntegerField(default=45)
|
||||
spm_min = models.IntegerField(default=10)
|
||||
spm_max = models.IntegerField(default=45)
|
||||
|
||||
55
rowers/templates/instroke_analysis.html
Normal file
55
rowers/templates/instroke_analysis.html
Normal file
@@ -0,0 +1,55 @@
|
||||
{% extends "newbase.html" %}
|
||||
{% load static %}
|
||||
{% load rowerfilters %}
|
||||
|
||||
{% block title %}Rowsandall - Analysis {% endblock %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
<h1>In-Stroke Analysis for {{ rower.user.first_name }} {{ rower.user.last_name }}</h1>
|
||||
|
||||
|
||||
<ul class="main-content">
|
||||
{% if analyses %}
|
||||
{% for analysis in analyses %}
|
||||
<li class="rounder" id="analysis_{{ analysis.id }}">
|
||||
<h2>{{ analysis.name }}</h2>
|
||||
<a class="small" href="/rowers/analyses/{{ analysis.id }}/delete/"
|
||||
title="Delete">
|
||||
<i class="fas fa-trash-alt fa-fw"></i>
|
||||
</a>
|
||||
<hr>
|
||||
<p>
|
||||
{{ analysis.notes }}
|
||||
</p>
|
||||
<p>
|
||||
Workout: {{ analysis.workout }}
|
||||
</p>
|
||||
<p>
|
||||
{{ analysis.spm_min }} - {{ analysis.spm_max }} SPM,
|
||||
{{ analysis.start_second|secondstotimestring }} - {{ analysis.end_second|secondstotimestring }}
|
||||
<p>
|
||||
<p id="date">
|
||||
<span id="date">
|
||||
{{ analysis.date }}
|
||||
</span>
|
||||
</p>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<li class="grid_4">
|
||||
<p>You have not saved any analyses for {{ rower.user.first_name }}</p>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
||||
|
||||
{% block sidebar %}
|
||||
{% include 'menu_analytics.html' %}
|
||||
{% endblock %}
|
||||
@@ -143,7 +143,8 @@ $( function() {
|
||||
<label for="amount">Active Range:</label>
|
||||
<input type="text" id="amount" readonly style="border:0; color:#1c75bc; font-weight:bold;">
|
||||
</p>
|
||||
<input name='form' class="button" type="submit" value="Submit">
|
||||
<p><input name='_form' class="button" type="submit" value="Submit"></p>
|
||||
<p><input name='_save' class="button" type="submit" value="Save"></p>
|
||||
</form>
|
||||
</li>
|
||||
<li class="grid_4">
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<p>Rower: {{ rower.user.first_name }}</p>
|
||||
|
||||
<p>
|
||||
<a href="/rowers/alerts/">Try out Alerts</a>
|
||||
<a href="/rowers/analysis/instrokeanalysis/">Try out In-Stroke Analysis</a>
|
||||
</p>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -828,6 +828,8 @@ urlpatterns = [
|
||||
re_path(r'^errormessage/(?P<errormessage>[\w\ ]+.*)/$',
|
||||
views.errormessage_view, name='errormessage_view'),
|
||||
re_path(r'^analysis/$', views.analysis_view, name='analysis'),
|
||||
re_path(r'^analysis/instrokeanalysis/$', views.instrokeanalysis_view,
|
||||
name='instrokeanalysis_view'),
|
||||
re_path(r'^promembership', TemplateView.as_view(
|
||||
template_name='promembership.html'), name='promembership'),
|
||||
re_path(r'^checkout/(?P<planid>\d+)/$',
|
||||
|
||||
@@ -1845,6 +1845,32 @@ def agegrouprecordview(request, sex='male', weightcategory='hwt',
|
||||
})
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True)
|
||||
def instrokeanalysis_view(request, userid=0):
|
||||
r = getrequestrower(request, userid=userid)
|
||||
|
||||
analyses = InStrokeAnalysis.objects.filter(rower=r).order_by("-date")
|
||||
|
||||
breadcrumbs = [
|
||||
{
|
||||
'url': '/rowers/analysis',
|
||||
'name': 'Analysis'
|
||||
},
|
||||
{
|
||||
'url': reverse('instrokeanalysis_view'),
|
||||
'name': 'In-Stroke Analysis',
|
||||
},
|
||||
]
|
||||
|
||||
return render(request, 'instroke_analysis.html',
|
||||
{
|
||||
'breadcrumbs': breadcrumbs,
|
||||
'analyses': analyses,
|
||||
'rower': r,
|
||||
})
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True)
|
||||
def alerts_view(request, userid=0):
|
||||
|
||||
@@ -153,7 +153,7 @@ from rowers.models import (
|
||||
VideoAnalysis, ShareKey,
|
||||
StandardCollection, CourseStandard,
|
||||
VirtualRaceFollower, TombStone, InstantPlan,
|
||||
PlannedSessionStep,
|
||||
PlannedSessionStep,InStrokeAnalysis,
|
||||
)
|
||||
from rowers.models import (
|
||||
RowerPowerForm, RowerHRZonesForm, RowerForm, RowerCPForm, GraphImage, AdvancedWorkoutForm,
|
||||
|
||||
@@ -2981,6 +2981,8 @@ def instroke_chart_interactive(request, id=0):
|
||||
metric = instrokemetrics[0]
|
||||
spm_min = 15
|
||||
spm_max = 45
|
||||
name = ''
|
||||
notes = ''
|
||||
|
||||
activeminutesmax = int(rowdata.duration/60.)
|
||||
activeminutesmin = 0
|
||||
@@ -2996,6 +2998,24 @@ def instroke_chart_interactive(request, id=0):
|
||||
activeminutesmin = form.cleaned_data['activeminutesmin']
|
||||
activeminutesmax = form.cleaned_data['activeminutesmax']
|
||||
individual_curves = form.cleaned_data['individual_curves']
|
||||
notes = form.cleaned_data['notes']
|
||||
name = form.cleaned_data['name']
|
||||
|
||||
if "_save" in request.POST:
|
||||
instroke_analysis = InStrokeAnalysis(
|
||||
workout = w,
|
||||
metric = metric,
|
||||
name = name,
|
||||
date = timezone.now().date(),
|
||||
notes = notes,
|
||||
start_second = 60*activeminutesmin,
|
||||
end_second = 60*activeminutesmax,
|
||||
spm_min = spm_min,
|
||||
spm_max = spm_max,
|
||||
rower=w.user,
|
||||
)
|
||||
instroke_analysis.save()
|
||||
messages.info(request,'In-Stroke Analysis saved')
|
||||
|
||||
|
||||
activesecondsmin = 60.*activeminutesmin
|
||||
@@ -3016,6 +3036,7 @@ def instroke_chart_interactive(request, id=0):
|
||||
activeminutesmin,
|
||||
activeminutesmax,
|
||||
individual_curves,
|
||||
name=name,notes=notes,
|
||||
)
|
||||
|
||||
# change to range spm_min to spm_max
|
||||
|
||||
Reference in New Issue
Block a user