diff --git a/logos/logofornk.psd b/logos/logofornk.psd new file mode 100644 index 00000000..f2ced586 Binary files /dev/null and b/logos/logofornk.psd differ diff --git a/logos/logofornk.xcf b/logos/logofornk.xcf index e9a1041f..a412cf93 100644 Binary files a/logos/logofornk.xcf and b/logos/logofornk.xcf differ diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index 04c2ee23..248545b1 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -178,6 +178,56 @@ def interactive_forcecurve(theworkouts): plot.add_layout(avf) + peakflabel = Label(x=455,y=530,x_units='screen',y_units='screen', + text="Fpeak: {peakforceav:6.2f}".format(peakforceav=peakforceav), + background_fill_alpha=.7, + text_color='blue', + ) + + avflabel = Label(x=465,y=500,x_units='screen',y_units='screen', + text="Favg: {averageforceav:6.2f}".format(averageforceav=averageforceav), + background_fill_alpha=.7, + text_color='blue', + ) + + catchlabel = Label(x=460,y=470,x_units='screen',y_units='screen', + text="Catch: {catchav:6.2f}".format(catchav=catchav), + background_fill_alpha=0.7, + text_color='red', + ) + + peakforceanglelabel = Label(x=420,y=440,x_units='screen',y_units='screen', + text="Peak angle: {peakforceangleav:6.2f}".format(peakforceangleav=peakforceangleav), + background_fill_alpha=0.7, + text_color='red', + ) + + finishlabel = Label(x=455,y=410,x_units='screen',y_units='screen', + text="Finish: {finishav:6.2f}".format(finishav=finishav), + background_fill_alpha=0.7, + text_color='red', + ) + + sliplabel = Label(x=470,y=380,x_units='screen',y_units='screen', + text="Slip: {slipav:6.2f}".format(slipav=slipav), + background_fill_alpha=0.7, + text_color='red', + ) + + washlabel = Label(x=460,y=350,x_units='screen',y_units='screen', + text="Wash: {washav:6.2f}".format(washav=washav), + background_fill_alpha=0.7, + text_color='red', + ) + + plot.add_layout(peakflabel) + plot.add_layout(peakforceanglelabel) + plot.add_layout(avflabel) + plot.add_layout(catchlabel) + plot.add_layout(sliplabel) + plot.add_layout(washlabel) + plot.add_layout(finishlabel) + plot.xaxis.axis_label = "Angle" plot.yaxis.axis_label = "Force (lbs)" plot.title.text = theworkouts[0].name @@ -193,7 +243,14 @@ def interactive_forcecurve(theworkouts): source=source, source2=source2, avf=avf, - ), code=""" + avflabel=avflabel, + catchlabel=catchlabel, + finishlabel=finishlabel, + sliplabel=sliplabel, + washlabel=washlabel, + peakflabel=peakflabel, + peakforceanglelabel=peakforceanglelabel, + ), code=""" var data = source.data var data2 = source2.data @@ -254,6 +311,13 @@ def interactive_forcecurve(theworkouts): data['y'] = [0,thresholdforce,peakforceav,thresholdforce,0] avf.location = averageforceav + avflabel.text = 'Favg: '+averageforceav.toFixed(2) + catchlabel.text = 'Catch: '+catchav.toFixed(2) + finishlabel.text = 'Finish: '+finishav.toFixed(2) + sliplabel.text = 'Slip: '+slipav.toFixed(2) + washlabel.text = 'Wash: '+washav.toFixed(2) + peakflabel.text = 'Fpeak: '+peakforceav.toFixed(2) + peakforceanglelabel.text = 'Peak angle: '+peakforceangleav.toFixed(2) source.trigger('change'); """) diff --git a/rowers/models.py b/rowers/models.py index 87585c37..37177144 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -344,12 +344,17 @@ class WorkoutForm(ModelForm): duration = forms.TimeInput(format='%H:%M:%S.%f') class Meta: model = Workout - fields = ['name','date','starttime','duration','distance','workouttype','notes'] + fields = ['name','date','starttime','duration','distance','workouttype','boattype','notes'] widgets = { 'date': DateInput(), 'notes': forms.Textarea, 'duration': forms.TimeInput(format='%H:%M:%S.%f'), } + + def __init__(self, *args, **kwargs): + super(WorkoutForm, self).__init__(*args, **kwargs) + if self.instance.workouttype != 'water': + del self.fields['boattype'] class AdvancedWorkoutForm(ModelForm): class Meta: diff --git a/rowers/templates/advancedotw.html b/rowers/templates/advancedotw.html index 52d3751b..2892dcc4 100644 --- a/rowers/templates/advancedotw.html +++ b/rowers/templates/advancedotw.html @@ -7,177 +7,201 @@ {% block content %}
- Please correct the error{{ form.errors|pluralize }} below. -
- {% endif %} + {% if form.errors %} ++ Please correct the error{{ form.errors|pluralize }} below. +
+ {% endif %} -This is a preview of the page with advanced functionality for Pro users. See the page about Pro membership for more information and to sign up for Pro Membership - {% endif %} -
- Edit Workout -
-- Export -
+This is a preview of the page with advanced functionality for Pro users. + See the page about Pro membership for more information and to sign up for Pro Membership +{% endif %} +
+ Edit Workout +
++ Export +
-| Date: | {{ workout.date }} | -
|---|---|
| Time: | {{ workout.starttime }} | -
| Distance: | {{ workout.distance }}m | -
| Duration: | {{ workout.duration |durationprint:"%H:%M:%S.%f" }} | -Public link to this workout | -- https://rowsandall.com/rowers/workout/{{ workout.id }} - | - |
| Date: | {{ workout.date }} | +
|---|---|
| Time: | {{ workout.starttime }} | +
| Distance: | {{ workout.distance }}m | +
| Duration: | {{ workout.duration |durationprint:"%H:%M:%S.%f" }} | +Public link to this workout | ++ https://rowsandall.com/rowers/workout/{{ workout.id }} + | + |
- {% if user.rower.rowerplan == 'pro' %} - Compare Workouts - {% else %} - Compare Workouts - {% endif %} -
-- Compare this workout to other workouts. Plot HR, SPM, or pace vs time or distance for the two workouts. -
-- {% if user.rower.rowerplan == 'pro' %} - Smooth out Pace Data - {% else %} - Smooth out Pace Data - {% endif %} +
+ {% if user.rower.rowerplan == 'pro' %} + Compare Workouts + {% else %} + Compare Workouts + {% endif %} +
++ Compare this workout to other workouts. Plot HR, SPM, or pace vs time or distance for the two workouts. +
++ Flexible Interactive plot. Pick your own X and Y axis parameters. +
++ {% if user.rower.rowerplan == 'pro' %} + Edit Intervals + {% else %} + Edit Intervals + {% endif %} +
+ Enter or change the interval and summary data for your workout + ++ Enter or change the interval and summary data for your workout +
+- This will reduce noise on your pace data (EWMA average). The smoothing is irreversible - but you can use the reset smoothing button. -
-- {% if user.rower.rowerplan == 'pro' %} - Raw Data - {% else %} - Reset Smoothing - {% endif %} -
-- Reset pace data to values before smoothing (as originally imported/uploaded) -
-- {% if user.rower.rowerplan == 'pro' %} - CrewNerd Summary - {% else %} - CrewNerd Summary - {% endif %} +
+ {% if user.rower.rowerplan == 'pro' %} + CrewNerd Summary + {% else %} + CrewNerd Summary + {% endif %} + +
++ Upload a CrewNerd Summary (CSV file) to this workout. +
+- Upload a CrewNerd Summary (CSV file) to this workout. -
-- {% if user.rower.rowerplan == 'pro' %} - Geeky Stuff - {% else %} - Geeky Stuff - {% endif %} +
+ {% if user.rower.rowerplan == 'pro' %} + Stroke Profile (Empower) + {% else %} + Stroke Profile (Empower) + {% endif %} +
+ Analyze your stroke force profile (need Empower Oarlock data)+ Interactive plot of Stroke Profile (with Empower Oarlock) +
+- Add weather and current data and OTW power calculations. -
-- See (and save) the big interactive plot -
-+ {% if user.rower.rowerplan == 'pro' %} + OTW Power Plot + {% else %} + OTW Power Plot + {% endif %} +
+ Note: You must run the OTW calculations under Geeky Stuff first. Otherwise the plot will be empty + ++ Pace, wind corrected pace, power, equivalent erg power in a static plot +
++ {% if user.rower.rowerplan == 'pro' %} + Geeky Stuff + {% else %} + Geeky Stuff + {% endif %} + +
++ Add weather and current data and OTW power calculations. +
+- Flexible Interactive plot. Pick your own X and Y axis parameters. -
+ ++ {% if user.rower.rowerplan == 'pro' %} + Smooth out Pace Data + {% else %} + Smooth out Pace Data + {% endif %} + +
+ This will reduce noise on your pace data. The smoothing is irreversible but you can use the reset smoothing button. + ++ Pace data too noisy? Press this button! +
+- {% if user.rower.rowerplan == 'pro' %} - OTW Power Plot - {% else %} - OTW Power Plot - {% endif %} -
- Note: You must run the OTW calculations under Geeky Stuff first. Otherwise the plot will be empty ++ {% if user.rower.rowerplan == 'pro' %} + Raw Data + {% else %} + Reset Smoothing + {% endif %} +
++ Reset pace data to values before smoothing +
+-Pace, wind corrected pace, power, equivalent erg power in a static plot -
-- {% if user.rower.rowerplan == 'pro' %} - Edit Intervals - {% else %} - Edit Intervals - {% endif %} -
- Enter or change the interval and summary data for your workout - --Enter or change the interval and summary data for your workout -
-+ See (and save) the big interactive plot +
+