Private
Public Access
1
0

Merge branch 'feature/submitrace' into develop

This commit is contained in:
Sander Roosendaal
2020-06-21 16:41:49 +02:00
7 changed files with 295 additions and 61 deletions

View File

@@ -12,6 +12,8 @@ billiard==3.6.0.0
bleach==3.1.0 bleach==3.1.0
bokeh==1.0.4 bokeh==1.0.4
boto==2.49.0 boto==2.49.0
boto3==1.14.7
botocore==1.17.7
braintree==3.55.0 braintree==3.55.0
cairocffi==1.0.2 cairocffi==1.0.2
celery==4.3.0 celery==4.3.0
@@ -53,7 +55,7 @@ django-rest-framework==0.1.0
django-rest-swagger==2.2.0 django-rest-swagger==2.2.0
django-rq==1.3.1 django-rq==1.3.1
django-rq-dashboard==0.3.3 django-rq-dashboard==0.3.3
django-ses==0.8.10 django-ses==1.0.0
django-shell-plus==1.1.7 django-shell-plus==1.1.7
django-social-share==1.3.2 django-social-share==1.3.2
django-suit==0.2.26 django-suit==0.2.26
@@ -96,6 +98,7 @@ itypes==1.1.0
jedi==0.13.3 jedi==0.13.3
jeepney==0.4 jeepney==0.4
Jinja2==2.10 Jinja2==2.10
jmespath==0.10.0
json5==0.8.5 json5==0.8.5
jsonschema==3.0.1 jsonschema==3.0.1
jupyter==1.0.0 jupyter==1.0.0
@@ -125,7 +128,7 @@ newrelic==5.2.1.129
nose==1.3.7 nose==1.3.7
nose-parameterized==0.6.0 nose-parameterized==0.6.0
notebook==5.7.6 notebook==5.7.6
numba==0.46.0 numba==0.50.0
numpy==1.18.5 numpy==1.18.5
oauth2==1.9.0.post1 oauth2==1.9.0.post1
oauthlib==3.0.1 oauthlib==3.0.1
@@ -179,6 +182,7 @@ rowingdata==2.9.1
rowingphysics==0.5.0 rowingphysics==0.5.0
rq==0.13.0 rq==0.13.0
rules==2.1 rules==2.1
s3transfer==0.3.3
scipy==1.2.1 scipy==1.2.1
SecretStorage==3.1.1 SecretStorage==3.1.1
Send2Trash==1.5.0 Send2Trash==1.5.0

View File

