Private
Public Access
1
0

otw interactive power plot

This commit is contained in:
Sander Roosendaal
2018-10-08 21:18:42 +02:00
parent 3222ced28d
commit b82abace65
4 changed files with 139 additions and 78 deletions

View File

@@ -1,3 +1,4 @@
{% load rowerfilters %}
<h1>Workout</h1>
<ul class="cd-accordion-menu animated">
<li class="has-children" id="workout">
@@ -5,10 +6,17 @@
<label for="group-workout">Workout</label>
<ul>
<li id="workout-dashboard">
{% if user.is_authenticated and workout|may_edit:request %}
<a href="/rowers/workout/{{ workout.id }}/workflow">
<i class="fas fa-tachometer-alt fa-fw"></i>&nbsp;View
</a>
{% else %}
<a href="/rowers/workout/{{ workout.id }}/workflow">
<i class="fas fa-tachometer-alt fa-fw"></i>&nbsp;View
</a>
{% endif %}
</li>
{% if user.is_authenticated and workout|may_edit:request %}
<li id="workout-edit">
<a href="/rowers/workout/{{ workout.id }}/edit">
<i class="fas fa-pencil-alt fa-fw"></i>&nbsp;Edit
@@ -19,6 +27,7 @@
<i class="fas fa-pause fa-fw"></i>&nbsp;Intervals
</a>
</li>
{% endif %}
<li id="workout-stats">
<a href="/rowers/workout/{{ workout.id }}/stats">
<i class="fal fa-table fa-fw"></i>&nbsp;Statistics
@@ -28,12 +37,14 @@
<a href="/rowers/multi-compare">
<i class="fas fa-balance-scale fa-fw"></i>&nbsp;Compare
</a>
</li>
</li>
{% if user.is_authenticated and workout|may_edit:request %}
<li id="workout-delete">
<a href="/rowers/workout/{{ workout.id }}/delete">
<i class="fas fa-trash-alt fa-fw"></i>&nbsp;Delete
</a>
</li>
{% endif %}
</ul>
</li>
<li class="has-children" id="flexchart">
@@ -45,13 +56,21 @@
<i class="fas fa-chart-line fa-fw"></i>&nbsp;Flex Chart
</a>
</li>
{% if workout|water %}
<li id="chart-map">
<a href="/rowers/workout/{{ workout.id }}/map">
<i class="fas fa-map-marked-alt fa-fw"></i>&nbsp;Map
</a>
</li>
<li id="chart-otwpower">
<a href="/rowers/workout/{{ workout.id }}/interactiveotwplot">
<i class="fal fa-calculator-alt fa-fw"></i>&nbsp;OTW Power
</a>
</li>
{% endif %}
</ul>
</li>
{% if user.is_authenticated and workout|may_edit:request %}
<li class="has-children" id="chart">
<input type="checkbox" name="group-chart" id="group-chart">
<label for="group-chart">Static Charts</label>
@@ -76,11 +95,13 @@
<i class="fas fa-heartbeat fa-fw"></i>&nbsp;Heart Rate (Pie)
</a>
</li>
{% if workout|water %}
<li id="chart-otwpower">
<a href="/rowers/workout/{{ workout.id }}/addotwpowerplot">
<i class="fas fa-chart-area fa-fw"></i>&nbsp;OTW Power
</a>
</li>
{% endif %}
</ul>
</li>
<li class="has-children" id="export">
@@ -128,6 +149,7 @@
<input type="checkbox" name="group-advanced" id="group-advanced">
<label for="group-advanced">Advanced</label>
<ul>
{% if workout|water %}
<li id="advanced-wind">
<a href="/rowers/workout/{{ workout.id }}/wind">
<i class="fas fa-pennant fa-fw"></i>&nbsp;Wind
@@ -143,9 +165,11 @@
<i class="fas fa-calculator-alt fa-fw"></i>&nbsp;OTW Power
</a>
</li>
{% endif %}
<li id="advanced-instroke">
<a href="/rowers/workout/{{ workout.id }}/instroke">
<i class="fas fa-search-plus fa-fw"></i>&nbsp;In-Stroke Metrics</a></li>
</ul>
</li>
{% endif %}
</ul><!-- cd-accordion-menu -->

View File

