Merge branch 'feature/manualranking' into develop
This commit is contained in:
@@ -555,6 +555,71 @@ def fetchcp(rower,theworkouts,table='cpdata'):
|
||||
return [],[],avgpower2
|
||||
|
||||
|
||||
# create a new workout from manually entered data
|
||||
def create_row_df(r,distance,duration,startdatetime,
|
||||
title = 'Manually added workout',notes='',
|
||||
workouttype='rower'):
|
||||
|
||||
|
||||
nr_strokes = int(distance/10.)
|
||||
|
||||
unixstarttime = arrow.get(startdatetime).timestamp
|
||||
|
||||
totalseconds = duration.hour*3600.
|
||||
totalseconds += duration.minute*60.
|
||||
totalseconds += duration.second
|
||||
totalseconds += duration.microsecond/1.e6
|
||||
|
||||
|
||||
spm = 60.*nr_strokes/totalseconds
|
||||
|
||||
step = totalseconds/float(nr_strokes)
|
||||
|
||||
elapsed = np.arange(0,totalseconds+step,step)
|
||||
|
||||
dstep = distance/float(nr_strokes)
|
||||
|
||||
d = np.arange(0,distance+dstep,dstep)
|
||||
|
||||
unixtime = unixstarttime + elapsed
|
||||
|
||||
pace = 500.*totalseconds/distance
|
||||
|
||||
if workouttype in ['rower','slides','dynamic']:
|
||||
velo = distance/totalseconds
|
||||
power = 2.8*velo**3
|
||||
else:
|
||||
power = 0
|
||||
|
||||
df = pd.DataFrame({
|
||||
'TimeStamp (sec)': unixtime,
|
||||
' Horizontal (meters)': d,
|
||||
' Cadence (stokes/min)': spm,
|
||||
' Stroke500mPace (sec/500m)':pace,
|
||||
' ElapsedTime (sec)':elapsed,
|
||||
' Power (watts)':power,
|
||||
})
|
||||
|
||||
timestr = strftime("%Y%m%d-%H%M%S")
|
||||
|
||||
csvfilename = 'media/df_' + timestr + '.csv'
|
||||
df[' ElapsedTime (sec)'] = df['TimeStamp (sec)']
|
||||
|
||||
row = rrdata(df=df)
|
||||
|
||||
row.write_csv(csvfilename, gzip = True)
|
||||
|
||||
id, message = save_workout_database(csvfilename, r,
|
||||
title=title,
|
||||
notes=notes,
|
||||
dosmooth=False,
|
||||
workouttype=workouttype,
|
||||
consistencychecks=False,
|
||||
totaltime=totalseconds)
|
||||
|
||||
return (id, message)
|
||||
|
||||
|
||||
# Processes painsled CSV file to database
|
||||
|
||||
|
||||
|
||||
38
rowers/templates/manualadd.html
Normal file
38
rowers/templates/manualadd.html
Normal file
@@ -0,0 +1,38 @@
|
||||
{% extends "base.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load rowerfilters %}
|
||||
{% load tz %}
|
||||
|
||||
|
||||
{% get_current_timezone as TIME_ZONE %}
|
||||
|
||||
{% block content %}
|
||||
<div class="grid_12 alpha">
|
||||
<h1>Add Workout Manually</h1>
|
||||
<div class="grid_6 alpha">
|
||||
{% if form.errors %}
|
||||
<p style="color: red;">
|
||||
Please correct the error{{ form.errors|pluralize }} below.
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
<form id="importantform"
|
||||
enctype="multipart/form-data" action="" method="post">
|
||||
<table width=100%>
|
||||
{{ form.as_table }}
|
||||
</table>
|
||||
{% csrf_token %}
|
||||
<div id="formbutton" class="grid_1 suffix_1 omega">
|
||||
<input class="button green" type="submit" value="Save">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="images" class="grid_6 omega">
|
||||
<p> </p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
@@ -72,7 +72,7 @@
|
||||
|
||||
<p>The table gives the best efforts achieved on the official Concept2 ranking pieces in the selected date range.</p>
|
||||
|
||||
<p>This page will evolve and try to give you guidance on where to improve.</p>
|
||||
|
||||
</div>
|
||||
<div id="form" class="grid_6 omega">
|
||||
<p>Use this form to select a different date range:</p>
|
||||
@@ -138,6 +138,19 @@
|
||||
<p> No ranking workouts found </p>
|
||||
{% endif %}
|
||||
|
||||
<p>Missing your best pieces? Upload stroke data of any Concept2
|
||||
ranking piece and they will be automatically added to this page.</p>
|
||||
<p> Don't have stroke data for official Concept2 ranking pieces?
|
||||
The <a href="/rowers/promembership">PRO membership</a> ranking piece functionality
|
||||
allows you to include your best non ranking pieces and even use
|
||||
parts of workouts for improved calculation accuracy.
|
||||
</p>
|
||||
|
||||
<p>Want to add race results but you don't have stroke data?
|
||||
<a href="/rowers/addmanual">Click here.</a></p>
|
||||
|
||||
<p>Scroll down for the chart and pace predictions for ranking pieces.</p>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@@ -126,6 +126,7 @@ urlpatterns = [
|
||||
url(r'^list-workouts/team/(?P<teamid>\d+)/$',views.workouts_view),
|
||||
url(r'^list-workouts/(?P<startdatestring>\w+.*)/(?P<enddatestring>\w+.*)$',views.workouts_view),
|
||||
url(r'^list-workouts/$',views.workouts_view),
|
||||
url(r'^addmanual/$',views.addmanual_view),
|
||||
url(r'^team-compare-select/team/(?P<teamid>\d+)/(?P<startdatestring>\w+.*)/(?P<enddatestring>\w+.*)$',views.team_comparison_select),
|
||||
url(r'^team-compare-select/team/(?P<teamid>\d+)/$',views.team_comparison_select),
|
||||
url(r'^team-compare-select/(?P<startdatestring>\w+.*)/(?P<enddatestring>\w+.*)$',views.team_comparison_select),
|
||||
|
||||
@@ -3096,6 +3096,82 @@ def histo(request,theuser=0,
|
||||
'teams':get_my_teams(request.user),
|
||||
})
|
||||
|
||||
# add a workout manually
|
||||
@login_required()
|
||||
def addmanual_view(request):
|
||||
r = Rower.objects.get(user=request.user)
|
||||
|
||||
if request.method == 'POST':
|
||||
# Form was submitted
|
||||
form = WorkoutForm(request.POST)
|
||||
if form.is_valid():
|
||||
# Get values from form
|
||||
name = form.cleaned_data['name']
|
||||
date = form.cleaned_data['date']
|
||||
starttime = form.cleaned_data['starttime']
|
||||
workouttype = form.cleaned_data['workouttype']
|
||||
duration = form.cleaned_data['duration']
|
||||
distance = form.cleaned_data['distance']
|
||||
notes = form.cleaned_data['notes']
|
||||
thetimezone = form.cleaned_data['timezone']
|
||||
try:
|
||||
boattype = request.POST['boattype']
|
||||
except KeyError:
|
||||
boattype = '1x'
|
||||
try:
|
||||
privacy = request.POST['privacy']
|
||||
except KeyError:
|
||||
privacy = 'visible'
|
||||
try:
|
||||
rankingpiece = form.cleaned_data['rankingpiece']
|
||||
except KeyError:
|
||||
rankingpiece =- Workout.objects.get(id=id).rankingpiece
|
||||
|
||||
startdatetime = (str(date) + ' ' + str(starttime))
|
||||
startdatetime = datetime.datetime.strptime(startdatetime,
|
||||
"%Y-%m-%d %H:%M:%S")
|
||||
startdatetime = timezone.make_aware(startdatetime)
|
||||
startdatetime = startdatetime.astimezone(
|
||||
pytz.timezone(thetimezone)
|
||||
)
|
||||
|
||||
|
||||
print name
|
||||
id,message = dataprep.create_row_df(r,
|
||||
distance,
|
||||
duration,startdatetime,
|
||||
title = name,
|
||||
notes=notes,
|
||||
workouttype=workouttype)
|
||||
|
||||
|
||||
|
||||
if message:
|
||||
messages.error(request,message)
|
||||
|
||||
if id:
|
||||
w = Workout.objects.get(id=id)
|
||||
w.rankingpiece = rankingpiece
|
||||
w.notes = notes
|
||||
w.save()
|
||||
messages.info(request,'New workout created')
|
||||
|
||||
|
||||
initial = {
|
||||
'workouttype':'rower',
|
||||
'date':datetime.date.today(),
|
||||
'starttime':timezone.now(),
|
||||
'timezone':r.defaulttimezone,
|
||||
'duration':datetime.timedelta(minutes=2),
|
||||
'distance':500,
|
||||
|
||||
}
|
||||
form = WorkoutForm(initial=initial)
|
||||
|
||||
return render(request,'manualadd.html',
|
||||
{'form':form,
|
||||
})
|
||||
|
||||
# Show ranking distances including predicted paces
|
||||
@login_required()
|
||||
def rankings_view(request,theuser=0,
|
||||
|
||||
Reference in New Issue
Block a user