@@ -124,7 +124,7 @@ class EmailForm(forms.Form):
subject = forms.CharField(max_length=255) subject = forms.CharField(max_length=255)
message = forms.CharField(widget=forms.Textarea()) message = forms.CharField(widget=forms.Textarea())
disqualificationreasons = ( disqualificationreasons = (
('noimage','No monitor screenshot or data evidence was included'), ('noimage','No monitor screenshot or data evidence was included'),
@@ -386,7 +386,7 @@ class UploadOptionsForm(forms.Form):
makeprivate = forms.BooleanField(initial=False,required=False, makeprivate = forms.BooleanField(initial=False,required=False,
label='Make Workout Private') label='Make Workout Private')
submitrace = forms.ModelChoiceField(queryset=VirtualRace.objects.all(), submitrace = forms.ChoiceField(
label='Submit as challenge Result', label='Submit as challenge Result',
required=False) required=False)
@@ -404,6 +404,7 @@ class UploadOptionsForm(forms.Form):
r = Rower.objects.get(user=self.request.user) r = Rower.objects.get(user=self.request.user)
races = VirtualRace.objects.filter( races = VirtualRace.objects.filter(
registration_closure__gt=timezone.now()) registration_closure__gt=timezone.now())
registrations = IndoorVirtualRaceResult.objects.filter( registrations = IndoorVirtualRaceResult.objects.filter(
race__in = races, race__in = races,
userid = r.id) userid = r.id)
@@ -413,25 +414,41 @@ class UploadOptionsForm(forms.Form):
userid = r.id, userid = r.id,
) )
raceids = [r.race.id for r in registrations] choices1 = [(r.id,str(r)) for r in registrations]
raceids2 = [r.race.id for r in registrations2] choices2 = [(r.id,str(r)) for r in registrations2]
choices3 = [(0,'---')]
raceids = raceids+raceids2 noregistrations = []
for ra in VirtualRace.objects.filter(registration_closure__gt=timezone.now(),sessiontype='race'):
rs = VirtualRaceResult.objects.filter(race = ra,userid=r.id)
if rs.count()==0:
noregistrations.append((-ra.id,ra.name))
for ra in VirtualRace.objects.filter(registration_closure__gt=timezone.now(),sessiontype='indoorrace'):
rs = IndoorVirtualRaceResult.objects.filter(race = ra,userid=r.id)
if rs.count()==0:
noregistrations.append((-ra.id,ra.name))
races = VirtualRace.objects.filter( choices = choices3+choices1+choices2+noregistrations
id__in=raceids
)
if int(raceid) in [r.id for r in races]:
therace = VirtualRace.objects.get(id=raceid)
if therace.sessiontype == 'race':
registrations = VirtualRaceResult.objects.filter(race=therace,userid=r.id)
else:
registrations = IndoorVirtualRaceResult.objects.filter(race=therace,userid=r.id)
if registrations.count()==0:
race = VirtualRace.objects.get(id=raceid)
choices = [(-int(raceid),race.name)]
else:
choices = [(r.id,str(r)) for r in registrations]
choices = choices+[(0,'---')]
if races: if races:
self.fields['submitrace'].queryset = races self.fields['submitrace'].choices = choices
else: else:
del self.fields['submitrace'] del self.fields['submitrace']
if int(raceid) in raceids:
self.fields['submitrace'].initial = VirtualRace.objects.get(id=raceid)
# The form to indicate additional actions to be performed immediately # The form to indicate additional actions to be performed immediately
# after a successful upload. This version allows the Team manager to select # after a successful upload. This version allows the Team manager to select

View File

@@ -2648,7 +2648,7 @@ class VirtualRaceForm(ModelForm):
except KeyError: except KeyError:
registration_closure = enddatetime+datetime.timedelta(days=1) registration_closure = enddatetime+datetime.timedelta(days=1)
cd['registration_closure'] = registration_closure cd['registration_closure'] = registration_closure
registration_form = cd['registration_form'] registration_form = cd['registration_form']
try: try:
@@ -3124,6 +3124,8 @@ class CourseTestResult(models.Model):
distance = models.IntegerField(default=0) distance = models.IntegerField(default=0)
coursecompleted = models.BooleanField(default=False) coursecompleted = models.BooleanField(default=False)
class IndoorVirtualRaceResultForm(ModelForm): class IndoorVirtualRaceResultForm(ModelForm):
class Meta: class Meta:
model = IndoorVirtualRaceResult model = IndoorVirtualRaceResult

View File

