Private
Public Access
1
0

split workout (bugs)

This commit is contained in:
Sander Roosendaal
2017-08-22 20:15:06 +02:00
parent 6a65214d48
commit f44fee0f12
5 changed files with 219 additions and 2 deletions

View File

@@ -820,6 +820,43 @@ def new_workout_from_file(r,f2,
return (id,message,f2)
def split_workout(r,parent,splitsecond,splitmode):
data,row = getrowdata_db(id=parent.id)
data['time'] = data['time']/1000.
data1 = data[data['time']<=splitsecond].copy()
data2 = data[data['time']>splitsecond].copy()
messages = []
ids = []
if 'keep first' in splitmode:
id,message = new_workout_from_df(r,data1,
title=parent.name+' First Part',
parent=parent)
messages.append(message)
ids.append(id)
if 'keep second' in splitmode:
data2['cumdist'] = data2['cumdist'] - data2['cumdist'].min()
data2['time'] = data2['time'] - data2['time'].min()
id,message = new_workout_from_df(r,data2,
title=parent.name+' Second Part',
parent=parent)
messages.append(message)
ids.append(id)
if not 'keep original' in splitmode:
if 'keep second' in splitmode or 'keep first' in splitmode:
parent.delete()
messages.append('Deleted Workout: '+parent.name)
else:
messages.append('That would delete your workout')
ids.append(parent.id)
return ids,messages
# Create new workout from data frame and store it in the database
# This routine should be used everywhere in views.py and mailprocessing.py
# Currently there is code duplication
@@ -853,6 +890,7 @@ def new_workout_from_df(r,df,
df.rename(columns = columndict,inplace=True)
starttimeunix = mktime(startdatetime.utctimetuple())
df[' ElapsedTime (sec)'] = df['TimeStamp (sec)']
df['TimeStamp (sec)'] = df['TimeStamp (sec)']+starttimeunix

View File

@@ -110,6 +110,21 @@ class TeamUploadOptionsForm(forms.Form):
class Meta:
fields = ['make_plot','plottype']
# This form is used on the Workout Split page
class WorkoutSplitForm(forms.Form):
splitchoices = (
('keep original','Keep Original'),
('keep first','Keep First Part'),
('keep second','Keep Second Part'),
)
splittime = forms.TimeField(input_formats=['%H:%M:%S.%f','%H:%M:%S','%M:%S.%f'])
splitmode = forms.MultipleChoiceField(
initial=['keep original',
'keep first',
'keep second'],
label='Split Mode',
choices=splitchoices)
# This form is used on the Analysis page to add a custom distance/time
# trial and predict the pace
class PredictedPieceForm(forms.Form):

View File

@@ -0,0 +1,113 @@
{% extends "base.html" %}
{% load staticfiles %}
{% load rowerfilters %}
{% load tz %}
{% block title %}Change Workout {% endblock %}
{% block content %}
<div id="workouts" class="grid_6 alpha">
{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
</p>
{% endif %}
<h1>Edit Workout Interval Data</h1>
<div class="grid_6 alpha">
<div class="grid_2 alpha">
<p>
<a class="button gray small" href="/rowers/workout/{{ workout.id }}/edit">Edit</a>
</p>
</div>
<div class="grid_2">
<p>
<a class="button gray small" href="/rowers/workout/{{ workout.id }}/export">Export</a>
</p>
</div>
<div class="grid_2 omega tooltip">
<p>
<a class="button gray small" href="/rowers/workout/{{ workout.id }}/advanced">Advanced</a>
</p>
<span class="tooltiptext">Advanced Functionality (More interactive Charts)</span>
</div>
</div>
{% localtime on %}
<table width=100%>
<tr>
<th>Date/Time:</th><td>{{ workout.startdatetime }}</td>
</tr><tr>
<th>Distance:</th><td>{{ workout.distance }}m</td>
</tr><tr>
<th>Duration:</th><td>{{ workout.duration |durationprint:"%H:%M:%S.%f" }}</td>
</tr><tr>
<th>Public link to this workout</th>
<td>
<a href="/rowers/workout/{{ workout.id }}">https://rowsandall.com/rowers/workout/{{ workout.id }}</a>
<td>
</tr><tr>
<th>Public link to interactive chart</th>
<td>
<a href="/rowers/workout/{{ workout.id }}/interactiveplot">https://rowsandall.com/rowers/workout/{{ workout.id }}/interactiveplot</a>
<td>
</tr>
</table>
{% endlocaltime %}
<h1>Workout Split</h1>
<p>Split your workout in half</p>
<form enctype="multipart/form-data" action="/rowers/workout/{{ workout.id }}/split" method="post">
<table width=100%>
{{ form.as_table }}
</table>
{% csrf_token %}
<div id="formbutton" class="grid_1 prefix_4 suffix_1">
<input class="button green" type="submit" value="Split">
</div>
</form>
</div>
<div id="advancedplots" class="grid_6 omega">
<div class="grid_6 alpha">
<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>
{{ thescript |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, true, true);
};
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>
<div id="interactiveplot" class="grid_6 omega">
{{ thediv |safe }}
</div>
</div>
</div>
{% endblock %}

View File

@@ -202,6 +202,7 @@ urlpatterns = [
url(r'^workout/(?P<id>\d+)/crewnerdsummary$',views.workout_crewnerd_summary_view),
url(r'^workout/(?P<id>\d+)/editintervals$',views.workout_summary_edit_view),
url(r'^workout/(?P<id>\d+)/restore$',views.workout_summary_restore_view),
url(r'^workout/(?P<id>\d+)/split$',views.workout_split_view),
url(r'^workout/(?P<id>\d+)/interactiveplot$',views.workout_biginteractive_view),
url(r'^workout/(?P<id>\d+)/view$',views.workout_view),
url(r'^workout/(?P<id>\d+)$',views.workout_view),

View File

@@ -36,7 +36,7 @@ from rowers.forms import (
RegistrationFormUniqueEmail,CNsummaryForm,UpdateWindForm,
UpdateStreamForm,WorkoutMultipleCompareForm,ChartParamChoiceForm,
FusionMetricChoiceForm,BoxPlotChoiceForm,MultiFlexChoiceForm,
TrendFlexModalForm,
TrendFlexModalForm,WorkoutSplitForm,
)
from rowers.models import Workout, User, Rower, WorkoutForm,FavoriteChart
from rowers.models import (
@@ -7773,6 +7773,8 @@ def workout_delete_view(request,id=0):
messages.info(request,'Workout deleted')
try:
url = request.session['referer']
if 'rowers/workout/' in url:
url = reverse(workouts_view)
except KeyError:
url = reverse(workouts_view)
@@ -7877,7 +7879,7 @@ def graph_show_view(request,id):
raise Http404("This graph doesn't exist")
except Workout.DoesNotExist:
raise Http404("This workout doesn't exist")
# Restore original stroke data and summary
@login_required()
def workout_summary_restore_view(request,id,message="",successmessage=""):
@@ -7935,6 +7937,54 @@ def workout_summary_restore_view(request,id,message="",successmessage=""):
)
return HttpResponseRedirect(url)
# Split a workout
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_split_view(request,id=id):
try:
row = Workout.objects.get(id=id)
if (checkworkoutuser(request.user,row)==False):
raise PermissionDenied("You are not allowed to edit this workout")
except Workout.DoesNotExist:
raise Http404("Workout doesn't exist")
r = getrower(request.user)
if not checkworkoutuser(request.user,row):
raise PermissionDenied("You are not allowed to edit this workout")
if request.method == 'POST':
form = WorkoutSplitForm(request.POST)
if form.is_valid():
splittime = form.cleaned_data['splittime']
splitsecond = splittime.hour*3600
splitsecond += splittime.minute*60
splitsecond += splittime.second
splitsecond += splittime.microsecond/1.e6
splitmode = form.cleaned_data['splitmode']
ids,mesgs = dataprep.split_workout(r,row,splitsecond,splitmode)
for message in mesgs:
messages.info(request,message)
url = reverse(workouts_view)
return HttpResponseRedirect(url)
form = WorkoutSplitForm()
# create interactive plot
try:
res = interactive_chart(id,promember=1)
script = res[0]
div = res[1]
except ValueError:
pass
return render(request, 'splitworkout.html',
{'form':form,
'workout':row,
'thediv':script,
'thescript':div,
})
# Fuse two workouts
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_fusion_view(request,id1=0,id2=1):