Private
Public Access
1
0

expanded boat types & classes

This commit is contained in:
Sander Roosendaal
2018-06-07 00:50:24 +02:00
parent 657ee8b467
commit 38a201e7e7
9 changed files with 128 additions and 74 deletions

View File

@@ -36,6 +36,8 @@ from requests import Request, Session
from utils import myqueue
from rowers.types import otwtypes
from rowsandall_app.settings import C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET
from rowers.tasks import handle_c2_import_stroke_data
@@ -340,7 +342,7 @@ def createc2workoutdata_as_splits(w):
newnotes = 'from '+w.workoutsource+' via rowsandall.com'
wtype = w.workouttype
if wtype in ('other','coastal'):
if wtype in otwtypes:
wtype = 'water'
data = {
@@ -404,7 +406,7 @@ def createc2workoutdata(w):
durationstr = datetime.strptime(str(w.duration),"%H:%M:%S")
workouttype = w.workouttype
if workouttype in ('coastal','other'):
if workouttype in otwtypes:
workouttype = 'water'
data = {

View File

@@ -68,7 +68,7 @@ queuelow = django_rq.get_queue('low')
queuehigh = django_rq.get_queue('default')
from rowsandall_app.settings import SITE_URL
from rowers.types import otwtypes
user = settings.DATABASES['default']['USER']
password = settings.DATABASES['default']['PASSWORD']
@@ -2355,7 +2355,7 @@ def workout_rscore(w):
normp = (pwr4mean)**(0.25)
if not np.isnan(normp):
ftp = float(r.ftp)
if w.workouttype in ('water','coastal'):
if w.workouttype in otwtypes:
ftp = ftp*(100.-r.otwslack)/100.
intensityfactor = pwrmean/float(ftp)

View File

@@ -521,7 +521,7 @@ class TrendFlexModalForm(forms.Form):
initial='all')
waterboattype = forms.MultipleChoiceField(choices=boattypes,
label='Water Boat Type',
initial = ['1x','2x','2-','4x','4-','8+'])
initial = types.waterboattype)
# This form sets options for the summary stats page
@@ -531,15 +531,21 @@ class StatsOptionsForm(forms.Form):
waterboattype = forms.MultipleChoiceField(choices=boattypes,
label='Water Boat Type',
widget=forms.CheckboxSelectMultiple(),
initial = ['1x','2x','2-','4x','4-','8+'])
rower = forms.BooleanField(initial=True,required=False)
dynamic = forms.BooleanField(initial=True,required=False)
slides = forms.BooleanField(initial=True,required=False)
skierg = forms.BooleanField(initial=False,required=False)
paddle = forms.BooleanField(initial=False,required=False)
snow = forms.BooleanField(initial=False,required=False)
coastal = forms.BooleanField(initial=False,required=False)
other = forms.BooleanField(initial=False,required=False)
initial = types.waterboattype)
def __init__(self, *args, **kwargs):
super(StatsOptionsForm, self).__init__(*args,**kwargs)
for type in types.checktypes:
self.fields[type] = forms.BooleanField(initial=True,required=False)
# rower = forms.BooleanField(initial=True,required=False)
# dynamic = forms.BooleanField(initial=True,required=False)
# slides = forms.BooleanField(initial=True,required=False)
# skierg = forms.BooleanField(initial=False,required=False)
# paddle = forms.BooleanField(initial=False,required=False)
# snow = forms.BooleanField(initial=False,required=False)
# coastal = forms.BooleanField(initial=False,required=False)
# other = forms.BooleanField(initial=False,required=False)
class CourseSelectForm(forms.Form):
course = forms.ModelChoiceField(queryset=GeoCourse.objects.all())
@@ -706,6 +712,8 @@ class WorkoutSessionSelectForm(forms.Form):
class RaceResultFilterForm(forms.Form):
boatclasses = (type for type in types.workouttypes if type[0] in types.otwtypes)
boatclassinitial = [t for t in types.otwtypes]
sexchoices = (
('female','Female'),
('male','Male'),
@@ -724,10 +732,16 @@ class RaceResultFilterForm(forms.Form):
label='Gender',
widget=forms.CheckboxSelectMultiple())
boatclass = forms.MultipleChoiceField(
choices=boatclasses,
initial=boatclassinitial,
label='Boat Class',
widget=forms.CheckboxSelectMultiple())
boattype = forms.MultipleChoiceField(
choices=boattypes,
label='Boat Type',
initial=['1x','2x','2-','4x','4-','8+'],
initial=types.waterboattype,
widget=forms.CheckboxSelectMultiple())
age_min = forms.IntegerField(label='Min Age',initial=16)