@@ -1,83 +1,50 @@
{% extends "base.html" %}
{% extends "newbase.html" %}
{% load staticfiles %}
{% load rowerfilters %}
{% block title %}View Workout {% endblock %}
{% block content %}
{% block main %}
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
<script async="true" type="text/javascript">
Bokeh.set_log_level("info");
</script>
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
<script async="true" type="text/javascript">
Bokeh.set_log_level("info");
</script>
{{ interactiveplot |safe }}
<script>
// Set things up to resize the plot on a window resize. You can play with
// the arguments of resize_width_height() to change the plot's behavior.
var plot_resize_setup = function () {
var plotid = Object.keys(Bokeh.index)[0]; // assume we have just one plot
var plot = Bokeh.index[plotid];
var plotresizer = function() {
// arguments: use width, use height, maintain aspect ratio
plot.resize_width_height(true, false, false);
};
window.addEventListener('resize', plotresizer);
plotresizer();
};
window.addEventListener('load', plot_resize_setup);
</script>
<style>
/* Need this to get the page in "desktop mode"; not having an infinite height.*/
html, body {height: 100%; margin:5px;}
</style>
{{ interactiveplot |safe }}
<div id="workouts" class="grid_12 alpha">
<h1>Interactive Plot</h1>
<h1>Interactive Plot</h1>
{% if user.is_authenticated and mayedit %}
<div class="grid_2 alpha">
<p>
<a class="button gray small" href="/rowers/workout/{{ workout.id }}/edit">Edit Workout</a>
</p>
</div>
<div class="grid_2">
<p>
<a class="button gray small" href="/rowers/workout/{{ workout.id }}/advanced">Advanced Edit</a>
</p>
</div>
<div class="grid_2">
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/wind">Edit Wind Data</a>
</div>
<div class="grid_2">
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/stream">Edit Stream Data</a>
</div>
<div class="grid_2">
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/otwsetpower">OTW Power</a>
</div>
{% endif %}
</div>
<div id="theplot" class="grid_12 alpha flexplot">
<ul class="main-content">
<li class="grid_4">
{{ the_div|safe }}
</div>
</li>
<li class="grid_4">
<p>
<h2>Notes</h2>
<ul>
<li>
Is your erg pace slower than you expected? This may be a sign of room for improvement regarding your technique. An alternative explanation is that your team mates are fatter than they told you! For example, put 80.0 kg if your four consists of 2 70kg guys and 2 90kg guys.
</li>
<li>
In order to speed up the calculation, we are running the calculation only for every 10th datapoint, using interpolation in between. Some very fine pace shifts may disappear.
</li>
<li>
While the wind and stream correction is fairly reliable, the OTW to OTE conversion sometimes throws errors. Those data points are omitted and replaced by interpolated values. We are sorry if this messed up some of your plots.
</li>
<li>
Read more details about the way we calculate things <a href="/rowers/physics">here</a>.
</li>
</ul>
</p>
</li>
<div class="grid_12">
<p>
<h3>Notes</h3>
<ul>
<li>Is your erg pace slower than you expected? This may be a sign of room for improvement regarding your technique. An alternative explanation is that your team mates are fatter than they told you! For example, put 80.0 kg if your four consists of 2 70kg guys and 2 90kg guys.</li>
<li>In order to speed up the calculation, we are running the calculation only for every 10th datapoint, using interpolation in between. Some very fine pace shifts may disappear.</li>
<li>While the wind and stream correction is fairly reliable, the OTW to OTE conversion sometimes throws errors. Those data points are omitted and replaced by interpolated values. We are sorry if this messed up some of your plots.</li>
<li>Read more details about the way we calculate things <a href="/rowers/physics"</a>here</a>.</li>
</ul>
</p>
</ul>
</div>
{% endblock %}
{% endblock %}
{% block sidebar %}
{% include 'menu_workout.html' %}
{% endblock %}

View File

@@ -13,6 +13,8 @@ from rowers.plannedsessions import (
race_can_register, race_can_submit,race_rower_status
)
from rowers.types import otwtypes
def strfdelta(tdelta):
minutes,seconds = divmod(tdelta.seconds,60)
tenths = int(tdelta.microseconds/1e5)
@@ -48,6 +50,10 @@ def secondstotimestring(tdelta):
return res
@register.filter
def water(workout):
return workout.workouttype in otwtypes
@register.filter
def ddays(ddelta):
return ddelta.days+1
@@ -120,6 +126,18 @@ def is_session_manager(id,user):
return ps.manager == user
from rowers.models import checkworkoutuser
@register.filter
def may_edit(workout,request):
mayedit = 0
if request.user == workout.user.user:
mayedit = True
if checkworkoutuser(request.user,workout):
mayedit = True
return mayedit
@register.filter(name='times')
def times(number):
return range(number)

View File