@@ -45,7 +45,7 @@ from rowers.models import (
GeoCourse, TrainingMicroCycle,TrainingMesoCycle,TrainingMacroCycle, GeoCourse, TrainingMicroCycle,TrainingMesoCycle,TrainingMacroCycle,
TrainingPlan,PlannedSession,VirtualRaceResult,CourseTestResult, TrainingPlan,PlannedSession,VirtualRaceResult,CourseTestResult,
get_course_timezone, IndoorVirtualRaceResult,VirtualRace,createmacrofillers, get_course_timezone, IndoorVirtualRaceResult,VirtualRace,createmacrofillers,
createmesofillers,createmicrofillers, createmesofillers,createmicrofillers,CourseStandard,
) )
from rowers.courses import get_time_course from rowers.courses import get_time_course
@@ -1041,8 +1041,8 @@ def race_can_edit(r,race):
return False return False
def race_can_submit(r,race): def race_can_submit(r,race):
if r not in race.rower.all(): #if r not in race.rower.all():
return False # return False
start_time = race.start_time start_time = race.start_time
start_date = race.startdate start_date = race.startdate
@@ -1341,8 +1341,70 @@ def remove_rower_race(r,race,recordid=None):
return 1 return 1
def default_class(r,w,race):
if r.birthdate:
age = calculate_age(r.birthdate)
else:
age = 25
sex = r.sex
if sex=='not specified':
sex='male'
if w is not None:
boatclass = w.workouttype
boattype = w.boattype
adaptiveclass = w.adaptiveclass
weightclass = w.weightcategory
else:
if race.sessiontype == 'race':
boatclass = 'water'
else:
boatclass = 'rower'
boattype = '1x'
adaptiveclass = 'None'
weightclass = 'hwt'
if race.coursestandards:
standards = CourseStandard.objects.filter(
agemin__lt=age,agemax__gt=age,
boatclass=boatclass,
adaptiveclass=adaptiveclass,
boattype=boattype,
weightclass=weightclass
).order_by("agemax","-agemin","boattype")
if standards.count()==0:
# omit weight
standards = CourseStandard.objects.filter(agemin__lt=age,agemax__gt=age,
boatclass=boatclass,
adaptiveclass=adaptiveclass,
boattype=boattype,
)
if standards.count()==0:
standards = CourseStandard.objects.filter(agemin__lt=age,agemax__gt=age,
boattype=boattype)
if standards.count()==0:
standards = CourseStandard.objects.filter(agemin__lt=age,agemax__gt=age)
if standards.count()==0:
# boolean, boattype, boatclass, adaptiveclass, weightclass, sex, coursestandard,
return False,'1x','water',None,'hwt','male',None
if standards.count()>0:
# find optimum standard
s = standards[0]
return True,s.boattype,s.boatclass,s.adaptiveclass,s.weightclass,s.sex,s
# No Course Standard
return True,boattype,boatclass,adaptiveclass,weightclass,sex,None
# Low Level functions - to be called by higher level methods # Low Level functions - to be called by higher level methods
def add_workout_indoorrace(ws,race,r,recordid=0): def add_workout_indoorrace(ws,race,r,recordid=0,doregister=False):
result = 0 result = 0
comments = [] comments = []
errors = [] errors = []
@@ -1389,12 +1451,34 @@ def add_workout_indoorrace(ws,race,r,recordid=0):
else: else:
age = None age = None
record = IndoorVirtualRaceResult.objects.get( try:
userid=r.id, record = IndoorVirtualRaceResult.objects.get(
race=race, userid=r.id,
id=recordid race=race,
) id=recordid
)
except IndoorVirtualRaceResult.DoesNotExist:
if doregister:
hasinitial,boattype,boatclass,adaptiveclass,weightclass,sex,initialcategory = default_class(r,ws[0],race)
if hasinitial:
record = IndoorVirtualRaceResult(
userid = r.id,
username = r.user.first_name+' '+r.user.last_name,
weightcategory=weightclass,
adaptiveclass=adaptiveclass,
race=race,
boatclass=boatclass,
sex=sex,
age = age,
entrycategory=initialcategory,
)
record.save()
else:
errors.append("Unable to find a suitable start category")
return result,comments,errors,0
else:
errors.append("Couldn't find this entry")
return result,comments,errors,0
records = IndoorVirtualRaceResult.objects.filter( records = IndoorVirtualRaceResult.objects.filter(
userid=r.id, userid=r.id,
@@ -1402,9 +1486,11 @@ def add_workout_indoorrace(ws,race,r,recordid=0):
workoutid = ws[0].id workoutid = ws[0].id
) )
if not record:
errors.append("Couldn't find this entry")
return result,comments,errors,0
if race.sessionmode == 'distance': if race.sessionmode == 'distance':
if ws[0].distance != race.sessionvalue: if ws[0].distance != race.sessionvalue:
@@ -1471,7 +1557,7 @@ def add_workout_indoorrace(ws,race,r,recordid=0):
return result,comments,errors,0 return result,comments,errors,0
def add_workout_race(ws,race,r,splitsecond=0,recordid=0): def add_workout_race(ws,race,r,splitsecond=0,recordid=0,doregister=False):
result = 0 result = 0
comments = [] comments = []
errors = [] errors = []
@@ -1517,11 +1603,35 @@ def add_workout_race(ws,race,r,splitsecond=0,recordid=0):
else: else:
age = None age = None
record = VirtualRaceResult.objects.get( try:
userid=r.id, record = VirtualRaceResult.objects.get(
race=race, userid=r.id,
id=recordid race=race,
) id=recordid
)
except VirtualRaceResult.DoesNotExist:
if doregister:
hasinitial,boattype,boatclass,adaptiveclass,weightclass,sex,initialcategory = default_class(r,ws[0],race)
if hasinitial:
record = VirtualRaceResult(
userid = r.id,
username = r.user.first_name+' '+r.user.last_name,
weightcategory=weightclass,
adaptiveclass=adaptiveclass,
race=race,
boatclass=boatclass,
boattype=boattype,
sex=sex,
age = age,
entrycategory=initialcategory,
)
record.save()
else:
errors.append("Unable to find a suitable start category")
return result,comments,errors,0
else:
errors.append("Couldn't find this entry")
return result,comments,errors,0
records = VirtualRaceResult.objects.filter( records = VirtualRaceResult.objects.filter(
userid=r.id, userid=r.id,
@@ -1529,7 +1639,7 @@ def add_workout_race(ws,race,r,splitsecond=0,recordid=0):
workoutid = ws[0].id workoutid = ws[0].id
) )
if not record: if not record and not doregister:
errors.append("Couldn't find this entry") errors.append("Couldn't find this entry")
return result,comments,errors,0 return result,comments,errors,0
@@ -1589,6 +1699,8 @@ def add_workout_race(ws,race,r,splitsecond=0,recordid=0):
referencespeed=record.referencespeed,coursedistance=race.course.distance referencespeed=record.referencespeed,coursedistance=race.course.distance
) )
comments.append('We are now checking adherence to the race course. This may take a few minutes to complete')
add_workouts_plannedsession(ws,race,r) add_workouts_plannedsession(ws,race,r)

