Private
Public Access
1
0

Merge branch 'feature/spi' into develop

This commit is contained in:
2025-01-15 17:39:03 +01:00
12 changed files with 139 additions and 12 deletions
+31 -1
View File
@@ -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,35 @@ 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 not duplicate and workouttype in otetypes:
cntr = Workout.objects.filter(user=r, workouttype__in=otetypes,
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):
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 not duplicate and workouttype in otwtypes:
cntr = Workout.objects.filter(user=r, workouttype__in=otwtypes,
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
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)
+4
View File
@@ -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'),
+1 -1
View File
@@ -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,
+5
View File
@@ -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 = {
+50 -1
View File
@@ -104,11 +104,15 @@
{% endif %}
{% for workout in workouts %}
{% if not workout.is_commute %}
<li class="grid_4 divlines">
{% if request.GET.selectworkouts %}
<input type="checkbox" id="workoutid" value={{ workout.id|encode }} name="workoutid" />
{% endif %}
{{ workout.date|date:"Y-m-d" }} {{ workout.starttime|date:"H:i" }}
{% if workout.privacy == 'hidden' %}
<span style="font-size: smaller"><i class="fa-solid fa-eye-slash"></i></span>
{% endif %}
{% if workout.duplicate %}
<span style="font-size: smaller"><i class="fal fa-angle-double-up"></i></span>
{% endif %}
@@ -198,7 +202,52 @@
</div>
</div>
</li>
{% elif user.rower.show_commutes %}
<li class="grid_4 divlines">
<div class="workoutcontainer">
<div class="workoutelement">
<span style="font-size: smaller"><i class="fa-solid fa-train"></i></span>
</div>
<div class="workoutelement">
<span style="color:#555">Distance</span>
{{ workout.distance|distanceprint }}
</div>
<div class="workoutelement">
<span style="color:#555">Time</span>
{{ workout.duration |durationprint:"%H:%M:%S.%f" }}
</div>
<div class="workoutelement">
{% if workout|may_edit:request %}
<a class="small"
href={% url rower.defaultlandingpage id=workout.id|encode %}
title="{{ rower.defaultlandingpage|verbose }}">
<i class="{{ rower.defaultlandingpage|landingicon }}"></i></a>
{% else %}
&nbsp;
{% endif %}
</div>
<div class="workoutelement">
{% if workout|may_edit:request %}
{% if rower.defaultlandingpage2 != 'workout_delete' %}
<a class="small"
href={% url rower.defaultlandingpage2 id=workout.id|encode %}
title="{{ rower.defaultlandingpage2|verbose }}">
<i class="{{ rower.defaultlandingpage2|landingicon }}"></i></a>
{% else %}
<a class="small"
href={% url rower.defaultlandingpage2 id=workout.id|encode %}
title="{{ rower.defaultlandingpage2|verbose }}">
<i class="{{ rower.defaultlandingpage2|landingicon }}"></i></a>
{% endif %}
{% else %}
&nbsp;
{% endif %}
</div>
</div>
</li>
{% endif %}
{% endfor %}
{% else %}
+19 -2
View File
@@ -40,41 +40,58 @@
<table class="listtable shortpadded" width=100%>
<thead>
<tr>
<th>ID&nbsp;</th><th>Zone Name</th><th>Lower Boundary (Watt)&nbsp;</th><th>Lower Boundary (Watt)</th>
<th>ID&nbsp;</th>
<th>Zone Name</th>
<th>Lower Boundary (Watt)&nbsp;</th>
<th>Lower Boundary (Watt)</th>
<th>Target SPM</th>
<th>Target SPM</th>
</tr>
<tr>
<th></th><th></th><th>Indoor</th><th>OTW</th>
<th></th><th></th><th>Indoor</th><th>OTW</th><th>Indoor</th><th>OTW</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td><td>{{ user.rower.powerzones.0 }}</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>2</td><td>{{ user.rower.powerzones.1 }}</td>
<td>{{ user.rower.pw_ut2 }}</td>
<td>{{ user.rower.pw_ut2|otwslack:user }}</td>
<td>&lt;{{ user.rower.pw_ut1|target_spm_erg:user }}</td>
<td>&lt;{{ user.rower.pw_ut1|target_spm_otw:user }}</td>
</tr>
<tr>
<td>3</td><td>{{ user.rower.powerzones.2 }}</td>
<td>{{ user.rower.pw_ut1 }}</td>
<td>{{ user.rower.pw_ut1|otwslack:user }}</td>
<td>{{ user.rower.pw_ut1|target_spm_erg:user }}-{{ user.rower.pw_at|target_spm_erg:user }}</td>
<td>{{ user.rower.pw_ut1|target_spm_otw:user }}-{{ user.rower.pw_at|target_spm_otw:user }}</td>
</tr>
<tr>
<td>4</td><td>{{ user.rower.powerzones.3 }}</td>
<td>{{ user.rower.pw_at }}</td>
<td>{{ user.rower.pw_at|otwslack:user }}</td>
<td>{{ user.rower.pw_at|target_spm_erg:user }}-{{ user.rower.pw_tr|target_spm_erg:user }}</td>
<td>{{ user.rower.pw_at|target_spm_otw:user }}-{{ user.rower.pw_tr|target_spm_otw:user }}</td>
</tr>
<tr>
<td>5</td><td>{{ user.rower.powerzones.4 }}</td>
<td>{{ user.rower.pw_tr }}</td>
<td>{{ user.rower.pw_tr|otwslack:user }}</td>
<td>{{ user.rower.pw_tr|target_spm_erg:user }}-{{ user.rower.pw_an|target_spm_erg:user }}</td>
<td>{{ user.rower.pw_tr|target_spm_otw:user }}-{{ user.rower.pw_an|target_spm_otw:user }}</td>
</tr>
<tr>
<td>6</td><td>{{ user.rower.powerzones.5 }}</td>
<td>{{ user.rower.pw_an }}</td>
<td>{{ user.rower.pw_an|otwslack:user }}</td>
<td>&gt;{{ user.rower.pw_an|target_spm_erg:user }}</td>
<td>&gt;{{ user.rower.pw_an|target_spm_otw:user }}</td>
</tr>
</tbody>
</table>
+12
View File
@@ -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)
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
sander@rowsandall-2.17364:1733469196
-1
View File
@@ -605,7 +605,6 @@ def strokedata_fit(request):
name=title,
date=startdate,
)
# workouttype='water',)
uploadoptions = {
'secret': UPLOAD_SERVICE_SECRET,
-6
View File
@@ -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 <a href="/rowers/paidplans">paid plans</a> \
or part of a coaching group.')
for attr, value in cd.items():
doset = True
try:
+16
View File
@@ -2067,6 +2067,22 @@ def workouts_bulk_actions(request):
for w in workouts:
messages.info(request,'Removed workout '+str(encoder.encode_hex(w.id)))
w.delete()
elif action == 'set private':
for w in workouts:
w.privacy = 'private'
w.save()
elif action == 'set commute':
for w in workouts:
w.is_commute = True
w.save()
elif action == 'unset commute':
for w in workouts:
w.is_commute = False
w.save()
elif action == 'set public':
for w in workouts:
w.privacy = 'public'
w.save()
elif action == 'export':
exportchoice = ExportChoices(request.POST)
if exportchoice.is_valid():