diff --git a/rowers/dataprep.py b/rowers/dataprep.py index f99a9468..3261c14f 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -158,6 +158,72 @@ def filter_df(datadf, fieldname, value, largerthan=True): return datadf +# joins workouts +def join_workouts(r,ids,title='Joined Workout', + parent=None, + setprivate=False, + forceunit='lbs'): + + message = None + + summary = '' + if parent: + oarlength = parent.oarlength + inboard = parent.inboard + workouttype = parent.workouttype + notes = parent.notes + summary = parent.summary + if parent.privacy == 'hidden': + makeprivate = True + else: + makeprivate = False + + startdatetime = parent.startdatetime + else: + oarlength = 2.89 + inboard = 0.88 + workouttype = 'rower' + notes = '' + summary = '' + makeprivate = False + startdatetime = timezone.now() + + if setprivate == True and makeprivate == False: + makeprivate = True + elif setprivate == False and makeprivate == True: + makeprivate = False + + + # reorder in chronological order + ws = Workout.objects.filter(id__in=ids).order_by("date", "starttime") + files = [w.csvfilename for w in ws] + + row = rdata(files[0]) + + files = files[1:] + + while len(files): + row2 = rdata(files[0]) + if row2 != 0: + row = row+row2 + files = files[1:] + + timestr = strftime("%Y%m%d-%H%M%S") + csvfilename = 'media/df_' + timestr + '.csv' + + row.write_csv(csvfilename,gzip=True) + id, message = save_workout_database(csvfilename, r, + workouttype=workouttype, + title=title, + notes=notes, + oarlength=oarlength, + inboard=inboard, + makeprivate=makeprivate, + dosmooth=False, + consistencychecks=False) + + return (id, message) + def df_resample(datadf): # time stamps must be in seconds @@ -801,6 +867,7 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', pytz.timezone(timezone_str) ).strftime('%H:%M:%S') + if makeprivate: privacy = 'hidden' else: diff --git a/rowers/forms.py b/rowers/forms.py index bad60f81..aa8cf8ed 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -521,7 +521,11 @@ class ChartParamChoiceForm(forms.Form): formaxlabels.pop('time') metricchoices = list(sorted(formaxlabels.items(), key = lambda x:x[1])) - + +class WorkoutJoinParamForm(forms.Form): + workout_name = forms.CharField(required = True, initial = 'Joined Workout') + set_private = forms.BooleanField(initial=False, required = False) + class FusionMetricChoiceForm(ModelForm): class Meta: model = Workout diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index 29edb78c..de097e7a 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -2475,9 +2475,12 @@ def interactive_flex_chart2(id=0,promember=0, slider_work_max = Slider(start=0.0, end=1500,value=1500.0, step=10, title="Max Work per Stroke",callback=callback) callback.args["maxwork"] = slider_work_max - - distmax = 100+100*int(rowdata['distance'].max()/100.) - + + try: + distmax = 100+100*int(rowdata['distance'].max()/100.) + except KeyError: + distmax = 100 + slider_dist_min = Slider(start=0,end=distmax,value=0,step=1, title="Min Distance",callback=callback) callback.args["mindist"] = slider_dist_min diff --git a/rowers/management/commands/processemail.py b/rowers/management/commands/processemail.py index cae0ccb0..f5b6c8f5 100644 --- a/rowers/management/commands/processemail.py +++ b/rowers/management/commands/processemail.py @@ -4,7 +4,7 @@ import sys import os import zipfile - +import re import time from time import strftime @@ -95,6 +95,24 @@ def processattachment(rower, fileobj, title, uploadoptions,testing=False): return workoutid +def get_from_address(message): + + from_address = message.from_address[0].lower() + + if message.encoded: + body = message.text.splitlines() + else: + body = message.get_body().splitlines() + + first_line = body[0].lower() + + if "quiske" in first_line: + match = re.search(r'[\w\.-]+@[\w\.-]+', first_line) + return match.group(0) + + return from_address + + class Command(BaseCommand): def add_arguments(self, parser): parser.add_argument( @@ -131,7 +149,9 @@ class Command(BaseCommand): uploadoptions = uploads.upload_options(body) - from_address = message.from_address[0].lower() + + from_address = get_from_address(message) + name = message.subject # get a list of users # theusers = User.objects.filter(email=from_address) diff --git a/rowers/templates/advancededit.html b/rowers/templates/advancededit.html index 0df1fff3..a43e0c04 100644 --- a/rowers/templates/advancededit.html +++ b/rowers/templates/advancededit.html @@ -6,198 +6,217 @@ {% block content %}
- 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 -
-- Workflow View -
-- 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 }} - | - |
+ 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 %} -- 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. -
+ -+
| 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 }} + | + |
- Enter or change the interval and summary data for your workout -
++ 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' or user.rower.rowerplan == 'coach' %} + 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 +
+- {% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %} - Dist Metrics Plot - {% else %} - Dist Metrics Plot - {% endif %} -
-- Various advanced stroke metrics plotted versus distance. -
++ {% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %} + Dist Metrics Plot + {% else %} + Dist Metrics Plot + {% endif %} +
++ Various advanced stroke metrics plotted versus distance. +
++ {% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %} + Time Metrics Plot + {% else %} + Time Metrics Plot + {% endif %} +
++ Various advanced stroke metrics plotted versus time. +
++ {% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %} + Power Histogram + {% else %} + Power Histogram + {% endif %} +
++ Plot the Power Histogram of this workout +
+- {% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %} - Time Metrics Plot - {% else %} - Time Metrics Plot - {% endif %} -
-- Various advanced stroke metrics plotted versus time. -
++ {% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %} + Glue + {% else %} + Glue + {% endif %} +
++ Glue multiple workouts together (into one workout). For example, to combine separately recorded intervals. +
++ {% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %} + Sensor Fusion + {% else %} + Sensor Fusion + {% endif %} +
++ Merge data from another source into this workout +
++ {% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %} + Split Workout + {% else %} + Split Workout + {% endif %} +
++ Split workout into two seperate workouts +
+- See (and save) the big interactive plot -
++ See (and save) the big interactive plot +
+- {% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %} - Power Histogram - {% else %} - Dist Metrics Plot - {% endif %} -
-- Plot the Power Histogram of this workout -
-- {% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %} - Sensor Fusion - {% else %} - Sensor Fusion - {% endif %} -
-- Merge data from another source into this workout -
-- {% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %} - Split Workout - {% else %} - Split Workout - {% endif %} -
-- Split workout into two seperate workouts -
-- See (and save) the big interactive plot -
-+ {% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %} + Glue + {% else %} + Glue + {% endif %} +
++ Glue multiple workouts together (into one workout). For example, to combine separately recorded intervals. +
+{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %} @@ -220,6 +224,17 @@
+ See (and save) the big interactive plot +
+{% if team %}