View File

@@ -163,6 +163,7 @@
Registered users of rowsandall.com can participate in this challenge. Registered users of rowsandall.com can participate in this challenge.
Participation is free, unless specified differently in the race comment above. Participation is free, unless specified differently in the race comment above.
{% if race.sessiontype == 'race' %} {% if race.sessiontype == 'race' %}
Register to let others know you plan to do this challenge:
<a href="/rowers/virtualevent/{{ race.id }}/register"><h3>Register</h3></a> <a href="/rowers/virtualevent/{{ race.id }}/register"><h3>Register</h3></a>
{% else %} {% else %}
<a href="/rowers/virtualevent/{{ race.id }}/registerindoor"><h3>Register</h3></a> <a href="/rowers/virtualevent/{{ race.id }}/registerindoor"><h3>Register</h3></a>
@@ -183,6 +184,8 @@
{% for button in buttons %} {% for button in buttons %}
{% if button == 'registerbutton' %} {% if button == 'registerbutton' %}
<p> <p>
Register to let others know you plan to do this challenge. This also give you the option to
select your entry category:
{% if race.sessiontype == 'race' %} {% if race.sessiontype == 'race' %}
<a href="/rowers/virtualevent/{{ race.id }}/register"><h3>Register</h3></a> <a href="/rowers/virtualevent/{{ race.id }}/register"><h3>Register</h3></a>
{% else %} {% else %}

View File