@@ -7132,6 +7132,12 @@ def workout_otwsetpower_view(request,id=0,message="",successmessage=""):
w = get_workout(id)
r = getrower(request.user)
mayedit = 0
if request.user == w.user.user:
mayedit=1
if checkworkoutuser(request.user,w):
mayedit=1
if (checkworkoutuser(request.user,w)==False):
message = "You are not allowed to edit this workout"
messages.error(request,message)
@@ -7246,6 +7252,7 @@ def workout_otwsetpower_view(request,id=0,message="",successmessage=""):
'otwsetpower.html',
{'workout':w,
'rower':w,
'mayedit':mayedit,
'active':'nav-workouts',
'breadcrumbs':breadcrumbs,
'teams':get_my_teams(request.user),
@@ -7255,6 +7262,12 @@ def workout_otwsetpower_view(request,id=0,message="",successmessage=""):
@login_required()
def instroke_view(request,id=0):
w = get_workout(id)
r = getrower(request.user)
mayedit = 0
if request.user == w.user.user:
mayedit=1
if checkworkoutuser(request.user,w):
mayedit=1
breadcrumbs = [
{
@@ -7298,6 +7311,7 @@ def instroke_view(request,id=0):
'rower':r,
'active':'nav-workouts',
'breadcrumbs':breadcrumbs,
'mayedit':mayedit,
'teams':get_my_teams(request.user),
'instrokemetrics':instrokemetrics,
})
@@ -7727,6 +7741,12 @@ def workout_stats_view(request,id=0,message="",successmessage=""):
r = getrower(request.user)
w = get_workout(id)
mayedit = 0
if request.user == w.user.user:
mayedit=1
if checkworkoutuser(request.user,w):
mayedit=1
breadcrumbs = [
{
'url':'/rowers/list-workouts',
@@ -7877,6 +7897,7 @@ def workout_stats_view(request,id=0,message="",successmessage=""):
'teams':get_my_teams(request.user),
'workout':w,
'rower':r,
'mayedit':mayedit,
'breadcrumbs':breadcrumbs,
'active':'nav-workouts',
'workstrokesonly':workstrokesonly,
@@ -8555,14 +8576,31 @@ def workout_biginteractive_view(request,id=0,message="",successmessage=""):
# The interactive plot with wind corrected pace for OTW outings
def workout_otwpowerplot_view(request,id=0,message="",successmessage=""):
row = get_workout(id)
w = get_workout(id)
r = getrower(request.user)
breadcrumbs = [
{
'url':'/rowers/list-workouts',
'name':'Workouts'
},
{
'url':get_workout_default_page(request,id),
'name': str(w.id)
},
{
'url':reverse(workout_otwpowerplot_view,kwargs={'id':id}),
'name': 'Interactive OTW Power Plot'
}
]
# check if user is owner of this workout
# create interactive plot
f1 = row.csvfilename
u = row.user.user
f1 = w.csvfilename
u = w.user.user
# r = getrower(u)
promember=0
@@ -8572,7 +8610,7 @@ def workout_otwpowerplot_view(request,id=0,message="",successmessage=""):
result = request.user.is_authenticated() and ispromember(request.user)
if result:
promember=1
if request.user == row.user.user:
if request.user == w.user.user:
mayedit=1
# create interactive plot
@@ -8585,7 +8623,10 @@ def workout_otwpowerplot_view(request,id=0,message="",successmessage=""):
return render(request,
'otwinteractive.html',
{'workout':row,
{'workout':w,
'rower':r,
'active':'nav-workouts',
'breadcrumbs':breadcrumbs,
'teams':get_my_teams(request.user),
'interactiveplot':script,
'the_div':div,
@@ -9354,6 +9395,7 @@ def course_upload_view(request):
def workout_add_chart_view(request,id,plotnr=1):
w = get_workout(id)
r = getrower(request.user)
plotnr = int(plotnr)
@@ -9378,10 +9420,9 @@ def workout_add_chart_view(request,id,plotnr=1):
except KeyError:
request.session['async_tasks'] = [(jobid,'make_plot')]
try:
url = request.session['referer']
except KeyError:
url = "/rowers/workout/"+str(w.id)+"/edit"
url = reverse(r.defaultlandingpage,kwargs={'id':str(w.id)})
return HttpResponseRedirect(url)
@@ -14617,11 +14658,22 @@ class WorkoutDelete(DeleteView):
}
]
mayedit=0
if not self.request.user.is_anonymous():
r = getrower(self.request.user)
result = self.request.user.is_authenticated() and ispromember(self.request.user)
if result:
promember=1
if self.request.user == self.object.user.user:
mayedit=1
context['active'] = 'nav-workouts'
context['rower'] = getrower(self.request.user)
context['breadcrumbs'] = breadcrumbs
context['workout'] = self.object
context['mayedit'] = mayedit
context['promember'] = promember
return context