From d9ffc1612788bdb66e91e881dc549c52220b94e2 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Thu, 9 Jan 2025 13:47:43 +0100 Subject: [PATCH 1/7] suppressing commutes and start of auto_wps --- rowers/models.py | 5 +++ rowers/templates/list_workouts.html | 48 ++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/rowers/models.py b/rowers/models.py index edf851aa..dbaa5d34 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -1257,6 +1257,7 @@ class Rower(models.Model): verbose_name='Receive email notifications') imports_are_private = models.BooleanField(default=False, verbose_name='Make imports private by default') + show_commutes = models.BooleanField(default=False, verbose_name='Show commutes in workout list') # Friends/Team friends = models.ManyToManyField("self", blank=True) @@ -1295,6 +1296,9 @@ class Rower(models.Model): fastpaceotw = models.DurationField( default=otwpacefast, verbose_name='Fastest OTW Pace') + running_wps = models.FloatField(default=400.0, verbose_name='Running Work per Stroke') + running_wps_erg = models.FloatField(default=500.0, verbose_name='Running Work per Stroke (ergometer)') + fav_analysis = models.CharField(default='compare', choices=favanalysischoices, max_length=100, verbose_name='Favorite Analysis') @@ -5177,6 +5181,7 @@ class AccountRowerForm(ModelForm): 'defaultlandingpage', 'defaultlandingpage2', 'defaultlandingpage3', + 'show_commutes', 'offercoaching', 'autojoin', 'emailalternatives'] widgets = { diff --git a/rowers/templates/list_workouts.html b/rowers/templates/list_workouts.html index 51e40308..4d41fffa 100644 --- a/rowers/templates/list_workouts.html +++ b/rowers/templates/list_workouts.html @@ -104,6 +104,7 @@ {% endif %} {% for workout in workouts %} + {% if not workout.is_commute %}
  • {% if request.GET.selectworkouts %} @@ -198,7 +199,52 @@
  • - + {% elif user.rower.show_commutes %} +
  • +
    +
    + +
    + +
    + Distance + {{ workout.distance|distanceprint }} +
    +
    + Time + {{ workout.duration |durationprint:"%H:%M:%S.%f" }} +
    +
    + {% if workout|may_edit:request %} + + + {% else %} +   + {% endif %} +
    +
    + {% if workout|may_edit:request %} + {% if rower.defaultlandingpage2 != 'workout_delete' %} + + + {% else %} + + + {% endif %} + {% else %} +   + {% endif %} +
    +
    +
  • + {% endif %} + {% endfor %} {% else %} From e191ab4fc3dff4cb4a5156386770f39947810d9c Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Thu, 9 Jan 2025 14:33:28 +0100 Subject: [PATCH 2/7] new feature first code --- rowers/dataprep.py | 30 ++++++++++++++++++- rowers/templates/rower_simplepreferences.html | 21 +++++++++++-- rowers/templatetags/rowerfilters.py | 12 ++++++++ 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/rowers/dataprep.py b/rowers/dataprep.py index 9dbfd80a..cae865fe 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -1274,7 +1274,7 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', pass # recalculate power data - if workouttype == 'rower' or workouttype == 'dynamic' or workouttype == 'slides': + if workouttype in otetypes: try: if r.erg_recalculatepower: row.erg_recalculatepower() @@ -1282,6 +1282,7 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', except: pass + averagehr = row.df[' HRCur (bpm)'].mean() maxhr = row.df[' HRCur (bpm)'].max() @@ -1451,6 +1452,33 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', _ = update_wps(r, mytypes.otwtypes) _ = update_wps(r, mytypes.otetypes) + # set user running wps + if workouttype in otetypes: + cntr = Workout.objects.filter(user=r, workouttype__in=otetypes, + startdatetime__gt=tz.now()-tz.timedelta(days=42)).count() + new_value = (cntr*r.running_wps_erg + row.df['driveenergy'].mean())/(cntr+1.0) + # if new_value is not zero or infinite or -inf, r.running_wps can be set to value + if not (math.isnan(new_value) or math.isinf(new_value) or new_value == 0): + r.running_wps_erg = new_value + elif not (math.isnan(r.running_wps_erg) or math.isinf(r.running_wps_erg) or r.running_wps_erg == 0): + pass + else: + r.running_wps_erg = 600. + r.save() + + if workouttype in otwtypes: + cntr = Workout.objects.filter(user=r, workouttype__in=otwtypes, + startdatetime__gt=tz.now()-tz.timedelta(days=42)).count() + new_value = (cntr*r.running_wps_erg + row.df['driveenergy'].mean())/(cntr+1.0) + if not (math.isnan(new_value) or math.isinf(new_value) or new_value == 0): + r.running_wps = new_value + elif not (math.isnan(r.running_wps) or math.isinf(r.running_wps) or r.running_wps == 0): + pass + else: + r.running_wps = 400. + r.save() + + _ = myqueue(queuehigh, handle_calctrimp, w.id, f2, r.ftp, r.sex, r.hrftp, r.max, r.rest) diff --git a/rowers/templates/rower_simplepreferences.html b/rowers/templates/rower_simplepreferences.html index 7aa851fd..9accb6d9 100644 --- a/rowers/templates/rower_simplepreferences.html +++ b/rowers/templates/rower_simplepreferences.html @@ -40,41 +40,58 @@ - + + + + + + - + + + + + + + + + + + + +
    ID Zone NameLower Boundary (Watt) Lower Boundary (Watt)ID Zone NameLower Boundary (Watt) Lower Boundary (Watt)Target SPMTarget SPM
    IndoorOTWIndoorOTWIndoorOTW
    1{{ user.rower.powerzones.0 }}
    2{{ user.rower.powerzones.1 }} {{ user.rower.pw_ut2 }} {{ user.rower.pw_ut2|otwslack:user }}{{ user.rower.pw_ut2|target_spm_erg:user }}{{ user.rower.pw_ut2|target_spm_otw:user }}
    3{{ user.rower.powerzones.2 }} {{ user.rower.pw_ut1 }} {{ user.rower.pw_ut1|otwslack:user }}{{ user.rower.pw_ut1|target_spm_erg:user }}{{ user.rower.pw_ut1|target_spm_otw:user }}
    4{{ user.rower.powerzones.3 }} {{ user.rower.pw_at }} {{ user.rower.pw_at|otwslack:user }}{{ user.rower.pw_at|target_spm_erg:user }}{{ user.rower.pw_at|target_spm_otw:user }}
    5{{ user.rower.powerzones.4 }} {{ user.rower.pw_tr }} {{ user.rower.pw_tr|otwslack:user }}{{ user.rower.pw_tr|target_spm_erg:user }}{{ user.rower.pw_tr|target_spm_otw:user }}
    6{{ user.rower.powerzones.5 }} {{ user.rower.pw_an }} {{ user.rower.pw_an|otwslack:user }}{{ user.rower.pw_an|target_spm_erg:user }}{{ user.rower.pw_an|target_spm_otw:user }}
    diff --git a/rowers/templatetags/rowerfilters.py b/rowers/templatetags/rowerfilters.py index 60a97c29..d6fe9ff1 100644 --- a/rowers/templatetags/rowerfilters.py +++ b/rowers/templatetags/rowerfilters.py @@ -1065,3 +1065,15 @@ def previousworkout(workout, user): def otwslack(value, user): r = Rower.objects.get(user=user) return int(value*(100.-r.otwslack)/100.) + +@register.filter +def target_spm_erg(value, user): + r = Rower.objects.get(user=user) + value = 1.0*value + return int(value*60/r.running_wps_erg) + +@register.filter +def target_spm_otw(value, user): + r = Rower.objects.get(user=user) + value = value*(100.-r.otwslack)/100. + return int(value*60/r.running_wps) From 26a5f7acfcb1945aa0bf4b3f348821dc0e9a05fd Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Thu, 9 Jan 2025 15:30:47 +0100 Subject: [PATCH 3/7] ignore duplicates for rolling wps --- rowers/dataprep.py | 10 +++++---- rowers/forms.py | 4 ++++ rowers/templates/list_workouts.html | 3 +++ rowers/templates/rower_simplepreferences.html | 20 +++++++++--------- rowers/tests/testdata/testdata.tcx.gz | Bin 3989 -> 3989 bytes rowers/views/workoutviews.py | 16 ++++++++++++++ 6 files changed, 39 insertions(+), 14 deletions(-) diff --git a/rowers/dataprep.py b/rowers/dataprep.py index cae865fe..0864eec7 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -1453,9 +1453,10 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', _ = update_wps(r, mytypes.otetypes) # set user running wps - if workouttype in otetypes: + if not duplicate and workouttype in otetypes: cntr = Workout.objects.filter(user=r, workouttype__in=otetypes, - startdatetime__gt=tz.now()-tz.timedelta(days=42)).count() + startdatetime__gt=tz.now()-tz.timedelta(days=42), + duplicate=False).count() new_value = (cntr*r.running_wps_erg + row.df['driveenergy'].mean())/(cntr+1.0) # if new_value is not zero or infinite or -inf, r.running_wps can be set to value if not (math.isnan(new_value) or math.isinf(new_value) or new_value == 0): @@ -1466,9 +1467,10 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', r.running_wps_erg = 600. r.save() - if workouttype in otwtypes: + if not duplicate and workouttype in otwtypes: cntr = Workout.objects.filter(user=r, workouttype__in=otwtypes, - startdatetime__gt=tz.now()-tz.timedelta(days=42)).count() + startdatetime__gt=tz.now()-tz.timedelta(days=42), + duplicate=False).count() new_value = (cntr*r.running_wps_erg + row.df['driveenergy'].mean())/(cntr+1.0) if not (math.isnan(new_value) or math.isinf(new_value) or new_value == 0): r.running_wps = new_value diff --git a/rowers/forms.py b/rowers/forms.py index 44469278..2db9b8bf 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -1226,6 +1226,10 @@ bulkactions = ( ('remove','remove'), ('export','export'), ('rower assign','rower assign'), + ('set commute','set commute'), + ('set private','set private'), + ('set public','set public'), + ('unset commute','unset commute'), ) destinations = ( ('c2','c2'), diff --git a/rowers/templates/list_workouts.html b/rowers/templates/list_workouts.html index 4d41fffa..cd31fc05 100644 --- a/rowers/templates/list_workouts.html +++ b/rowers/templates/list_workouts.html @@ -110,6 +110,9 @@ {% endif %} {{ workout.date|date:"Y-m-d" }} {{ workout.starttime|date:"H:i" }} + {% if workout.privacy == 'hidden' %} + + {% endif %} {% if workout.duplicate %} {% endif %} diff --git a/rowers/templates/rower_simplepreferences.html b/rowers/templates/rower_simplepreferences.html index 9accb6d9..328b0d70 100644 --- a/rowers/templates/rower_simplepreferences.html +++ b/rowers/templates/rower_simplepreferences.html @@ -62,36 +62,36 @@ 2{{ user.rower.powerzones.1 }} {{ user.rower.pw_ut2 }} {{ user.rower.pw_ut2|otwslack:user }} - {{ user.rower.pw_ut2|target_spm_erg:user }} - {{ user.rower.pw_ut2|target_spm_otw:user }} + <{{ user.rower.pw_ut1|target_spm_erg:user }} + <{{ user.rower.pw_ut1|target_spm_otw:user }} 3{{ user.rower.powerzones.2 }} {{ user.rower.pw_ut1 }} {{ user.rower.pw_ut1|otwslack:user }} - {{ user.rower.pw_ut1|target_spm_erg:user }} - {{ user.rower.pw_ut1|target_spm_otw:user }} + {{ user.rower.pw_ut1|target_spm_erg:user }}-{{ user.rower.pw_at|target_spm_erg:user }} + {{ user.rower.pw_ut1|target_spm_otw:user }}-{{ user.rower.pw_at|target_spm_otw:user }} 4{{ user.rower.powerzones.3 }} {{ user.rower.pw_at }} {{ user.rower.pw_at|otwslack:user }} - {{ user.rower.pw_at|target_spm_erg:user }} - {{ user.rower.pw_at|target_spm_otw:user }} + {{ user.rower.pw_at|target_spm_erg:user }}-{{ user.rower.pw_tr|target_spm_erg:user }} + {{ user.rower.pw_at|target_spm_otw:user }}-{{ user.rower.pw_tr|target_spm_otw:user }} 5{{ user.rower.powerzones.4 }} {{ user.rower.pw_tr }} {{ user.rower.pw_tr|otwslack:user }} - {{ user.rower.pw_tr|target_spm_erg:user }} - {{ user.rower.pw_tr|target_spm_otw:user }} + {{ user.rower.pw_tr|target_spm_erg:user }}-{{ user.rower.pw_an|target_spm_erg:user }} + {{ user.rower.pw_tr|target_spm_otw:user }}-{{ user.rower.pw_an|target_spm_otw:user }} 6{{ user.rower.powerzones.5 }} {{ user.rower.pw_an }} {{ user.rower.pw_an|otwslack:user }} - {{ user.rower.pw_an|target_spm_erg:user }} - {{ user.rower.pw_an|target_spm_otw:user }} + >{{ user.rower.pw_an|target_spm_erg:user }} + >{{ user.rower.pw_an|target_spm_otw:user }} diff --git a/rowers/tests/testdata/testdata.tcx.gz b/rowers/tests/testdata/testdata.tcx.gz index 4a3b747de7238e885296ce620e3e12645a716ba4..4528d65552e2f4edfa93540da57c302c7cbfe394 100644 GIT binary patch delta 15 WcmbO#KUJPhzMF%?_VPxyetrNW Date: Thu, 9 Jan 2025 18:48:09 +0100 Subject: [PATCH 4/7] more changes --- rowers/tests/testdata/testdata.tcx.gz | Bin 3989 -> 3989 bytes rowers/views/apiviews.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/rowers/tests/testdata/testdata.tcx.gz b/rowers/tests/testdata/testdata.tcx.gz index 4528d65552e2f4edfa93540da57c302c7cbfe394..8fc402d9865bbca0a4ce03b264f1825cb19fa88c 100644 GIT binary patch delta 15 WcmbO#KUJPhzMF%C^ZrJ*etrNV=mcf} delta 15 WcmbO#KUJPhzMF%?_VPxyetrNW Date: Wed, 15 Jan 2025 17:38:43 +0100 Subject: [PATCH 5/7] fixing idoklad issue --- rowers/idoklad.py | 2 +- rowers/tests/testdata/testdata.tcx.gz | Bin 3989 -> 3989 bytes rowers/views/.#apiviews.py | 1 + rowers/views/userviews.py | 6 ------ 4 files changed, 2 insertions(+), 7 deletions(-) create mode 120000 rowers/views/.#apiviews.py diff --git a/rowers/idoklad.py b/rowers/idoklad.py index cb6f2593..2119a662 100644 --- a/rowers/idoklad.py +++ b/rowers/idoklad.py @@ -147,7 +147,7 @@ def create_contact(rower): if res.status_code not in [200, 201]: dologging('idoklad.log','Contact Created - reason '+str(res.reason)+'\n') - _ = myqueue.enqueue( + _ = myqueue( queuehigh, handle_send_email_noinvoice, rower.user.email, rower.user.first_name, diff --git a/rowers/tests/testdata/testdata.tcx.gz b/rowers/tests/testdata/testdata.tcx.gz index 8fc402d9865bbca0a4ce03b264f1825cb19fa88c..ff1f672da52f58a01114b6174486c7faaadee5f6 100644 GIT binary patch delta 16 XcmbO#KUJPxzMF&N@q_k_?0x(IE~N#@ delta 16 XcmbO#KUJPxzMF%C^M3tC_C9_9D1ij# diff --git a/rowers/views/.#apiviews.py b/rowers/views/.#apiviews.py new file mode 120000 index 00000000..5317f650 --- /dev/null +++ b/rowers/views/.#apiviews.py @@ -0,0 +1 @@ +sander@rowsandall-2.17364:1733469196 \ No newline at end of file diff --git a/rowers/views/userviews.py b/rowers/views/userviews.py index 7df07582..90cb4480 100644 --- a/rowers/views/userviews.py +++ b/rowers/views/userviews.py @@ -429,12 +429,6 @@ def rower_exportsettings_view(request, userid=0): } if form.is_valid(): cd = form.cleaned_data - if r.rowerplan == 'basic': # pragma: no cover - messages.error( - request, 'This setting will only be effective if you are a user \ - on one of the paid plans \ - or part of a coaching group.') - for attr, value in cd.items(): doset = True try: From 139ce17b6123021900e32af4d8453898d72183e7 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Wed, 15 Jan 2025 17:41:12 +0100 Subject: [PATCH 6/7] fix --- rowers/views/.#apiviews.py | 1 - rowers/views/apiviews.py | 1 - 2 files changed, 2 deletions(-) delete mode 120000 rowers/views/.#apiviews.py diff --git a/rowers/views/.#apiviews.py b/rowers/views/.#apiviews.py deleted file mode 120000 index 5317f650..00000000 --- a/rowers/views/.#apiviews.py +++ /dev/null @@ -1 +0,0 @@ -sander@rowsandall-2.17364:1733469196 \ No newline at end of file diff --git a/rowers/views/apiviews.py b/rowers/views/apiviews.py index 00d2980f..2bef2928 100644 --- a/rowers/views/apiviews.py +++ b/rowers/views/apiviews.py @@ -610,7 +610,6 @@ def strokedata_fit(request): 'secret': UPLOAD_SERVICE_SECRET, 'user': request.user.id, 'file': fit_filename, - 'workouttype': 'water', 'boattype': '1x', 'title': title, 'rpe': 0, From e18834339aae111ebe8f97dc9709af4d0a970a43 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Wed, 15 Jan 2025 17:57:06 +0100 Subject: [PATCH 7/7] fix --- rowers/tests/testdata/testdata.tcx.gz | Bin 3989 -> 3989 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/rowers/tests/testdata/testdata.tcx.gz b/rowers/tests/testdata/testdata.tcx.gz index ff1f672da52f58a01114b6174486c7faaadee5f6..b81e6990222b7e150aef07aefc80b0552d7f6a8d 100644 GIT binary patch delta 15 WcmbO#KUJPhzMF$X{n+Q{rmtZ2?ap_