@@ -746,6 +746,7 @@ def virtualevent_disqualify_view(request,id=0,recordid=0):
r = getrower(request.user) r = getrower(request.user)
race = get_object_or_404(VirtualRace,pk=id) race = get_object_or_404(VirtualRace,pk=id)
raceid = race.id
if race.sessiontype == 'race': if race.sessiontype == 'race':
@@ -1499,6 +1500,7 @@ def virtualevent_addboat_view(request,id=0):
raise Http404("Virtual Challenge does not exist") raise Http404("Virtual Challenge does not exist")
categories = None categories = None
hasinitial,boattype,boatclass,adaptiveclass,weightclass,sex,initialcategory = default_class(r,None,race)
if race.coursestandards is not None: if race.coursestandards is not None:
categories = CourseStandard.objects.filter( categories = CourseStandard.objects.filter(
standardcollection=race.coursestandards).order_by("name") standardcollection=race.coursestandards).order_by("name")
@@ -1700,11 +1702,22 @@ def virtualevent_addboat_view(request,id=0):
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
else: else:
initial = { if hasinitial:
'age': calculate_age(r.birthdate), initial = {
'weightcategory': r.weightcategory, 'age': calculate_age(r.birthdate),
'adaptiveclass': r.adaptiveclass, 'boattype':boattype,
'boatclass':boatclass,
'adaptiveclass':adaptiveclass,
'weightclass':weightclass,
'sex':sex,
'entrycategory':initialcategory,
} }
else:
initial = {
'age': calculate_age(r.birthdate),
'weightcategory': r.weightcategory,
'adaptiveclass': r.adaptiveclass,
}
categories = None categories = None
if race.coursestandards is not None: if race.coursestandards is not None:
@@ -1774,6 +1787,7 @@ def virtualevent_register_view(request,id=0):
raise Http404("Virtual Challenge does not exist") raise Http404("Virtual Challenge does not exist")
categories = None categories = None
hasinitial,boattype,boatclass,adaptiveclass,weightclass,sex,initialcategory = default_class(r,None,race)
if race.coursestandards is not None: if race.coursestandards is not None:
categories = CourseStandard.objects.filter( categories = CourseStandard.objects.filter(
standardcollection=race.coursestandards).order_by("name") standardcollection=race.coursestandards).order_by("name")
@@ -1937,11 +1951,22 @@ def virtualevent_register_view(request,id=0):
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
else: else:
initial = { if hasinitial:
'age': calculate_age(r.birthdate), initial = {
'weightcategory': r.weightcategory, 'age': calculate_age(r.birthdate),
'adaptiveclass': r.adaptiveclass, 'boattype':boattype,
'boatclass':boatclass,
'adaptiveclass':adaptiveclass,
'weightclass':weightclass,
'sex':sex,
'entrycategory':initialcategory,
} }
else:
initial = {
'age': calculate_age(r.birthdate),
'weightcategory': r.weightcategory,
'adaptiveclass': r.adaptiveclass,
}
categories = None categories = None
if race.coursestandards is not None: if race.coursestandards is not None:
@@ -2786,6 +2811,29 @@ def virtualevent_submit_result_view(request,id=0,workoutid=0):
race=race race=race
) )
if records.count() == 0:
hasinitial,boattype,boatclass,adaptiveclass,weightclass,sex,initialcategory = default_class(r,None,race)
if not hasinitial:
messages.error(request,"Sorry, you have to register first")
url = reverse('virtualevent_view',
kwargs = {
'id':id,
})
return HttpResponseRedirect(url)
record = resultobj(
userid = r.id,
username = r.user.first_name+' '+r.user.last_name,
weightcategory=weightclass,
adaptiveclass=adaptiveclass,
race=race,
boatclass=boatclass,
sex=sex,
age=calculate_age(r.birthdate),
entrycategory=initialcategory,
)
record.save()
records = [record]
entrychoices = [] entrychoices = []

View File

