diff --git a/rowers/dataprep.py b/rowers/dataprep.py
index 33f961be..b0d015b9 100644
--- a/rowers/dataprep.py
+++ b/rowers/dataprep.py
@@ -1081,7 +1081,8 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower',
makeprivate=False,
oarlength=2.89, inboard=0.88,
forceunit='lbs',
- consistencychecks=False):
+ consistencychecks=False,
+ impeller=False):
message = None
powerperc = 100 * np.array([r.pw_ut2,
@@ -1289,7 +1290,8 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower',
startdatetime=workoutstartdatetime,
inboard=inboard, oarlength=oarlength,
timezone=timezone_str,
- privacy=privacy)
+ privacy=privacy,
+ impeller=impeller)
try:
w.save()
except ValidationError:
@@ -1421,24 +1423,30 @@ def handle_nonpainsled(f2, fileformat, summary=''):
oarlength = 2.89
inboard = 0.88
hasrecognized = False
+ impeller = False
row,hasrecognized,summary,fileformat = parsenonpainsled(fileformat,f2,summary)
# Handle c2log
if (fileformat == 'c2log' or fileformat == 'rowprolog'):
- return (0,'',0,0,'')
+ return (0,'',0,0,'',impeller)
if not hasrecognized:
- return (0,'',0,0,'')
+ return (0,'',0,0,'',impeller)
f_to_be_deleted = f2
# should delete file
f2 = f2[:-4] + 'o.csv'
- try:
- row2 = rrdata(df = row.df)
- row2.write_csv(f2, gzip=True)
- except:
- return (0,'',0,0,'')
+ row2 = rrdata(df = row.df)
+ if 'speedcoach2' in fileformat:
+ # impeller consistency
+ impellerdata, consistent, ratio = row.impellerconsistent(threshold=0.3)
+ if impellerdata and consistent:
+ impeller = True
+ if impellerdata and not consistent:
+ row2.use_gpsdata()
+ row2.write_csv(f2, gzip=True)
+
# os.remove(f2)
try:
@@ -1449,7 +1457,7 @@ def handle_nonpainsled(f2, fileformat, summary=''):
except:
pass
- return (f2, summary, oarlength, inboard, fileformat)
+ return (f2, summary, oarlength, inboard, fileformat, impeller)
# Create new workout from file and store it in the database
# This routine should be used everywhere in views.py and mailprocessing.py
@@ -1476,6 +1484,7 @@ def new_workout_from_file(r, f2,
inboard = 0.88
if len(fileformat) == 3 and fileformat[0] == 'zip':
f_to_be_deleted = f2
+ impeller = False
workoutsbox = Mailbox.objects.filter(name='workouts')[0]
msg = Message(mailbox=workoutsbox,
from_header=r.user.email,
@@ -1543,7 +1552,7 @@ def new_workout_from_file(r, f2,
# handle non-Painsled by converting it to painsled compatible CSV
if (fileformat != 'csv'):
- f2, summary, oarlength, inboard, fileformat = handle_nonpainsled(
+ f2, summary, oarlength, inboard, fileformat, impeller = handle_nonpainsled(
f2,
fileformat,
summary=summary
@@ -1571,7 +1580,8 @@ def new_workout_from_file(r, f2,
summary=summary,
inboard=inboard, oarlength=oarlength,
title=title,
- forceunit='N'
+ forceunit='N',
+ impeller=impeller,
)
return (id, message, f2)
diff --git a/rowers/models.py b/rowers/models.py
index 47b6d629..fd830b37 100644
--- a/rowers/models.py
+++ b/rowers/models.py
@@ -2734,6 +2734,7 @@ class Workout(models.Model):
choices=privacychoices)
rankingpiece = models.BooleanField(default=False,verbose_name='Ranking Piece')
duplicate = models.BooleanField(default=False,verbose_name='Duplicate Workout')
+ impeller = models.BooleanField(default=False,verbose_name='Impeller')
def save(self, *args, **kwargs):
user = self.user
diff --git a/rowers/templates/menu_workout.html b/rowers/templates/menu_workout.html
index f6edffd0..5c06f2a4 100644
--- a/rowers/templates/menu_workout.html
+++ b/rowers/templates/menu_workout.html
@@ -287,10 +287,25 @@
OTW Power
+ {% if 'speedcoach2' in workout.workoutsource %}
+
+
+
+ {% if workout.impeller %} {% else %}• {% endif %}Use GPS data
+
+
+
+
+
+ {% if workout.impeller %}• {% else %} {% endif %}Use Impeller data
+
+
+ {% endif %}
{% endif %}
- In-Stroke Metrics
+
+ In-Stroke Metrics
diff --git a/rowers/urls.py b/rowers/urls.py
index 5696c0d4..97a45af6 100644
--- a/rowers/urls.py
+++ b/rowers/urls.py
@@ -283,6 +283,10 @@ urlpatterns = [
re_path(r'^graph/(?P\d+)/delete/$',views.GraphDelete.as_view(),name='graph_delete'),
re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/get-thumbnails/$',views.get_thumbnails,
name='get_thumbnails'),
+ re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/otwuseimpeller/$',views.otw_use_impeller,
+ name='otw_use_impeller'),
+ re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/otwusegps/$',views.otw_use_gps,
+ name='otw_use_gps'),
re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/toggle-ranking/$',views.workout_toggle_ranking,
name='workout_toggle_ranking'),
re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/get-testscript/$',views.get_testscript,
diff --git a/rowers/views/analysisviews.py b/rowers/views/analysisviews.py
index a7ea6a70..5f19f8c1 100644
--- a/rowers/views/analysisviews.py
+++ b/rowers/views/analysisviews.py
@@ -4453,7 +4453,7 @@ def alert_report_view(request,id=0,userid=0,nperiod=0):
raise Http404("This alert doesn't exist")
- if alert.manager != request.user:
+ if not checkalertowner(alert,request.user):
raise PermissionDenied('You are not allowed to edit this Alert')
stats = alert_get_stats(alert,nperiod=nperiod)
diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py
index 592cbc14..f72537f9 100644
--- a/rowers/views/workoutviews.py
+++ b/rowers/views/workoutviews.py
@@ -456,18 +456,54 @@ def workout_forcecurve_view(request,id=0,workstrokesonly=False):
'teams':get_my_teams(request.user),
})
-# Test asynchronous tasking and messaging
-#@login_required()
-#def workout_test_task_view(request,id=0):
-# row = Workout.objects.get(id=id)
-# res = myqueue(queuehigh,addcomment2,request.user.id,row.id)#
-#
-#
-# url = reverse('workout_edit_view',
-# kwargs = {
-# 'id':int(id),
-# })
-# return HttpResponseRedirect(url)
+# Switch from GPS to Impeller (only for SpeedCoach 2, if impeller data)
+@login_required
+def otw_use_impeller(request,id=0):
+ w = get_workout(id)
+
+ if (checkworkoutuser(request.user,w)==False):
+ raise PermissionDenied("Access denied")
+
+ row = rdata(w.csvfilename)
+ success = row.use_impellerdata()
+ if success:
+ row.write_csv(w.csvfilename)
+ dataprep.update_strokedata(w.id,row.df)
+ w.impeller = True
+ w.save()
+ messages.info(request,'The distance and speed data are now based on Impeller data')
+ else:
+ messages.error(request,'No impeller data found')
+
+ url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)})
+
+ return HttpResponseRedirect(url)
+
+
+# Switch from Impeller to GPS (only for SpeedCoach 2, if impeller data)
+@login_required
+def otw_use_gps(request,id=0):
+ w = get_workout(id)
+
+ if (checkworkoutuser(request.user,w)==False):
+ raise PermissionDenied("Access denied")
+
+ row = rdata(w.csvfilename)
+ success = row.use_gpsdata()
+ if success:
+ row.write_csv(w.csvfilename)
+ dataprep.update_strokedata(w.id,row.df)
+ w.impeller = False
+ w.save()
+ messages.info(request,'The distance and speed data are now based on GPS data')
+ else:
+ messages.error(request,'No GPS data found')
+
+ url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)})
+
+ return HttpResponseRedirect(url)
+
+
# Show Stroke power histogram for a workout
@login_required()
diff --git a/templates/newbase.html b/templates/newbase.html
index 885e3f90..41486614 100644
--- a/templates/newbase.html
+++ b/templates/newbase.html
@@ -43,6 +43,7 @@
+