View File

@@ -5,6 +5,7 @@ from utils import myqueue
import django_rq
queue = django_rq.get_queue('default')
from rowers.tasks import handle_updatefitnessmetric
from rowers.types import otwtypes
def getrower(user):
try:
@@ -45,7 +46,7 @@ def do_update(user,mode='rower',days=42):
else:
workouts = Workout.objects.filter(
user=r,
workouttype__in=['water','coastal'],
workouttype__in=otwtypes,
startdatetime__gte=startdate)
theids = [int(w.id) for w in workouts]

View File

@@ -1602,6 +1602,7 @@ def auto_delete_strokedata_on_delete(sender, instance, **kwargs):
# Virtual Race results (for keeping results when workouts are deleted)
class VirtualRaceResult(models.Model):
boatclasses = (type for type in types.workouttypes if type[0] in types.otwtypes)
userid = models.IntegerField(default=0)
teamname = models.CharField(max_length=80,verbose_name = 'Team Name',
blank=True,null=True)
@@ -1613,6 +1614,10 @@ class VirtualRaceResult(models.Model):
race = models.ForeignKey(VirtualRace)
duration = models.TimeField(default=datetime.time(1,0))
distance = models.IntegerField(default=0)
boatclass = models.CharField(choices=boatclasses,
max_length=40,
default='water',
verbose_name = 'Boat Class')
boattype = models.CharField(choices=boattypes,max_length=40,
default='1x',
verbose_name = 'Boat Type'
@@ -1649,7 +1654,7 @@ class CourseTestResult(models.Model):
class VirtualRaceResultForm(ModelForm):
class Meta:
model = VirtualRaceResult
fields = ['teamname','weightcategory','boattype','age']
fields = ['teamname','weightcategory','boatclass','boattype','age']
def __init__(self, *args, **kwargs):

View File

@@ -106,6 +106,7 @@
<th>&nbsp;</th>
<th>&nbsp;</th>
<th>&nbsp;</th>
<th>Class</th>
<th>Boat</th>
<th>Time</th>
<th>Distance</th>
@@ -123,6 +124,7 @@
<td>{{ result.age }}</td>
<td>{{ result.sex }}</td>
<td>{{ result.weightcategory }}</td>
<td>{{ result.boatclass }}</td>
<td>{{ result.boattype }}</td>
<td>{{ result.duration |durationprint:"%H:%M:%S.%f" }}</td>
<td>{{ result.distance }} m</td>
@@ -139,6 +141,7 @@
<td>{{ result.age }}</td>
<td>{{ result.sex }}</td>
<td>{{ result.weightcategory }}</td>
<td>{{ result.boatclass }}</td>
<td>{{ result.boattype }}</td>
<td>DNS</td>
</tr>
@@ -158,6 +161,7 @@
<tr>
<th>Name</th>
<th>Team Name</th>
<th>Class</th>
<th>Boat</th>
<th>Age</th>
<th>Gender</th>
@@ -168,6 +172,7 @@
<tr>
<td>{{ record.username }}
<td>{{ record.teamname }}</td>
<td>{{ record.boatclass }}</td>
<td>{{ record.boattype }}</td>
<td>{{ record.age }}</td>
<td>{{ record.sex }}</td>

View File

@@ -1,5 +1,5 @@
workouttypes = (
('water','On-water'),
('water','On-water - Olympic'),
('rower','Indoor Rower'),
('skierg','Ski Erg'),
('dynamic','Dynamic Indoor Rower'),
@@ -7,9 +7,20 @@ workouttypes = (
('paddle','Paddle Adapter'),
('snow','On-snow'),
('coastal','Coastal'),
('c-boat','Dutch C boat'),
('churchboat','Finnish Church boat'),
('other','Other'),
)
otwtypes = (
'water',
'coastal',
'c-boat',
'churchboat'
)
checktypes = [i[0] for i in workouttypes]
workoutsources = (
('strava','strava'),
('concept2','concept2'),
@@ -36,12 +47,20 @@ workoutsources = (
boattypes = (
('1x', '1x (single)'),
('2x', '2x (double)'),
('2x+', '2x+ (coxed double)'),
('2-', '2- (pair)'),
('2+', '2+ (coxed pair)'),
('3x+','3x+ (coxed triple)'),
('4x', '4x (quad)'),
('4x+', '4x+ (coxed quad)'),
('4-', '4- (four)'),
('4+', '4+ (coxed four)'),
('8+', '8+ (eight)'),
('8x+', '8x+ (octuple scull)'),
)
waterboattype = [i[0] for i in boattypes]
privacychoices = (
('private','Private'),
('visible','Visible'),

View File

@@ -27,7 +27,7 @@ queue = django_rq.get_queue('default')
queuelow = django_rq.get_queue('low')
queuehigh = django_rq.get_queue('low')
from types import workouttypes,boattypes
from types import workouttypes,boattypes,otwtypes
try:
from cStringIO import StringIO
@@ -297,7 +297,7 @@ def make_plot(r,w,f1,f2,plottype,title,imagename='',plotnr=0):
r.pw_tr,r.pw_an])/r.ftp
ftp = float(r.ftp)
if w.workouttype in ('water','coastal'):
if w.workouttype in otwtypes:
ftp = ftp*(100.-r.otwslack)/100.
hrpwrdata = {
@@ -322,7 +322,7 @@ def make_plot(r,w,f1,f2,plottype,title,imagename='',plotnr=0):
if plotnr == 0:
plotnr = plotnrs[plottype]
if w.workouttype in ('water','coastal'):
if w.workouttype in otwtypes:
plotnr = plotnr+3

View File

@@ -606,7 +606,7 @@ def get_thumbnails(request,id):
aantalcomments = len(comments)
workouttype = 'ote'
if row.workouttype in ('water','coastal'):
if row.workouttype in types.otwtypes:
workouttype = 'otw'
try:
@@ -1330,7 +1330,7 @@ def add_workout_from_runkeeperdata(user,importid,data):
times_location = times_distance
latcoord = np.zeros(len(times_distance))
loncoord = np.zeros(len(times_distance))
if workouttype in ('water','coastal'):
if workouttype in types.otwtypes:
workouttype = 'rower'
try:
@@ -1511,7 +1511,7 @@ def add_workout_from_stdata(user,importid,data):
times_location = times_distance
latcoord = np.zeros(len(times_distance))
loncoord = np.zeros(len(times_distance))
if workouttype in ('water','coastal'):
if workouttype in types.otwtypes:
workouttype = 'rower'
try:
@@ -1682,7 +1682,7 @@ def add_workout_from_underarmourdata(user,importid,data):
times_location = times_distance
latcoord = np.zeros(len(times_distance))
loncoord = np.zeros(len(times_distance))
if workouttype in ('water','coastal'):
if workouttype in types.otwtypes:
workouttype = 'rower'
try:
@@ -2886,8 +2886,8 @@ def histo_all(request,theuser=0,
enddatestring="",
options={
'includereststrokes':False,
'workouttypes':['rower','dynamic','slides'],
'waterboattype':['1x','2x','2-','4x','4-','8+']
'workouttypes':[i[0] for i in types.workouttypes],
'waterboattype':types.waterboattype
}):
if 'options' in request.session:
@@ -2899,8 +2899,8 @@ def histo_all(request,theuser=0,
workstrokesonly = not includereststrokes
checktypes = ['water','rower','dynamic','slides','skierg',
'paddle','snow','coastal','other']
# checktypes = ['water','rower','dynamic','slides','skierg',
# 'paddle','snow','coastal','other']
if deltadays>0:
@@ -2972,8 +2972,8 @@ def cum_flex_data(
request,
options={
'includereststrokes':False,
'workouttypes':['rower','dynamic','slides'],
'waterboattype':['1x','2x','2-','4x','4-','8+'],
'workouttypes':[i[0] for i in types.workouttypes],
'waterboattype':types.waterboattype,
'theuser':0,
'xparam':'spm',
'yparam1':'power',
@@ -3072,8 +3072,8 @@ def cum_flex(request,theuser=0,
enddatestring="",
options={
'includereststrokes':False,
'workouttypes':['rower','dynamic','slides'],
'waterboattype':['1x','2x','2-','4x','4-','8+']
'workouttypes':[i[0] for i in types.workouttypes],
'waterboattype':types.waterboattype
}):
if 'options' in request.session:
@@ -3082,7 +3082,7 @@ def cum_flex(request,theuser=0,
try:
workouttypes = options['workouttypes']
except KeyError:
workouttypes = ['rower','dynamic','slides']
workouttypes = [i[0] for i in types.workouttypes]
try:
includereststrokes = options['includereststrokes']
@@ -3092,13 +3092,13 @@ def cum_flex(request,theuser=0,
try:
waterboattype = options['waterboattype']
except KeyError:
waterboattype = ['1x','2x','2-','4x','4-','8+']
waterboattype = types.waterboattype
workstrokesonly = not includereststrokes
checktypes = ['water','rower','dynamic','slides','skierg',
'paddle','snow','coastal','other']
# checktypes = ['water','rower','dynamic','slides','skierg',
# 'paddle','snow','coastal','other']
if deltadays>0:
@@ -3176,7 +3176,7 @@ def cum_flex(request,theuser=0,
workstrokesonly = not includereststrokes
waterboattype = optionsform.cleaned_data['waterboattype']
workouttypes = []
for type in checktypes:
for type in types.checktypes:
if optionsform.cleaned_data[type]:
workouttypes.append(type)
@@ -3222,7 +3222,7 @@ def cum_flex(request,theuser=0,
initial['waterboattype'] = waterboattype
for wtype in checktypes:
for wtype in types.checktypes:
if wtype in workouttypes:
initial[wtype] = True
else:
@@ -3409,8 +3409,8 @@ def histo(request,theuser=0,
enddatestring="",
options={
'includereststrokes':False,
'workouttypes':['water','rower','dynamic','slides'],
'waterboattype':['1x','2x','2-','4x','4-','8+']
'workouttypes':[i[0] for i in types.workouttypes],
'waterboattype':types.waterboattype
}):
if 'options' in request.session:
@@ -3421,15 +3421,15 @@ def histo(request,theuser=0,
includereststrokes = options['includereststrokes']
waterboattype = options['waterboattype']
except KeyError:
workouttypes = ['water','rower','dynamic','slides']
waterboattype = ['1x','2x','2-','4x','4-','8+']
workouttypes = [i[0] for i in types.workouttypes]
waterboattype = types.waterboattype
includereststrokes = False
workstrokesonly = not includereststrokes
checktypes = ['water','rower','dynamic','slides','skierg',
'paddle','snow','coastal','other']
# checktypes = ['water','rower','dynamic','slides','skierg',
# 'paddle','snow','coastal','other']
if deltadays>0:
startdate = enddate-datetime.timedelta(days=int(deltadays))
@@ -3499,7 +3499,7 @@ def histo(request,theuser=0,
workstrokesonly = not includereststrokes
waterboattype = optionsform.cleaned_data['waterboattype']
workouttypes = []
for type in checktypes:
for type in types.checktypes:
if optionsform.cleaned_data[type]:
workouttypes.append(type)
@@ -3564,7 +3564,7 @@ def histo(request,theuser=0,
initial['waterboattype'] = waterboattype
for wtype in checktypes:
for wtype in types.checktypes:
if wtype in workouttypes:
initial[wtype] = True
else:
@@ -4476,7 +4476,7 @@ def workout_update_cp_view(request,id=0):
dataprep.runcpupdate(r)
if row.workouttype in ('water','coastal'):
if row.workouttype in types.otwtypes:
url = reverse(otwrankings_view)
else:
url = reverse(oterankings_view)
@@ -5297,7 +5297,7 @@ def workouts_join_select(request,
if 'waterboattype' in request.session:
waterboattype = request.session['waterboattype']
else:
waterboattype = ['1x','2x','2-','4x','4-','8+']
waterboattype = types.waterboattype
if 'modalities' in request.session:
@@ -5456,7 +5456,7 @@ def team_comparison_select(request,
if 'waterboattype' in request.session:
waterboattype = request.session['waterboattype']
else:
waterboattype = ['1x','2x','2-','4x','4-','8+']
waterboattype = types.waterboattype
if 'modalities' in request.session:
@@ -5720,7 +5720,7 @@ def user_multiflex_select(request,
if 'waterboattype' in request.session:
waterboattype = request.session['waterboattype']
else:
waterboattype = ['1x','2x','2-','4x','4-','8+']
waterboattype = types.waterboattype
if 'modalities' in request.session:
@@ -6214,7 +6214,7 @@ def user_boxplot_select(request,
options={
'includereststrokes':False,
'workouttypes':['rower','dynamic','slides'],
'waterboattype':['1x','2x','2-','4x','4-','8+']
'waterboattype':types.waterboattype
},
userid=0):
@@ -6238,9 +6238,9 @@ def user_boxplot_select(request,
workstrokesonly = not includereststrokes
checktypes = ['water','rower','dynamic','slides','skierg',
'paddle','snow','other','coastal']
waterboattype = ['1x','2x','2-','4x','4-','8+']
# checktypes = ['water','rower','dynamic','slides','skierg',
# 'paddle','snow','other','coastal']
waterboattype = types.waterboattype
if 'startdate' in request.session:
startdate = iso8601.parse_date(request.session['startdate'])
@@ -6287,7 +6287,7 @@ def user_boxplot_select(request,
if optionsform.is_valid():
workouttypes = []
waterboattype = optionsform.cleaned_data['waterboattype']
for type in checktypes:
for type in types.checktypes:
if optionsform.cleaned_data[type]:
workouttypes.append(type)
@@ -6361,7 +6361,7 @@ def user_boxplot_select(request,
initial = {}
initial['waterboattype'] = waterboattype
for wtype in checktypes:
for wtype in types.checktypes:
if wtype in workouttypes:
initial[wtype] = True
else:
@@ -7617,7 +7617,7 @@ def workout_geeky_view(request,id=0,message="",successmessage=""):
messages.error(request,message)
messages.info(request,successmessage)
if row.workouttype in ('water','coastal'):
if row.workouttype in types.otwtypes:
return render(request,
'otwgeeky.html',
{'workout':row,
@@ -7702,7 +7702,7 @@ def cumstats(request,theuser=0,
options={
'includereststrokes':False,
'workouttypes':['rower','dynamic','slides'],
'waterboattype':['1x','2x','2-','4x','4-','8+']
'waterboattype':types.waterboattype
}):
if 'options' in request.session:
@@ -7722,9 +7722,9 @@ def cumstats(request,theuser=0,
workstrokesonly = not includereststrokes
checktypes = ['water','rower','dynamic','slides','skierg',
'paddle','snow','other','coastal']
waterboattype = ['1x','2x','2-','4x','4-','8+']
# checktypes = ['water','rower','dynamic','slides','skierg',
# 'paddle','snow','other','coastal']
waterboattype = types.waterboattype
if deltadays>0:
startdate = enddate-datetime.timedelta(days=int(deltadays))
@@ -7800,7 +7800,7 @@ def cumstats(request,theuser=0,
workstrokesonly = not includereststrokes
workouttypes = []
waterboattype = optionsform.cleaned_data['waterboattype']
for type in checktypes:
for type in types.checktypes:
if optionsform.cleaned_data[type]:
workouttypes.append(type)
@@ -7952,7 +7952,7 @@ def cumstats(request,theuser=0,
initial['includereststrokes'] = includereststrokes
initial['waterboattype'] = waterboattype
for wtype in checktypes:
for wtype in types.checktypes:
if wtype in workouttypes:
initial[wtype] = True
else:
@@ -8172,7 +8172,7 @@ def workout_advanced_view(request,id=0,message="",successmessage=""):
messages.info(request,successmessage)
if row.workouttype in ('water','coastal'):
if row.workouttype in types.otwtypes:
return render(request,
'advancedotw.html',
{'workout':row,
@@ -8436,7 +8436,7 @@ def workout_workflow_view(request,id):
aantalcomments = len(comments)
workouttype = 'ote'
if row.workouttype in ('water','coastal'):
if row.workouttype in types.otwtypes:
workouttype = 'otw'
try:
@@ -8528,7 +8528,7 @@ def workout_flexchart3_view(request,*args,**kwargs):
mayedit=1
workouttype = 'ote'
if row.workouttype in ('water','coastal'):
if row.workouttype in types.otwtypes:
workouttype = 'otw'
try:
@@ -8686,7 +8686,7 @@ def workout_flexchart3_view(request,*args,**kwargs):
noylist = ["time","distance"]
axchoicesbasic.pop("cumdist")
if row.workouttype in ('water','coastal'):
if row.workouttype in types.otwtypes:
for name,d in rowingmetrics:
if d['mode'] == 'erg':
axchoicespro.pop(name)
@@ -10961,7 +10961,7 @@ def workout_summary_restore_view(request,id,message="",successmessage=""):
r.pw_tr,r.pw_an])/r.ftp
ftp = float(r.ftp)
if row.workouttype in ('water','coastal'):
if row.workouttype in types.otwtypes:
ftp = ftp*(100.-r.otwslack)/100.
rr = rrower(hrmax=r.max,hrut2=r.ut2,
@@ -11147,7 +11147,7 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
r.pw_tr,r.pw_an])/r.ftp
ftp = float(r.ftp)
if row.workouttype in ('water','coastal'):
if row.workouttype in types.otwtypes:
ftp = ftp*(100.-r.otwslack)/100.
rr = rrower(hrmax=r.max,hrut2=r.ut2,
@@ -11907,7 +11907,7 @@ def strokedatajson(request,id):
r.pw_tr,r.pw_an])/r.ftp
ftp = float(r.ftp)
if row.workouttype in ('water','coastal'):
if row.workouttype in types.otwtypes:
ftp = ftp*(100.-r.otwslack)/100.
rr = rrower(hrmax=r.max,hrut2=r.ut2,
@@ -13644,6 +13644,7 @@ def virtualevent_view(request,id=0):
cd = form.cleaned_data
sex = cd['sex']
boattype = cd['boattype']
boatclass = cd['boatclass']
age_min = cd['age_min']
age_max = cd['age_max']
weightcategory = cd['weightcategory']
@@ -13651,6 +13652,7 @@ def virtualevent_view(request,id=0):
results = VirtualRaceResult.objects.filter(
race=race,
workoutid__isnull=False,
boatclass__in=boatclass,
boattype__in=boattype,
sex__in=sex,
weightcategory__in=weightcategory,
@@ -13664,6 +13666,7 @@ def virtualevent_view(request,id=0):
dns = VirtualRaceResult.objects.filter(
race=race,
workoutid__isnull=True,
boatclass__in=boatclass,
boattype__in=boattype,
sex__in=sex,
weightcategory__in=weightcategory,
@@ -13752,6 +13755,7 @@ def virtualevent_addboat_view(request,id=0):
)
boattypes = [record.boattype for record in records]
boatclasses = [record.boatclass for record in records]
allowedboats = tuple([ type for type in types.boattypes if type[0] not in boattypes] )
@@ -13763,6 +13767,7 @@ def virtualevent_addboat_view(request,id=0):
cd = form.cleaned_data
teamname = cd['teamname']
boattype = cd['boattype']
boatclass = cd['boatclass']
weightcategory = cd['weightcategory']
age = cd['age']
mix = cd['mix']
@@ -13778,8 +13783,8 @@ def virtualevent_addboat_view(request,id=0):
if sex == 'not specified':
sex = 'male'
if boattype in boattypes:
messages.error(request,"You have already registered in that boat type")
if boattype in boattypes and boatclass in boatclasses:
messages.error(request,"You have already registered in that boat class/type")
url = reverse(virtualevent_view,
kwargs = {
'id': race.id
@@ -13799,6 +13804,7 @@ def virtualevent_addboat_view(request,id=0):
weightcategory=weightcategory,
duration=datetime.time(0,0),
boattype=boattype,
boatclass=boatclass,
coursecompleted=False,
sex=sex,
age=age
@@ -13828,7 +13834,7 @@ def virtualevent_addboat_view(request,id=0):
'weightcategory': r.weightcategory,
}
form = VirtualRaceResultForm(initial=initial,boattypes=allowedboats)
form = VirtualRaceResultForm(initial=initial)
return render(request,'virtualeventregister.html',
{
@@ -13864,6 +13870,7 @@ def virtualevent_register_view(request,id=0):
cd = form.cleaned_data
teamname = cd['teamname']
boattype = cd['boattype']
boatclass = cd['boatclass']
weightcategory = cd['weightcategory']
age = cd['age']
mix = cd['mix']
@@ -13889,6 +13896,7 @@ def virtualevent_register_view(request,id=0):
),
weightcategory=weightcategory,
duration=datetime.time(0,0),
boatclass=boatclass,
boattype=boattype,
coursecompleted=False,
sex=sex,