@@ -4909,7 +4909,7 @@ def workout_upload_view(request,
notes = form.cleaned_data['notes'] notes = form.cleaned_data['notes']
offline = form.cleaned_data['offline'] offline = form.cleaned_data['offline']
race = None registrationid = 0
if optionsform.is_valid(): if optionsform.is_valid():
make_plot = optionsform.cleaned_data['make_plot'] make_plot = optionsform.cleaned_data['make_plot']
plottype = optionsform.cleaned_data['plottype'] plottype = optionsform.cleaned_data['plottype']
@@ -4923,9 +4923,9 @@ def workout_upload_view(request,
landingpage = optionsform.cleaned_data['landingpage'] landingpage = optionsform.cleaned_data['landingpage']
try: try:
race = optionsform.cleaned_data['submitrace'] registrationid = optionsform.cleaned_data['submitrace']
except KeyError: except KeyError:
race = None registrationid = 0
uploadoptions = { uploadoptions = {
'makeprivate':makeprivate, 'makeprivate':makeprivate,
@@ -5113,17 +5113,58 @@ def workout_upload_view(request,
else: else:
messages.error(request,message) messages.error(request,message)
if race and race_can_submit(r,race): if int(registrationid) < 0:
if race.sessiontype == 'indoorrace': race = VirtualRace.objects.get(id=-int(registrationid))
records = IndoorVirtualRaceResult.objects.filter( if race.sessiontype == 'race':
race=race, result,comments,errors,jobid = add_workout_race(
userid=r.id [w], race,r,doregister=True,
)
if result:
messages.info(
request,
"We have submitted your workout to the race")
for c in comments:
messages.info(request,c)
for er in errors:
messages.error(request,er)
elif race.sessiontype == 'indoorrace':
result,comments,errors,jobid = add_workout_indoorrace(
[w],race,r,doregister=True,
) )
if records: if result:
messages.info(
request,
"We have submitted your workout to the race")
for c in comments:
messages.info(request,c)
for er in errors:
messages.error(request,er)
if int(registrationid)>0:
races = VirtualRace.objects.filter(
registration_closure__gt=timezone.now()
)
registrations = IndoorVirtualRaceResult.objects.filter(
race__in = races,
id=registrationid,
userid = r.id,
)
registrations2 = VirtualRaceResult.objects.filter(
race__in = races,
id=registrationid,
userid=r.id,
)
if int(registrationid) in [r.id for r in registrations]:
# indoor race
registrations = registrations.filter(id=registrationid)
if registrations:
race = registrations[0].race
result,comments,errors,jobid = add_workout_indoorrace( result,comments,errors,jobid = add_workout_indoorrace(
[w],race,r,recordid=records[0].id [w],race,r,recordid=registrations[0].id
) )
if result: if result:
@@ -5135,15 +5176,15 @@ def workout_upload_view(request,
messages.info(request,c) messages.info(request,c)
for er in errors: for er in errors:
messages.error(request,er) messages.error(request,er)
if race.sessiontype == 'race':
records = VirtualRaceResult.objects.filter(
race=race,userid=r.id
)
if records: if int(registrationid) in [r.id for r in registrations2]:
# race
registrations = registrations2.filter(id=registrationid)
if registrations:
race = registrations[0].race
result,comments,errors,jobid = add_workout_race( result,comments,errors,jobid = add_workout_race(
[w], race,r,recordid=records[0].id [w], race,r,recordid=registrations[0].id
) )
if result: if result:
messages.info( messages.info(
@@ -5156,11 +5197,18 @@ def workout_upload_view(request,
messages.error(request,er) messages.error(request,er)
if landingpage != 'workout_upload_view':
if registrationid != 0:
url = reverse('virtualevent_view',
kwargs = {
'id':race.id,
})
elif landingpage != 'workout_upload_view':
url = reverse(landingpage, url = reverse(landingpage,
kwargs = { kwargs = {
'id':encoder.encode_hex(w.id), 'id':encoder.encode_hex(w.id),
}) })
else: else:
url = reverse(landingpage) url = reverse(landingpage)