Merge branch 'release/v8.68'
This commit is contained in:
@@ -2000,9 +2000,20 @@ class IndoorVirtualRaceForm(ModelForm):
|
|||||||
'evaluation_closure':AdminSplitDateTime(),
|
'evaluation_closure':AdminSplitDateTime(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
'sessionunit': 'Meters or minutes',
|
||||||
|
'sessionvalue': 'How far or how long'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def __init__(self,*args,**kwargs):
|
def __init__(self,*args,**kwargs):
|
||||||
|
timezone = kwargs.pop('timezone',None)
|
||||||
super(IndoorVirtualRaceForm, self).__init__(*args, **kwargs)
|
super(IndoorVirtualRaceForm, self).__init__(*args, **kwargs)
|
||||||
self.fields['sessionunit'].choices = [('min','minutes'),('m','meters')]
|
self.fields['sessionunit'].choices = [('min','minutes'),('m','meters')]
|
||||||
|
self.fields['sessionvalue'].initial = 2000
|
||||||
|
self.fields['sessionunit'].initial = 'm'
|
||||||
|
if timezone:
|
||||||
|
self.fields['timezone'].initial = timezone
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cd = self.cleaned_data
|
cd = self.cleaned_data
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ def get_indoorraces(workout):
|
|||||||
|
|
||||||
registrations = IndoorVirtualRaceResult.objects.filter(
|
registrations = IndoorVirtualRaceResult.objects.filter(
|
||||||
race__in = races,
|
race__in = races,
|
||||||
|
boatclass = workout.workouttype,
|
||||||
userid=workout.user.id)
|
userid=workout.user.id)
|
||||||
|
|
||||||
races = [r.race for r in registrations]
|
races = [r.race for r in registrations]
|
||||||
@@ -1008,6 +1009,9 @@ def add_workout_indoorrace(ws,race,r,recordid=0):
|
|||||||
record.distance = ws[0].distance
|
record.distance = ws[0].distance
|
||||||
record.duration = ws[0].duration
|
record.duration = ws[0].duration
|
||||||
|
|
||||||
|
if ws[0].workouttype != record.boatclass:
|
||||||
|
errors.append('Your workout boat class is different than on your race registration')
|
||||||
|
return 0,comments,errors,0
|
||||||
|
|
||||||
if ws[0].workouttype not in mytypes.otetypes:
|
if ws[0].workouttype not in mytypes.otetypes:
|
||||||
errors.append('You must submit a indoor rowing workout')
|
errors.append('You must submit a indoor rowing workout')
|
||||||
@@ -1109,6 +1113,9 @@ def add_workout_race(ws,race,r,splitsecond=0,recordid=0):
|
|||||||
errors.append('You have to submit a rowing on water workout')
|
errors.append('You have to submit a rowing on water workout')
|
||||||
return 0,comments,errors,0
|
return 0,comments,errors,0
|
||||||
|
|
||||||
|
if ws[0].workouttype != record.boatclass:
|
||||||
|
errors.append('Your workout boat class is different than on your race registration')
|
||||||
|
return 0,comments,errors,0
|
||||||
|
|
||||||
if ws[0].boattype != record.boattype:
|
if ws[0].boattype != record.boattype:
|
||||||
errors.append('Your workout boat type did not match the boat type you registered')
|
errors.append('Your workout boat type did not match the boat type you registered')
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<h1>Planned Sessions for {{ rower.user.first_name }} {{ rower.user.last_name }}</h1>
|
<h1>Planned Sessions for {{ rower.user.first_name }} {{ rower.user.last_name }}</h1>
|
||||||
|
|
||||||
<ul class="main-content">
|
<ul class="main-content">
|
||||||
<li>
|
<li class="grid_2">
|
||||||
<p>
|
<p>
|
||||||
<form enctype="multipart/form-data" method="get">
|
<form enctype="multipart/form-data" method="get">
|
||||||
<table>
|
<table>
|
||||||
@@ -172,6 +172,82 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="grid_2">
|
||||||
|
<p>
|
||||||
|
<table width="90%" class="listtable shortpadded">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th> </th>
|
||||||
|
<th>Distance</th>
|
||||||
|
<th>Time (minutes)</th>
|
||||||
|
<th>rScore</th>
|
||||||
|
<th>TRIMP</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
Total
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ totals|lookup:'distance' }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ totals|lookup:'time' }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ totals|lookup:'rscore' }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ totals|lookup:'trimp' }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
Planned
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ totals|lookup:'planneddistance' }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ totals|lookup:'plannedtime' }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ totals|lookup:'plannedrscore' }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ totals|lookup:'plannedtrimp' }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
Actual
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ totals|lookup:'actualdistance' }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ totals|lookup:'actualtime' }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ totals|lookup:'actualrscore' }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ totals|lookup:'actualtrimp' }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Total is the total minutes, meters, rScore, TRIMP of all workouts in this
|
||||||
|
time period.
|
||||||
|
Planned time is the total time for sessions planned for time.
|
||||||
|
Actual time is the total time of workouts linked to sessions
|
||||||
|
planned for time.
|
||||||
|
Similarly for distance, rScore and TRIMP.
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -335,6 +335,8 @@ data-text="@rowsandall #rowingdata Participate in Indoor Rowing virtual race '{{
|
|||||||
{% if race.sessiontype == 'race' %}
|
{% if race.sessiontype == 'race' %}
|
||||||
<th>Class</th>
|
<th>Class</th>
|
||||||
<th>Boat</th>
|
<th>Boat</th>
|
||||||
|
{% else %}
|
||||||
|
<th>Class</th>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<th>Age</th>
|
<th>Age</th>
|
||||||
<th>Gender</th>
|
<th>Gender</th>
|
||||||
@@ -348,6 +350,8 @@ data-text="@rowsandall #rowingdata Participate in Indoor Rowing virtual race '{{
|
|||||||
{% if race.sessiontype == 'race' %}
|
{% if race.sessiontype == 'race' %}
|
||||||
<td>{{ record.boatclass }}</td>
|
<td>{{ record.boatclass }}</td>
|
||||||
<td>{{ record.boattype }}</td>
|
<td>{{ record.boattype }}</td>
|
||||||
|
{% else %}
|
||||||
|
<td>{{ record.boatclass }}</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<td>{{ record.age }}</td>
|
<td>{{ record.age }}</td>
|
||||||
<td>{{ record.sex }}</td>
|
<td>{{ record.sex }}</td>
|
||||||
|
|||||||
@@ -38,6 +38,22 @@
|
|||||||
<h1>{{ workout.name }}</h1>
|
<h1>{{ workout.name }}</h1>
|
||||||
<ul class="main-content">
|
<ul class="main-content">
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
|
{% if records %}
|
||||||
|
{% for record in records %}
|
||||||
|
<p>
|
||||||
|
This workout was a race. See race result here:
|
||||||
|
<a href="/rowers/virtualevent/{{ record.race.id }}">{{ record.race.name }}</a>
|
||||||
|
</p>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% if recordsindoor %}
|
||||||
|
{% for record in recordsindoor %}
|
||||||
|
<p>
|
||||||
|
This workout was a race. See race result here:
|
||||||
|
<a href="/rowers/virtualevent/{{ record.race.id }}">{{ record.race.name }}</a>
|
||||||
|
</p>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
<p>
|
<p>
|
||||||
<div class="fb-share-button"
|
<div class="fb-share-button"
|
||||||
data-href="https://rowsandall.com/rowers/workout/{{ workout.id }}"
|
data-href="https://rowsandall.com/rowers/workout/{{ workout.id }}"
|
||||||
|
|||||||
+73
-1
@@ -7343,6 +7343,9 @@ def workout_view(request,id=0):
|
|||||||
|
|
||||||
u = row.user.user
|
u = row.user.user
|
||||||
|
|
||||||
|
recordsindoor = IndoorVirtualRaceResult.objects.filter(workoutid= row.id)
|
||||||
|
records = VirtualRaceResult.objects.filter(workoutid= row.id)
|
||||||
|
|
||||||
return render(request, 'workout_view.html',
|
return render(request, 'workout_view.html',
|
||||||
{'workout':row,
|
{'workout':row,
|
||||||
'rower':rower,
|
'rower':rower,
|
||||||
@@ -7350,6 +7353,8 @@ def workout_view(request,id=0):
|
|||||||
'active':'nav-workouts',
|
'active':'nav-workouts',
|
||||||
'graphs':g,
|
'graphs':g,
|
||||||
'last_name':u.last_name,
|
'last_name':u.last_name,
|
||||||
|
'records':records,
|
||||||
|
'recordsindoor':recordsindoor,
|
||||||
'first_name':u.first_name,
|
'first_name':u.first_name,
|
||||||
'interactiveplot':script,
|
'interactiveplot':script,
|
||||||
'aantalcomments':aantalcomments,
|
'aantalcomments':aantalcomments,
|
||||||
@@ -15292,6 +15297,46 @@ def plannedsessions_view(request,
|
|||||||
completiondate = {}
|
completiondate = {}
|
||||||
sessioncolor = {}
|
sessioncolor = {}
|
||||||
|
|
||||||
|
totals = {
|
||||||
|
'trimp':0,
|
||||||
|
'rscore':0,
|
||||||
|
'distance':0,
|
||||||
|
'time':0,
|
||||||
|
'plannedtime':0,
|
||||||
|
'planneddistance':0,
|
||||||
|
'plannedtrimp':0,
|
||||||
|
'plannedrscore':0,
|
||||||
|
'actualtime':0,
|
||||||
|
'actualdistance':0,
|
||||||
|
'actualtrimp':0,
|
||||||
|
'actualrscore':0,
|
||||||
|
}
|
||||||
|
|
||||||
|
ws = Workout.objects.filter(
|
||||||
|
user=r,
|
||||||
|
date__gte=startdate,date__lte=enddate)
|
||||||
|
|
||||||
|
for w in ws:
|
||||||
|
thetrimp,hrtss = dataprep.workout_trimp(w)
|
||||||
|
totals['trimp'] += thetrimp
|
||||||
|
tss = dataprep.workout_rscore(w)[0]
|
||||||
|
if not np.isnan(tss) and tss != 0:
|
||||||
|
totals['rscore'] += tss
|
||||||
|
elif tss == 0:
|
||||||
|
totals['rscore'] += hrtss
|
||||||
|
tss = hrtss
|
||||||
|
totals['distance'] += w.distance
|
||||||
|
totals['time'] += timefield_to_seconds_duration(w.duration)
|
||||||
|
if w.plannedsession:
|
||||||
|
if w.plannedsession.sessionmode == 'distance':
|
||||||
|
totals['actualdistance'] += w.distance
|
||||||
|
elif w.plannedsession.sessionmode == 'time':
|
||||||
|
totals['actualtime'] += timefield_to_seconds_duration(w.duration)
|
||||||
|
elif w.plannedsession.sessionmode == 'rScore':
|
||||||
|
totals['actualrscore'] += tss
|
||||||
|
elif w.plannedsession.sessionmode == 'TRIMP':
|
||||||
|
totals['actualtrimp'] += thetrimp
|
||||||
|
|
||||||
if not sps and request.user.rower.rowerplan == 'basic':
|
if not sps and request.user.rower.rowerplan == 'basic':
|
||||||
messages.error(request,
|
messages.error(request,
|
||||||
"You must purchase Coach or Self-coach plans or be part of a team to get planned sessions")
|
"You must purchase Coach or Self-coach plans or be part of a team to get planned sessions")
|
||||||
@@ -15303,6 +15348,18 @@ def plannedsessions_view(request,
|
|||||||
sessioncolor[ps.id] = cratiocolors[status]
|
sessioncolor[ps.id] = cratiocolors[status]
|
||||||
ws = Workout.objects.filter(user=r,plannedsession=ps)
|
ws = Workout.objects.filter(user=r,plannedsession=ps)
|
||||||
completiondate[ps.id] = cdate
|
completiondate[ps.id] = cdate
|
||||||
|
if ps.sessionmode == 'distance':
|
||||||
|
totals['planneddistance'] += ps.sessionvalue
|
||||||
|
elif ps.sessionmode == 'time':
|
||||||
|
totals['plannedtime'] += ps.sessionvalue
|
||||||
|
elif ps.sessionmode == 'rScore':
|
||||||
|
totals['plannedrscore'] += ps.sessionvalue
|
||||||
|
elif ps.sessionmode == 'TRIMP':
|
||||||
|
totals['plannedtrimp'] += ps.sessionvalue
|
||||||
|
|
||||||
|
totals['time'] = int(totals['time']/60.)
|
||||||
|
totals['actualtime'] = int(totals['actualtime']/60.)
|
||||||
|
totals['plannedtime'] = int(totals['plannedtime']/60.)
|
||||||
|
|
||||||
unmatchedworkouts = Workout.objects.filter(
|
unmatchedworkouts = Workout.objects.filter(
|
||||||
user=r,
|
user=r,
|
||||||
@@ -15333,6 +15390,7 @@ def plannedsessions_view(request,
|
|||||||
'plan':trainingplan,
|
'plan':trainingplan,
|
||||||
'active': 'nav-plan',
|
'active': 'nav-plan',
|
||||||
'dateform':dateform,
|
'dateform':dateform,
|
||||||
|
'totals':totals,
|
||||||
'rower':r,
|
'rower':r,
|
||||||
'timeperiod':timeperiod,
|
'timeperiod':timeperiod,
|
||||||
'completeness':completeness,
|
'completeness':completeness,
|
||||||
@@ -17048,7 +17106,7 @@ def indoorvirtualevent_create_view(request):
|
|||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
else:
|
else:
|
||||||
|
|
||||||
racecreateform = IndoorVirtualRaceForm()
|
racecreateform = IndoorVirtualRaceForm(timezone=r.defaulttimezone)
|
||||||
|
|
||||||
|
|
||||||
breadcrumbs = [
|
breadcrumbs = [
|
||||||
@@ -17464,6 +17522,20 @@ def virtualevent_submit_result_view(request,id=0,workoutid=0):
|
|||||||
startdatetime__lte=enddatetime,
|
startdatetime__lte=enddatetime,
|
||||||
).order_by("date","startdatetime","id")
|
).order_by("date","startdatetime","id")
|
||||||
|
|
||||||
|
if not ws:
|
||||||
|
messages.info(
|
||||||
|
request,
|
||||||
|
'You have no workouts executed during the race window. Please upload a result or enter it manually.'
|
||||||
|
)
|
||||||
|
|
||||||
|
url = reverse(virtualevent_view,
|
||||||
|
kwargs = {
|
||||||
|
'id':id
|
||||||
|
})
|
||||||
|
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
|
||||||
initialworkouts = [w.id for w in Workout.objects.filter(
|
initialworkouts = [w.id for w in Workout.objects.filter(
|
||||||
user=r,plannedsession=race
|
user=r,plannedsession=race
|
||||||
)]
|
)]
|
||||||
|
|||||||
Reference in New Issue
Block a user