Merge branch 'feature/scoringsystem' into develop
This commit is contained in:
+9
-1
@@ -11,7 +11,7 @@ from .models import (
|
|||||||
Team,TeamInvite,TeamRequest,
|
Team,TeamInvite,TeamRequest,
|
||||||
WorkoutComment,C2WorldClassAgePerformance,PlannedSession,
|
WorkoutComment,C2WorldClassAgePerformance,PlannedSession,
|
||||||
GeoCourse,GeoPolygon,GeoPoint,VirtualRace,VirtualRaceResult,
|
GeoCourse,GeoPolygon,GeoPoint,VirtualRace,VirtualRaceResult,
|
||||||
PaidPlan,IndoorVirtualRaceResult,ShareKey
|
PaidPlan,IndoorVirtualRaceResult,ShareKey, CourseStandard,StandardCollection,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Register your models here so you can use them in the Admin module
|
# Register your models here so you can use them in the Admin module
|
||||||
@@ -141,6 +141,12 @@ class IndoorVirtualRaceResultAdmin(admin.ModelAdmin):
|
|||||||
class PaidPlanAdmin(admin.ModelAdmin):
|
class PaidPlanAdmin(admin.ModelAdmin):
|
||||||
list_display = ('name','shortname','price','paymenttype','paymentprocessor','external_id')
|
list_display = ('name','shortname','price','paymenttype','paymentprocessor','external_id')
|
||||||
|
|
||||||
|
class StandardCollectionAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ('name','manager')
|
||||||
|
|
||||||
|
class CourseStandardAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ('name','standardcollection')
|
||||||
|
|
||||||
admin.site.unregister(User)
|
admin.site.unregister(User)
|
||||||
admin.site.register(User,UserAdmin)
|
admin.site.register(User,UserAdmin)
|
||||||
admin.site.register(Workout,WorkoutAdmin)
|
admin.site.register(Workout,WorkoutAdmin)
|
||||||
@@ -160,3 +166,5 @@ admin.site.register(VirtualRaceResult, VirtualRaceResultAdmin)
|
|||||||
admin.site.register(IndoorVirtualRaceResult, IndoorVirtualRaceResultAdmin)
|
admin.site.register(IndoorVirtualRaceResult, IndoorVirtualRaceResultAdmin)
|
||||||
admin.site.register(PaidPlan,PaidPlanAdmin)
|
admin.site.register(PaidPlan,PaidPlanAdmin)
|
||||||
admin.site.register(ShareKey,ShareKeyAdmin)
|
admin.site.register(ShareKey,ShareKeyAdmin)
|
||||||
|
admin.site.register(CourseStandard,CourseStandardAdmin)
|
||||||
|
admin.site.register(StandardCollection,StandardCollectionAdmin)
|
||||||
|
|||||||
@@ -2,6 +2,11 @@ from __future__ import absolute_import
|
|||||||
from __future__ import division
|
from __future__ import division
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# low level methods
|
# low level methods
|
||||||
def coordinate_in_path(latitude,longitude, p):
|
def coordinate_in_path(latitude,longitude, p):
|
||||||
|
|
||||||
|
|||||||
@@ -212,6 +212,18 @@ class CourseForm(forms.Form):
|
|||||||
from django.forms.widgets import HiddenInput
|
from django.forms.widgets import HiddenInput
|
||||||
super(CourseForm, self).__init__(*args, **kwargs)
|
super(CourseForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
# The form used for uploading images
|
||||||
|
class StandardsForm(forms.Form):
|
||||||
|
name = forms.CharField(max_length=150,label='Course Name')
|
||||||
|
file = forms.FileField(required=False,
|
||||||
|
validators=[must_be_csv])
|
||||||
|
notes = forms.CharField(required=False,
|
||||||
|
max_length=200,label='Course Notes',
|
||||||
|
widget=forms.Textarea)
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
from django.forms.widgets import HiddenInput
|
||||||
|
super(StandardsForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
# The form used for uploading files
|
# The form used for uploading files
|
||||||
class DocumentsForm(forms.Form):
|
class DocumentsForm(forms.Form):
|
||||||
@@ -1218,6 +1230,12 @@ class RaceResultFilterForm(forms.Form):
|
|||||||
initial=['None','PR1','PR2','PR3','FES'],
|
initial=['None','PR1','PR2','PR3','FES'],
|
||||||
widget=forms.CheckboxSelectMultiple())
|
widget=forms.CheckboxSelectMultiple())
|
||||||
|
|
||||||
|
entrycategory = forms.MultipleChoiceField(
|
||||||
|
choices = [],
|
||||||
|
label = 'Groups',
|
||||||
|
widget=forms.CheckboxSelectMultiple()
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
if 'records' in kwargs:
|
if 'records' in kwargs:
|
||||||
records = kwargs.pop('records',None)
|
records = kwargs.pop('records',None)
|
||||||
@@ -1225,6 +1243,21 @@ class RaceResultFilterForm(forms.Form):
|
|||||||
super(RaceResultFilterForm,self).__init__(*args,**kwargs)
|
super(RaceResultFilterForm,self).__init__(*args,**kwargs)
|
||||||
|
|
||||||
if records:
|
if records:
|
||||||
|
# group
|
||||||
|
thecategories = [record.entrycategory for record in records]
|
||||||
|
thecategories = list(set(thecategories))
|
||||||
|
if len(thecategories) <= 1:
|
||||||
|
del self.fields['entrycategory']
|
||||||
|
else:
|
||||||
|
categorychoices = []
|
||||||
|
for category in thecategories:
|
||||||
|
if category is not None:
|
||||||
|
categorychoices.append(
|
||||||
|
(category.id,category)
|
||||||
|
)
|
||||||
|
self.fields['entrycategory'].choices = categorychoices
|
||||||
|
self.fields['entrycategory'].initial = [cat[0] for cat in categorychoices]
|
||||||
|
|
||||||
# sex
|
# sex
|
||||||
thesexes = [record.sex for record in records]
|
thesexes = [record.sex for record in records]
|
||||||
thesexes = list(set(thesexes))
|
thesexes = list(set(thesexes))
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
+98
-19
@@ -243,15 +243,9 @@ def update_records(url=c2url,verbose=True):
|
|||||||
|
|
||||||
|
|
||||||
class CalcAgePerformance(models.Model):
|
class CalcAgePerformance(models.Model):
|
||||||
weightcategories = (
|
weightcategories = mytypes.weightcategories
|
||||||
('hwt','heavy-weight'),
|
|
||||||
('lwt','light-weight'),
|
|
||||||
)
|
|
||||||
|
|
||||||
sexcategories = (
|
sexcategories = mytypes.sexcategories
|
||||||
('male','male'),
|
|
||||||
('female','female'),
|
|
||||||
)
|
|
||||||
|
|
||||||
weightcategory = models.CharField(default="hwt",
|
weightcategory = models.CharField(default="hwt",
|
||||||
max_length=30,
|
max_length=30,
|
||||||
@@ -288,10 +282,7 @@ class PowerTimeFitnessMetric(models.Model):
|
|||||||
|
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
class C2WorldClassAgePerformance(models.Model):
|
class C2WorldClassAgePerformance(models.Model):
|
||||||
weightcategories = (
|
weightcategories = mytypes.weightcategories
|
||||||
('hwt','heavy-weight'),
|
|
||||||
('lwt','light-weight'),
|
|
||||||
)
|
|
||||||
|
|
||||||
sexcategories = (
|
sexcategories = (
|
||||||
('male','male'),
|
('male','male'),
|
||||||
@@ -593,10 +584,8 @@ sexcategories = (
|
|||||||
('female','female'),
|
('female','female'),
|
||||||
('not specified','not specified'),
|
('not specified','not specified'),
|
||||||
)
|
)
|
||||||
weightcategories = (
|
|
||||||
('hwt','heavy-weight'),
|
weightcategories = mytypes.weightcategories
|
||||||
('lwt','light-weight'),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# Plan
|
# Plan
|
||||||
@@ -2194,7 +2183,38 @@ class PlannedSession(models.Model):
|
|||||||
|
|
||||||
from django.core.validators import RegexValidator,validate_email
|
from django.core.validators import RegexValidator,validate_email
|
||||||
|
|
||||||
|
class StandardCollection(models.Model):
|
||||||
|
name = models.CharField(max_length=150)
|
||||||
|
manager = models.ForeignKey(User, null=True,on_delete=models.CASCADE)
|
||||||
|
notes = models.CharField(blank=True,null=True,max_length=1000)
|
||||||
|
active = models.BooleanField(default=True)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
class CourseStandard(models.Model):
|
||||||
|
name = models.CharField(max_length=150)
|
||||||
|
coursedistance = models.IntegerField()
|
||||||
|
coursetime = models.CharField(max_length=100,default="")
|
||||||
|
referencespeed = models.FloatField() # average boat speed
|
||||||
|
agemin = models.IntegerField(default=0)
|
||||||
|
agemax = models.IntegerField(default=120)
|
||||||
|
boatclass = models.CharField(max_length=150) # corresponds to workout workouttype
|
||||||
|
boattype = models.CharField(choices=mytypes.boattypes,max_length=50,default='1x')
|
||||||
|
sex = models.CharField(max_length=150)
|
||||||
|
weightclass = models.CharField(max_length=150)
|
||||||
|
adaptiveclass = models.CharField(choices=mytypes.adaptivetypes,max_length=50,default="None")
|
||||||
|
skillclass = models.CharField(max_length=150)
|
||||||
|
standardcollection = models.ForeignKey(StandardCollection,on_delete=models.CASCADE)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
unique_together = (
|
||||||
|
('name','standardcollection')
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
registerchoices = (
|
registerchoices = (
|
||||||
('windowstart','Start of challenge Window'),
|
('windowstart','Start of challenge Window'),
|
||||||
@@ -2233,6 +2253,9 @@ class VirtualRace(PlannedSession):
|
|||||||
contact_email = models.EmailField(max_length=254,
|
contact_email = models.EmailField(max_length=254,
|
||||||
validators=[validate_email],blank=True)
|
validators=[validate_email],blank=True)
|
||||||
|
|
||||||
|
coursestandards = models.ForeignKey(StandardCollection,null=True,on_delete=models.SET_NULL,
|
||||||
|
verbose_name='Standard Times',blank=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
name = self.name
|
name = self.name
|
||||||
@@ -2401,6 +2424,7 @@ class IndoorVirtualRaceForm(ModelForm):
|
|||||||
'registration_closure',
|
'registration_closure',
|
||||||
'evaluation_closure',
|
'evaluation_closure',
|
||||||
'comment',
|
'comment',
|
||||||
|
'coursestandards',
|
||||||
'contact_phone',
|
'contact_phone',
|
||||||
'contact_email',
|
'contact_email',
|
||||||
]
|
]
|
||||||
@@ -2434,6 +2458,7 @@ class IndoorVirtualRaceForm(ModelForm):
|
|||||||
self.fields['sessionunit'].initial = 'm'
|
self.fields['sessionunit'].initial = 'm'
|
||||||
if timezone:
|
if timezone:
|
||||||
self.fields['timezone'].initial = timezone
|
self.fields['timezone'].initial = timezone
|
||||||
|
self.fields['coursestandards'].queryset = StandardCollection.objects.filter(active=True)
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cd = self.cleaned_data
|
cd = self.cleaned_data
|
||||||
@@ -2537,6 +2562,7 @@ class VirtualRaceForm(ModelForm):
|
|||||||
'registration_closure',
|
'registration_closure',
|
||||||
'evaluation_closure',
|
'evaluation_closure',
|
||||||
'course',
|
'course',
|
||||||
|
'coursestandards',
|
||||||
'comment',
|
'comment',
|
||||||
'contact_phone',
|
'contact_phone',
|
||||||
'contact_email',
|
'contact_email',
|
||||||
@@ -2560,6 +2586,7 @@ class VirtualRaceForm(ModelForm):
|
|||||||
def __init__(self,*args,**kwargs):
|
def __init__(self,*args,**kwargs):
|
||||||
super(VirtualRaceForm, self).__init__(*args, **kwargs)
|
super(VirtualRaceForm, self).__init__(*args, **kwargs)
|
||||||
self.fields['course'].queryset = GeoCourse.objects.all().order_by("country","name")
|
self.fields['course'].queryset = GeoCourse.objects.all().order_by("country","name")
|
||||||
|
self.fields['coursestandards'].queryset = StandardCollection.objects.filter(active=True)
|
||||||
|
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
@@ -2905,9 +2932,12 @@ class VirtualRaceResult(models.Model):
|
|||||||
adaptiveclass = models.CharField(default="None",max_length=50,
|
adaptiveclass = models.CharField(default="None",max_length=50,
|
||||||
choices=mytypes.adaptivetypes,
|
choices=mytypes.adaptivetypes,
|
||||||
verbose_name="Adaptive Class")
|
verbose_name="Adaptive Class")
|
||||||
|
skillclass = models.CharField(default="Open",max_length=50,
|
||||||
|
verbose_name="Skill Class")
|
||||||
race = models.ForeignKey(VirtualRace,on_delete=models.CASCADE)
|
race = models.ForeignKey(VirtualRace,on_delete=models.CASCADE)
|
||||||
duration = models.TimeField(default=datetime.time(1,0))
|
duration = models.TimeField(default=datetime.time(1,0))
|
||||||
distance = models.IntegerField(default=0)
|
distance = models.IntegerField(default=0)
|
||||||
|
points = models.IntegerField(default=0)
|
||||||
boatclass = models.CharField(choices=boatclasses,
|
boatclass = models.CharField(choices=boatclasses,
|
||||||
max_length=40,
|
max_length=40,
|
||||||
default='water',
|
default='water',
|
||||||
@@ -2928,6 +2958,9 @@ class VirtualRaceResult(models.Model):
|
|||||||
|
|
||||||
startsecond = models.FloatField(default=0)
|
startsecond = models.FloatField(default=0)
|
||||||
endsecond = models.FloatField(default=0)
|
endsecond = models.FloatField(default=0)
|
||||||
|
referencespeed = models.FloatField(default=5.0)
|
||||||
|
entrycategory = models.ForeignKey(CourseStandard,null=True,on_delete=models.SET_NULL,
|
||||||
|
verbose_name='Group')
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
rr = Rower.objects.get(id=self.userid)
|
rr = Rower.objects.get(id=self.userid)
|
||||||
@@ -2936,6 +2969,14 @@ class VirtualRaceResult(models.Model):
|
|||||||
u2 = rr.user.last_name,
|
u2 = rr.user.last_name,
|
||||||
)
|
)
|
||||||
if self.teamname:
|
if self.teamname:
|
||||||
|
if self.entrycategory:
|
||||||
|
return u'Entry for {n} for "{r}" in {g} with {t}'.format(
|
||||||
|
n = name,
|
||||||
|
r = self.race,
|
||||||
|
g = self.entrycategory,
|
||||||
|
t = self.teamname,
|
||||||
|
)
|
||||||
|
|
||||||
return u'Entry for {n} for "{r}" in {c} {d} with {t} ({s})'.format(
|
return u'Entry for {n} for "{r}" in {c} {d} with {t} ({s})'.format(
|
||||||
n = name,
|
n = name,
|
||||||
r = self.race,
|
r = self.race,
|
||||||
@@ -2945,6 +2986,12 @@ class VirtualRaceResult(models.Model):
|
|||||||
s = self.sex,
|
s = self.sex,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
if self.entrycategory:
|
||||||
|
return u'Entry for {n} for "{r}" in {g}'.format(
|
||||||
|
n = name,
|
||||||
|
r = self.race,
|
||||||
|
g = self.entrycategory,
|
||||||
|
)
|
||||||
return u'Entry for {n} for "{r}" in {c} {d} ({s})'.format(
|
return u'Entry for {n} for "{r}" in {c} {d} ({s})'.format(
|
||||||
n = name,
|
n = name,
|
||||||
r = self.race,
|
r = self.race,
|
||||||
@@ -2968,9 +3015,13 @@ class IndoorVirtualRaceResult(models.Model):
|
|||||||
adaptiveclass = models.CharField(default="None",max_length=50,
|
adaptiveclass = models.CharField(default="None",max_length=50,
|
||||||
choices=mytypes.adaptivetypes,
|
choices=mytypes.adaptivetypes,
|
||||||
verbose_name="Adaptive Class")
|
verbose_name="Adaptive Class")
|
||||||
|
skillclass = models.CharField(default="Open",max_length=50,
|
||||||
|
verbose_name="Skill Class")
|
||||||
race = models.ForeignKey(VirtualRace,on_delete=models.CASCADE)
|
race = models.ForeignKey(VirtualRace,on_delete=models.CASCADE)
|
||||||
duration = models.TimeField(default=datetime.time(1,0))
|
duration = models.TimeField(default=datetime.time(1,0))
|
||||||
distance = models.IntegerField(default=0)
|
distance = models.IntegerField(default=0)
|
||||||
|
referencespeed = models.FloatField(default=5.0)
|
||||||
|
points = models.IntegerField(default=0)
|
||||||
boatclass = models.CharField(choices=boatclasses,
|
boatclass = models.CharField(choices=boatclasses,
|
||||||
max_length=40,
|
max_length=40,
|
||||||
default='rower',
|
default='rower',
|
||||||
@@ -2984,6 +3035,8 @@ class IndoorVirtualRaceResult(models.Model):
|
|||||||
age = models.IntegerField(null=True)
|
age = models.IntegerField(null=True)
|
||||||
emailnotifications = models.BooleanField(default=True,
|
emailnotifications = models.BooleanField(default=True,
|
||||||
verbose_name = 'Receive challenge notifications by email')
|
verbose_name = 'Receive challenge notifications by email')
|
||||||
|
entrycategory = models.ForeignKey(CourseStandard,null=True,on_delete=models.SET_NULL,
|
||||||
|
verbose_name='Group')
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
rr = Rower.objects.get(id=self.userid)
|
rr = Rower.objects.get(id=self.userid)
|
||||||
@@ -2992,6 +3045,13 @@ class IndoorVirtualRaceResult(models.Model):
|
|||||||
u2 = rr.user.last_name,
|
u2 = rr.user.last_name,
|
||||||
)
|
)
|
||||||
if self.teamname:
|
if self.teamname:
|
||||||
|
if self.entrycategory:
|
||||||
|
return u'Entry for {n} for "{r}" in {g} with {t}'.format(
|
||||||
|
n = name,
|
||||||
|
r = self.race,
|
||||||
|
g = self.entrycategory,
|
||||||
|
t = self.teamname,
|
||||||
|
)
|
||||||
return u'Entry for {n} for "{r}" on {c} with {t} ({s})'.format(
|
return u'Entry for {n} for "{r}" on {c} with {t} ({s})'.format(
|
||||||
n = name,
|
n = name,
|
||||||
r = self.race,
|
r = self.race,
|
||||||
@@ -3000,6 +3060,12 @@ class IndoorVirtualRaceResult(models.Model):
|
|||||||
s = self.sex,
|
s = self.sex,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
if self.entrycategory:
|
||||||
|
return u'Entry for {n} for "{r}" in {g}'.format(
|
||||||
|
n = name,
|
||||||
|
r = self.race,
|
||||||
|
g = self.entrycategory,
|
||||||
|
)
|
||||||
return u'Entry for {n} for "{r}" on {c} ({s})'.format(
|
return u'Entry for {n} for "{r}" on {c} ({s})'.format(
|
||||||
n = name,
|
n = name,
|
||||||
r = self.race,
|
r = self.race,
|
||||||
@@ -3019,22 +3085,29 @@ class CourseTestResult(models.Model):
|
|||||||
class IndoorVirtualRaceResultForm(ModelForm):
|
class IndoorVirtualRaceResultForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = IndoorVirtualRaceResult
|
model = IndoorVirtualRaceResult
|
||||||
fields = ['teamname','weightcategory','boatclass','age','adaptiveclass']
|
fields = ['teamname','weightcategory','boatclass','age','adaptiveclass',
|
||||||
|
'entrycategory']
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
categories = kwargs.pop('categories',None)
|
||||||
super(IndoorVirtualRaceResultForm, self).__init__(*args, **kwargs)
|
super(IndoorVirtualRaceResultForm, self).__init__(*args, **kwargs)
|
||||||
|
if categories is not None:
|
||||||
|
self.fields['entrycategory'].queryset = categories
|
||||||
|
self.fields['entrycategory'].empty_label = None
|
||||||
|
else:
|
||||||
|
self.fields.pop('entrycategory')
|
||||||
|
|
||||||
class VirtualRaceResultForm(ModelForm):
|
class VirtualRaceResultForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = VirtualRaceResult
|
model = VirtualRaceResult
|
||||||
fields = ['teamname','weightcategory','boatclass','boattype',
|
fields = ['teamname','weightcategory','boatclass','boattype',
|
||||||
'age','adaptiveclass']
|
'age','adaptiveclass','entrycategory']
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
boattypes = kwargs.pop('boattypes',None)
|
boattypes = kwargs.pop('boattypes',None)
|
||||||
|
categories = kwargs.pop('categories',None)
|
||||||
super(VirtualRaceResultForm, self).__init__(*args, **kwargs)
|
super(VirtualRaceResultForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
if boattypes:
|
if boattypes:
|
||||||
@@ -3044,6 +3117,12 @@ class VirtualRaceResultForm(ModelForm):
|
|||||||
required=False,
|
required=False,
|
||||||
label='Mixed Gender')
|
label='Mixed Gender')
|
||||||
|
|
||||||
|
if categories is not None:
|
||||||
|
self.fields['entrycategory'].queryset = categories
|
||||||
|
self.fields['entrycategory'].empty_label = None
|
||||||
|
else:
|
||||||
|
self.fields.pop('entrycategory')
|
||||||
|
|
||||||
from rowers.metrics import rowingmetrics
|
from rowers.metrics import rowingmetrics
|
||||||
|
|
||||||
strokedatafields = {
|
strokedatafields = {
|
||||||
|
|||||||
+11
-1
@@ -316,13 +316,23 @@ boattypes = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
adaptivetypes = (
|
adaptivetypes = (
|
||||||
('None','None'),
|
('None','Open'),
|
||||||
('PR1', 'PR1 (Arms and Shoulders)'),
|
('PR1', 'PR1 (Arms and Shoulders)'),
|
||||||
('PR2', 'PR2 (Trunk and Arms)'),
|
('PR2', 'PR2 (Trunk and Arms)'),
|
||||||
('PR3', 'PR3 (Leg Trunk and Arms)'),
|
('PR3', 'PR3 (Leg Trunk and Arms)'),
|
||||||
('FES', 'FES (Functional Electrical Stimulation)'),
|
('FES', 'FES (Functional Electrical Stimulation)'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
weightcategories = (
|
||||||
|
('hwt','open-weight'),
|
||||||
|
('lwt','light-weight'),
|
||||||
|
)
|
||||||
|
|
||||||
|
sexcategories = (
|
||||||
|
('male','Open'),
|
||||||
|
('female','Female'),
|
||||||
|
)
|
||||||
|
|
||||||
waterboattype = [i[0] for i in boattypes]
|
waterboattype = [i[0] for i in boattypes]
|
||||||
|
|
||||||
privacychoices = (
|
privacychoices = (
|
||||||
|
|||||||
@@ -1514,6 +1514,7 @@ def add_workout_race(ws,race,r,splitsecond=0,recordid=0):
|
|||||||
return 0,comments,errors,0
|
return 0,comments,errors,0
|
||||||
|
|
||||||
if ws[0].workouttype != record.boatclass:
|
if ws[0].workouttype != record.boatclass:
|
||||||
|
print(ws[0].workouttype,record.boatclass)
|
||||||
errors.append('Your workout boat class is different than on your race registration')
|
errors.append('Your workout boat class is different than on your race registration')
|
||||||
return 0,comments,errors,0
|
return 0,comments,errors,0
|
||||||
|
|
||||||
@@ -1551,7 +1552,8 @@ def add_workout_race(ws,race,r,splitsecond=0,recordid=0):
|
|||||||
comments.append('Workouts submitted to virtual events have to be public. We have changed the workout to a public workout.')
|
comments.append('Workouts submitted to virtual events have to be public. We have changed the workout to a public workout.')
|
||||||
|
|
||||||
job = myqueue(queue,handle_check_race_course,ws[0].csvfilename,
|
job = myqueue(queue,handle_check_race_course,ws[0].csvfilename,
|
||||||
ws[0].id,race.course.id,record.id,splitsecond=splitsecond)
|
ws[0].id,race.course.id,record.id,splitsecond=splitsecond,
|
||||||
|
referencespeed=record.referencespeed,coursedistance=race.course.distance)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,177 @@
|
|||||||
|
from rowers.models import StandardCollection,CourseStandard, VirtualRaceResult,IndoorVirtualRaceResult
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
import arrow
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
def save_scoring(name,user,filename,id=0,notes=""):
|
||||||
|
if id==0:
|
||||||
|
collection = StandardCollection(name=name,manager=user,notes=notes)
|
||||||
|
collection.save()
|
||||||
|
standards = CourseStandard.objects.filter(standardcollection=collection)
|
||||||
|
for standard in standards:
|
||||||
|
standards.delete()
|
||||||
|
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
collection = StandardCollection.objects.get(id=id)
|
||||||
|
collection.name = name
|
||||||
|
collection.notes = notes
|
||||||
|
collection.save()
|
||||||
|
standards = CourseStandard.objects.filter(standardcollection=collection)
|
||||||
|
for standard in standards:
|
||||||
|
records1 = VirtualRaceResult.objects.filter(entrycategory=standard)
|
||||||
|
records2 = IndoorVirtualRaceResult.objects.filter(entrycategory=standard)
|
||||||
|
if records1.count()+records2.count() == 0:
|
||||||
|
standard.delete()
|
||||||
|
|
||||||
|
|
||||||
|
except StandardCollection.DoesNotExist:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
df = pd.read_csv(filename)
|
||||||
|
except:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
df.rename(
|
||||||
|
columns={
|
||||||
|
'name':'Name',
|
||||||
|
'agemax':'MaxAge',
|
||||||
|
'agemin':'MinAge',
|
||||||
|
'adaptiveclass':'AdaptiveClass',
|
||||||
|
'coursedistance':'CourseDistance',
|
||||||
|
'coursetime':'CourseStandard',
|
||||||
|
'boatclass':'BoatClass',
|
||||||
|
'boattype':'BoatType',
|
||||||
|
'sex':'Gender',
|
||||||
|
'weightclass':'WeightClass',
|
||||||
|
'skillclass':'SkillClass',
|
||||||
|
},
|
||||||
|
inplace=True)
|
||||||
|
|
||||||
|
df = df.drop_duplicates(['Name'])
|
||||||
|
|
||||||
|
for index, row in df.iterrows():
|
||||||
|
try:
|
||||||
|
name = row['Name']
|
||||||
|
except KeyError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
coursedistance = row['CourseDistance']
|
||||||
|
coursetime = row['CourseStandard']
|
||||||
|
t = datetime.datetime.strptime(coursetime,'%M:%S.%f')
|
||||||
|
delta = datetime.timedelta(hours=t.hour, minutes=t.minute, seconds=t.second,microseconds=t.microsecond)
|
||||||
|
seconds = delta.total_seconds()
|
||||||
|
|
||||||
|
referencespeed = coursedistance/seconds
|
||||||
|
except KeyError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
agemin = row['MinAge']
|
||||||
|
agemax = row['MaxAge']
|
||||||
|
agemin = int(agemin)
|
||||||
|
agemax = int(agemax)
|
||||||
|
except KeyError:
|
||||||
|
agemin = 0
|
||||||
|
agemax = 120
|
||||||
|
|
||||||
|
try:
|
||||||
|
boatclass = row['BoatClass']
|
||||||
|
if boatclass.lower() in ['standard','olympic','normal','water']:
|
||||||
|
boatclass = 'water'
|
||||||
|
elif boatclass.lower() in ['erg','c2','concept','static','rower']:
|
||||||
|
boatclass = 'rower'
|
||||||
|
elif boatclass.lower() in ['dynamic']:
|
||||||
|
boatclass = 'dynamic'
|
||||||
|
elif boatclass.lower() in ['slides','slide','slider','sliders']:
|
||||||
|
boatclass = 'slides'
|
||||||
|
elif boatclass.lower() in ['c','c-boat']:
|
||||||
|
boatclass = 'c-boat'
|
||||||
|
elif boatclass.lower() in ['coastal','coast']:
|
||||||
|
boatclass = 'coastal'
|
||||||
|
elif boatclass.lower() in ['church','churchboat','finnish','finland']:
|
||||||
|
boatclass = 'churchboat'
|
||||||
|
except KeyError:
|
||||||
|
boatclass = 'water'
|
||||||
|
|
||||||
|
try:
|
||||||
|
boattype = row['BoatType']
|
||||||
|
except KeyError:
|
||||||
|
boattype = '1x'
|
||||||
|
|
||||||
|
try:
|
||||||
|
sex = row['Gender']
|
||||||
|
if sex.lower() in ['m','men','male','open']:
|
||||||
|
sex = 'male'
|
||||||
|
elif sex.lower() in ['mix','mixed']:
|
||||||
|
sex = 'mixed'
|
||||||
|
else:
|
||||||
|
sex = 'female'
|
||||||
|
except KeyError:
|
||||||
|
sex = 'female'
|
||||||
|
|
||||||
|
try:
|
||||||
|
weightclass = row['WeightClass']
|
||||||
|
if weightclass.lower() in ['hwt','h','o','heavy','open']:
|
||||||
|
weightclass = 'hwt'
|
||||||
|
elif weightclass.lower() in ['lwt','l','light','lights','lighties']:
|
||||||
|
weightclass = 'lwt'
|
||||||
|
except KeyError:
|
||||||
|
weightclass = 'hwt'
|
||||||
|
|
||||||
|
adaptiveclass = 'None'
|
||||||
|
try:
|
||||||
|
adaptiveclass = row['AdaptiveClass']
|
||||||
|
if adaptiveclass.lower() in ['o','open','none','no']:
|
||||||
|
adaptiveclass = 'None'
|
||||||
|
except KeyError:
|
||||||
|
adaptiveclass = 'None'
|
||||||
|
|
||||||
|
try:
|
||||||
|
skillclass = row['SkillClass']
|
||||||
|
except KeyError:
|
||||||
|
skillclass = 'Open'
|
||||||
|
|
||||||
|
# finding existing standard
|
||||||
|
existingstandards = CourseStandard.objects.filter(name=name,standardcollection=collection)
|
||||||
|
#print(existingstandards,collection)
|
||||||
|
if existingstandards:
|
||||||
|
existingstandards.update(
|
||||||
|
name=name,
|
||||||
|
coursedistance=coursedistance,
|
||||||
|
referencespeed=referencespeed,
|
||||||
|
coursetime=coursetime,
|
||||||
|
agemin=agemin,
|
||||||
|
agemax=agemax,
|
||||||
|
boatclass=boatclass,
|
||||||
|
boattype=boattype,
|
||||||
|
sex=sex,
|
||||||
|
weightclass=weightclass,
|
||||||
|
adaptiveclass=adaptiveclass,
|
||||||
|
skillclass=skillclass,
|
||||||
|
standardcollection = collection,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
#print('not')
|
||||||
|
standard = CourseStandard(
|
||||||
|
name=name,
|
||||||
|
coursedistance=coursedistance,
|
||||||
|
referencespeed=referencespeed,
|
||||||
|
coursetime=coursetime,
|
||||||
|
agemin=agemin,
|
||||||
|
agemax=agemax,
|
||||||
|
boatclass=boatclass,
|
||||||
|
boattype=boattype,
|
||||||
|
sex=sex,
|
||||||
|
weightclass=weightclass,
|
||||||
|
adaptiveclass=adaptiveclass,
|
||||||
|
skillclass=skillclass,
|
||||||
|
standardcollection = collection,
|
||||||
|
)
|
||||||
|
|
||||||
|
standard.save()
|
||||||
|
|
||||||
|
return collection.id
|
||||||
+19
-3
@@ -353,6 +353,16 @@ def handle_check_race_course(self,
|
|||||||
else:
|
else:
|
||||||
splitsecond = 0
|
splitsecond = 0
|
||||||
|
|
||||||
|
if 'referencespeed' in kwargs:
|
||||||
|
referencespeed = kwargs['referencespeed']
|
||||||
|
else:
|
||||||
|
referencespeed = 5.0
|
||||||
|
|
||||||
|
if 'coursedistance' in kwargs:
|
||||||
|
coursedistance = kwargs['coursedistance']
|
||||||
|
else:
|
||||||
|
coursedistance = 0
|
||||||
|
|
||||||
mode = 'race'
|
mode = 'race'
|
||||||
if 'mode' in kwargs:
|
if 'mode' in kwargs:
|
||||||
mode = kwargs['mode']
|
mode = kwargs['mode']
|
||||||
@@ -479,22 +489,28 @@ def handle_check_race_course(self,
|
|||||||
else:
|
else:
|
||||||
coursecompleted = False
|
coursecompleted = False
|
||||||
|
|
||||||
|
points = 0
|
||||||
if coursecompleted:
|
if coursecompleted:
|
||||||
query = 'UPDATE rowers_virtualraceresult SET coursecompleted = 1, duration = "{duration}", distance = {distance}, workoutid = {workoutid}, startsecond = {startsecond}, endsecond = {endsecond} WHERE id={recordid}'.format(
|
if coursedistance == 0:
|
||||||
|
coursedistance = coursemeters
|
||||||
|
velo = coursedistance/coursetimeseconds
|
||||||
|
points = int(100*(2.-referencespeed/velo))
|
||||||
|
query = 'UPDATE rowers_virtualraceresult SET coursecompleted = 1, duration = "{duration}", distance = {distance}, workoutid = {workoutid}, startsecond = {startsecond}, endsecond = {endsecond}, points={points} WHERE id={recordid}'.format(
|
||||||
recordid=recordid,
|
recordid=recordid,
|
||||||
duration=totaltime_sec_to_string(coursetimeseconds),
|
duration=totaltime_sec_to_string(coursetimeseconds),
|
||||||
distance=int(coursemeters),
|
distance=int(coursemeters),
|
||||||
|
points=points,
|
||||||
workoutid=workoutid,
|
workoutid=workoutid,
|
||||||
startsecond=startsecond,
|
startsecond=startsecond,
|
||||||
endsecond=endsecond,
|
endsecond=endsecond,
|
||||||
)
|
)
|
||||||
|
|
||||||
if mode == 'coursetest':
|
if mode == 'coursetest':
|
||||||
query = 'UPDATE rowers_coursetestresult SET coursecompleted = 1, duration = "{duration}", distance = {distance}, workoutid = {workoutid}, startsecond = {startsecond}, endsecond = {endsecond} WHERE id={recordid}'.format(
|
query = 'UPDATE rowers_coursetestresult SET coursecompleted = 1, duration = "{duration}", distance = {distance}, workoutid = {workoutid}, startsecond = {startsecond}, endsecond = {endsecond}, points={points} WHERE id={recordid}'.format(
|
||||||
recordid=recordid,
|
recordid=recordid,
|
||||||
duration=totaltime_sec_to_string(coursetimeseconds),
|
duration=totaltime_sec_to_string(coursetimeseconds),
|
||||||
distance=int(coursemeters),
|
distance=int(coursemeters),
|
||||||
|
points=points,
|
||||||
workoutid=workoutid,
|
workoutid=workoutid,
|
||||||
startsecond=startsecond,
|
startsecond=startsecond,
|
||||||
endsecond=endsecond,
|
endsecond=endsecond,
|
||||||
|
|||||||
@@ -160,6 +160,13 @@
|
|||||||
};
|
};
|
||||||
});});
|
});});
|
||||||
|
|
||||||
|
$('textarea').each(function( i ) {
|
||||||
|
$(this).change(function() {
|
||||||
|
data.set($(this).attr('name'),$(this).val());
|
||||||
|
console.log($(this).attr('name'),$(this).val());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
$('select').each(function( i ) {
|
$('select').each(function( i ) {
|
||||||
console.log($(this).attr('name'),$(this).val());
|
console.log($(this).attr('name'),$(this).val());
|
||||||
$(this).change(function() {
|
$(this).change(function() {
|
||||||
|
|||||||
@@ -55,6 +55,15 @@
|
|||||||
If you require a screenshot of the PM monitor, do mention this
|
If you require a screenshot of the PM monitor, do mention this
|
||||||
in the comment.
|
in the comment.
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
Standard Times are a way to compare results in a race category with
|
||||||
|
a course record or golden standard for that event. A point score is calculated
|
||||||
|
which compares the participant's result with the standard. This offers an
|
||||||
|
engaging way to compete on points across different categories, boat types, and skill
|
||||||
|
levels.
|
||||||
|
If you select a Standard Times set from the drop-down list, race categories will
|
||||||
|
be limited to those in the selected set of Standard Times.
|
||||||
|
</p>
|
||||||
</ul>
|
</ul>
|
||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
{% extends "newbase.html" %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
{% load rowerfilters %}
|
||||||
|
|
||||||
|
{% block title %}Rowsandall Course Standards List{% endblock %}
|
||||||
|
|
||||||
|
{% block scripts %}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
<style>
|
||||||
|
#mypointer {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h1>Standards Collections</h1>
|
||||||
|
|
||||||
|
<ul class="main-content">
|
||||||
|
<li class="grid_3">
|
||||||
|
{% if standards %}
|
||||||
|
<p>
|
||||||
|
<table width="100%" class="listtable shortpadded">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th> Name</th>
|
||||||
|
<th> Maintainer</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for standard in standards %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ standard.name }} </td>
|
||||||
|
<td>{{ standard.manager.first_name }} {{ standard.manager.last_name }}</td>
|
||||||
|
<td>
|
||||||
|
{% if standard.manager == user %}
|
||||||
|
<a href="/rowers/standards/{{ standard.id }}/">{{ standard.name }}</a>
|
||||||
|
{% else %}
|
||||||
|
<a href="/rowers/standards/{{ standard.id }}/">{{ standard.name }}</a>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</p>
|
||||||
|
{% else %}
|
||||||
|
<p> No standards found </p>
|
||||||
|
{% endif %}
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
<form id="searchform" action="/rowers/list-standards/"
|
||||||
|
method="get" accept-charset="utf-8">
|
||||||
|
{{ searchform }}
|
||||||
|
<input type="submit" value="GO"></input>
|
||||||
|
</form>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="/rowers/standards/upload/">Add Standards</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="grid_4">
|
||||||
|
<h2>How-to</h2>
|
||||||
|
<p>
|
||||||
|
A set of Course Standard Times allows you to calculate a score for
|
||||||
|
each participant on how well they have done against the course
|
||||||
|
standard time for their category. This allows for comparison
|
||||||
|
and competition between the different categories.
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block sidebar %}
|
||||||
|
{% include 'menu_racing.html' %}
|
||||||
|
{% endblock %}
|
||||||
@@ -55,12 +55,14 @@
|
|||||||
<i class="fas fa-file-upload fa-fw"></i> Upload your Challenge result
|
<i class="fas fa-file-upload fa-fw"></i> Upload your Challenge result
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
{% if race.sessiontype != 'race' %}
|
||||||
<li>
|
<li>
|
||||||
<a href="/rowers/workout/addmanual/">
|
<a href="/rowers/workout/addmanual/{{ race.id }}/">
|
||||||
<i class="fas fa-file-plus fa-fw"></i> Enter Result
|
<i class="fas fa-file-plus fa-fw"></i> Enter Result
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
{% if button == 'resubmitbutton' %}
|
{% if button == 'resubmitbutton' %}
|
||||||
<li>
|
<li>
|
||||||
<a href="/rowers/virtualevent/{{ race.id }}/submit/">Submit New Result</a>
|
<a href="/rowers/virtualevent/{{ race.id }}/submit/">Submit New Result</a>
|
||||||
@@ -131,6 +133,11 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<li id="standards">
|
||||||
|
<a href="/rowers/list-standards/">
|
||||||
|
<i class="fas fa-award fa-fw"></i> Course Time Standards
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
</ul> <!-- cd-accordion-menu -->
|
</ul> <!-- cd-accordion-menu -->
|
||||||
|
|
||||||
{% include 'menuscript.html' %}
|
{% include 'menuscript.html' %}
|
||||||
|
|||||||
@@ -0,0 +1,276 @@
|
|||||||
|
{% extends "newbase.html" %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
{% load rowerfilters %}
|
||||||
|
|
||||||
|
{% block title %}File loading{% endblock %}
|
||||||
|
|
||||||
|
{% block meta %}
|
||||||
|
<script type='text/javascript'
|
||||||
|
src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js'>
|
||||||
|
</script>
|
||||||
|
<script type='text/javascript'
|
||||||
|
src='https://ajax.aspnetcdn.com/ajax/jquery.validate/1.14.0/jquery.validate.min.js'>
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
<h1>Upload Course Standard Times File</h1>
|
||||||
|
|
||||||
|
<ul class="main-content">
|
||||||
|
<li class="grid_4">
|
||||||
|
<div id="id_dropregion watermark invisible">
|
||||||
|
<p>Drag and drop files here.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If you're updating an existing set of standard times,
|
||||||
|
existing groups with challenge entries will be updated. New
|
||||||
|
groups will be created. All groups with challenge entries will
|
||||||
|
remain, even if you delete them from the CSV file. So, it
|
||||||
|
is not possible to remove groups if there have been starts in this group.</p>
|
||||||
|
<p>
|
||||||
|
If you want to still remove those groups, it is better to set the
|
||||||
|
existing set of standard times to inactive and upload a new one.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div id="id_drop-files" class="grid_12 alpha drop-files">
|
||||||
|
<form id="file_form" enctype="multipart/form-data" method="post">
|
||||||
|
{% if form.errors %}
|
||||||
|
<p style="color: red;">
|
||||||
|
Please correct the error{{ form.errors|pluralize }} below.
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<table>
|
||||||
|
{{ form.as_table }}
|
||||||
|
</table>
|
||||||
|
{% csrf_token %}
|
||||||
|
<p>
|
||||||
|
<input type="submit" value="Submit">
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block sidebar %}
|
||||||
|
{% include 'menu_racing.html' %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block scripts %}
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
|
||||||
|
<script>
|
||||||
|
var td = new FormData();
|
||||||
|
var formdatasetok = false;
|
||||||
|
try {
|
||||||
|
td.set('aap','noot');
|
||||||
|
formdatasetok = true;
|
||||||
|
console.log('FormData.set OK');
|
||||||
|
}
|
||||||
|
catch(err) {
|
||||||
|
console.log('FormData.set not OK');
|
||||||
|
formdatasetok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!formdatasetok) {
|
||||||
|
$("#id_dropregion").remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formdatasetok) {
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
|
||||||
|
console.log("CSRF token",csrftoken);
|
||||||
|
|
||||||
|
function csrfSafeMethod(method) {
|
||||||
|
// these HTTP methods do not require CSRF protection
|
||||||
|
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
|
||||||
|
}
|
||||||
|
$.ajaxSetup({
|
||||||
|
beforeSend: function(xhr, settings) {
|
||||||
|
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
|
||||||
|
xhr.setRequestHeader("X-CSRFToken", csrftoken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log("Loading dropper");
|
||||||
|
jQuery.event.props.push('dataTransfer');
|
||||||
|
|
||||||
|
$(window).on('dragenter', function() {
|
||||||
|
$("#id_drop-files").css("background-color","#E9E9E4");
|
||||||
|
$("#id_dropregion").addClass("watermark").removeClass("invisible");})
|
||||||
|
|
||||||
|
$(window).on('dragleave', function() {
|
||||||
|
$("#id_drop-files").css("background-color","#FFFFFF");
|
||||||
|
$("#id_dropregion").removeClass("watermark").addClass("invisible");})
|
||||||
|
|
||||||
|
var frm = $("#file_form");
|
||||||
|
|
||||||
|
if( window.FormData === undefined ) {
|
||||||
|
console.log('no formdata');
|
||||||
|
alert("No FormData");
|
||||||
|
} else {
|
||||||
|
console.log('we have formdata');
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = new FormData(frm[0]);
|
||||||
|
|
||||||
|
|
||||||
|
$('#id_file').on('change', function(evt) {
|
||||||
|
var f = this.files[0];
|
||||||
|
console.log(f);
|
||||||
|
var istcx = false;
|
||||||
|
var isgzip = false;
|
||||||
|
var size1 = 10485760;
|
||||||
|
var size2 = 1048576;
|
||||||
|
if ((/\.(tcx|TCX)/i).test(f.name)) {
|
||||||
|
istcx = true;
|
||||||
|
console.log('tcx');
|
||||||
|
if ((/\.(gz|GZ)/i).test(f.name)) {
|
||||||
|
isgzip = true;
|
||||||
|
console.log('gzip');
|
||||||
|
size1 /= 5;
|
||||||
|
size2 /= 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(size1)
|
||||||
|
console.log(size2)
|
||||||
|
if (f.size > size1) {
|
||||||
|
alert("File Size must be smaller than 10 MB");
|
||||||
|
this.value = null;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (f.size > size2) {
|
||||||
|
$('#id_offline').val('True');
|
||||||
|
$('#id_offline').prop('checked','True');
|
||||||
|
data.set($('#id_offline').attr('name'),$('#id_offline').prop('checked'));
|
||||||
|
console.log("Set offline to True");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
$('input').each(function( i ) {
|
||||||
|
$(this).change(function() {
|
||||||
|
if ($(this).attr('type') == 'checkbox') {
|
||||||
|
data.set($(this).attr('name'),$(this).prop('checked'));
|
||||||
|
console.log($(this).attr('id'),$(this).attr('name'),$(this).attr('notes'),$(this).prop('checked'));
|
||||||
|
} else {
|
||||||
|
data.set($(this).attr('name'),$(this).val());
|
||||||
|
if ($(this).attr('id') == 'id_file') {
|
||||||
|
data.set("file",this.files[0]);
|
||||||
|
}
|
||||||
|
console.log($(this).attr('name'),$(this).val());
|
||||||
|
};
|
||||||
|
});});
|
||||||
|
|
||||||
|
$('textarea').each(function( i ) {
|
||||||
|
$(this).change(function() {
|
||||||
|
data.set($(this).attr('name'),$(this).val());
|
||||||
|
console.log($(this).attr('name'),$(this).val());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$('select').each(function( i ) {
|
||||||
|
console.log($(this).attr('name'),$(this).val());
|
||||||
|
$(this).change(function() {
|
||||||
|
data.set($(this).attr('name'),$(this).val());
|
||||||
|
console.log($(this).attr('id'),$(this).attr('name'),$(this).val());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
frm.submit(function() {
|
||||||
|
console.log("Form submission");
|
||||||
|
$(data.values()).each(function(value) {
|
||||||
|
console.log(value);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#id_drop-files").replaceWith(
|
||||||
|
'<div id="id_waiting"><img src="/static/img/rowingtimer.gif" width="60" height="50" style="width:60px">'
|
||||||
|
);
|
||||||
|
$.ajax({
|
||||||
|
data: data,
|
||||||
|
type: $(this).attr('method'),
|
||||||
|
url: window.location.pathname,
|
||||||
|
contentType: false,
|
||||||
|
processData: false,
|
||||||
|
error: function(result) {
|
||||||
|
$("#id_waiting").replaceWith(
|
||||||
|
'<div id="id_failed" class="grid_12 alpha message">Your upload failed</div>'
|
||||||
|
);
|
||||||
|
setTimeout(function() {
|
||||||
|
location.reload();
|
||||||
|
},1000);
|
||||||
|
},
|
||||||
|
success: function(result) {
|
||||||
|
console.log('got something back');
|
||||||
|
console.log(result);
|
||||||
|
if (result.result == 1) {
|
||||||
|
window.location.href = result.url;
|
||||||
|
} else {
|
||||||
|
console.log(result," reloading");
|
||||||
|
location.reload();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$('#id_drop-files').bind({
|
||||||
|
drop: function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
console.log("you dropped something");
|
||||||
|
var files = e.dataTransfer.files;
|
||||||
|
console.log(files[0]);
|
||||||
|
|
||||||
|
var f = files[0];
|
||||||
|
var istcx = false;
|
||||||
|
var isgzip = false;
|
||||||
|
var size1 = 10485760;
|
||||||
|
var size2 = 1048576;
|
||||||
|
if ((/\.(tcx|TCX)/i).test(f.name)) {
|
||||||
|
istcx = true;
|
||||||
|
console.log('tcx');
|
||||||
|
if ((/\.(gz|GZ)/i).test(f.name)) {
|
||||||
|
isgzip = true;
|
||||||
|
console.log('gzip');
|
||||||
|
size1 /= 5;
|
||||||
|
size2 /= 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(f);
|
||||||
|
console.log(size1)
|
||||||
|
console.log(size2)
|
||||||
|
if (f.size > size1) {
|
||||||
|
alert("File Size must be smaller than 10 MB");
|
||||||
|
$("#id_file").value = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
data.set("file",f);
|
||||||
|
// data.append("file",f);
|
||||||
|
|
||||||
|
$("#id_file").replaceWith('<div id="id_file">'+files[0].name+' <a class="remove" href="javascript:void(0);"><b><font color="red">X</font></b></a></div>');
|
||||||
|
},
|
||||||
|
mouseenter:function(){$("#id_drop-files").css("background-color","#E9E9E4");},
|
||||||
|
mouseleave:function(){$("#id_drop-files").css("background-color","#FFFFFF");},
|
||||||
|
dragover:function(e){
|
||||||
|
e.preventDefault();
|
||||||
|
$("#id_drop-files").css("background-color","#E9E9E4");},
|
||||||
|
dragleave:function(e){ e.preventDefault();},
|
||||||
|
});
|
||||||
|
$(document).on("click", "a.remove", function() {
|
||||||
|
$(this).parent().replaceWith('<td><input id="id_file" name="file" type="file" /></td>');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
{% extends "newbase.html" %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
{% load rowerfilters %}
|
||||||
|
{% load leaflet_tags %}
|
||||||
|
|
||||||
|
{% block meta %}
|
||||||
|
{% leaflet_js %}
|
||||||
|
{% leaflet_css %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block scripts %}
|
||||||
|
{% include "monitorjobs.html" %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block title %}{{ standard.name }} {% endblock %}
|
||||||
|
{% block og_title %}{{ standard.name }} {% endblock %}
|
||||||
|
{% block main %}
|
||||||
|
|
||||||
|
<h1>{{ standard.name }}</h1>
|
||||||
|
|
||||||
|
<ul class="main-content">
|
||||||
|
<li class="grid_2">
|
||||||
|
<table class="listtable shortpadded" width="100%">
|
||||||
|
<tr>
|
||||||
|
<th>Name</th><td>{{ collection.name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Manager</th><td>{{ collection.manager.first_name }} {{ collection.manager.last_name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Notes</th><td>{{ collection.notes|linebreaks }}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
{% if request.user == collection.manager %}
|
||||||
|
<p><a href="/rowers/standards/upload/{{ collection.id }}/">Update these Standard Times</a></p>
|
||||||
|
<p><a href="/rowers/standards/{{ collection.id }}/deactivate/">Deactivate this standard</a></p>
|
||||||
|
{% endif %}
|
||||||
|
<p><a href="/rowers/standards/{{ collection.id }}/download/">Download as CSV file</a></p>
|
||||||
|
</li>
|
||||||
|
<li class="grid_4">
|
||||||
|
<h2>Standard Times</h2>
|
||||||
|
<table class="listtable shortpadded" width="100%"?
|
||||||
|
<tr>
|
||||||
|
<th>Name<a href="?order_by=name">▲</a><a href="?order_by=-name">▼</a></th>
|
||||||
|
<th>Distance<a href="?order_by=coursedistance">▲</a><a href="?order_by=-coursedistance">▼</a></th>
|
||||||
|
<th>Standard Time<a href="?order_by=coursetime">▲</a><a href="?order_by=-coursetime">▼</a></th>
|
||||||
|
<th>Boat Class<a href="?order_by=boatclass">▲</a><a href="?order_by=-boatclass">▼</a></th>
|
||||||
|
<th>Boat Type<a href="?order_by=boattype">▲</a><a href="?order_by=-boattype">▼</a></th>
|
||||||
|
<th>Gender<a href="?order_by=sex">▲</a><a href="?order_by=-sex">▼</a></th>
|
||||||
|
<th>Weight Class<a href="?order_by=weightclass">▲</a><a href="?order_by=-weightclass">▼</a></th>
|
||||||
|
<th>Adaptive Class<a href="?order_by=adaptiveclass">▲</a><a href="?order_by=-adaptiveclass">▼</a></th>
|
||||||
|
<th>Skill Class<a href="?order_by=skillclass">▲</a><a href="?order_by=-skillclass">▼</a></th>
|
||||||
|
<th>Minimum<a href="?order_by=agemin">▲</a><a href="?order_by=-agemin">▼</a>/Maximum Age<a href="?order_by=agemax">▲</a><a href="?order_by=-agemax">▼</a></th>
|
||||||
|
</tr>
|
||||||
|
{% for standard in standards %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ standard.name }}</td>
|
||||||
|
<td>{{ standard.coursedistance }}</td>
|
||||||
|
<td>{{ standard.coursetime }}</td>
|
||||||
|
<td>{{ standard.boatclass|boatclass }}</td>
|
||||||
|
<td>{{ standard.boattype }}</td>
|
||||||
|
<td>{{ standard.sex|sex }}</td>
|
||||||
|
<td>{{ standard.weightclass|weight }}</td>
|
||||||
|
<td>{{ standard.adaptiveclass|adaptive }}</td>
|
||||||
|
<td>{{ standard.skillclass }}</td>
|
||||||
|
<td>{{ standard.agemin }}/{{ standard.agemax }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block sidebar %}
|
||||||
|
{% include 'menu_racing.html' %}
|
||||||
|
{% endblock %}
|
||||||
@@ -104,6 +104,11 @@
|
|||||||
<th>Challenge Time Zone</th><td>{{ race.timezone }}</td>
|
<th>Challenge Time Zone</th><td>{{ race.timezone }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if race.coursestandards %}
|
||||||
|
<tr>
|
||||||
|
<th>Standard Times</th><td><a href="/rowers/standards/{{ race.coursestandards.id }}/">{{ race.coursestandards }}</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{{ race.sessionmode }} challenge
|
{{ race.sessionmode }} challenge
|
||||||
@@ -263,7 +268,9 @@
|
|||||||
<th> </th>
|
<th> </th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Team Name</th>
|
<th>Team Name</th>
|
||||||
<th> </th>
|
{% if race.coursestandards %}
|
||||||
|
<th>Group</th>
|
||||||
|
{% else %}
|
||||||
<th> </th>
|
<th> </th>
|
||||||
<th> </th>
|
<th> </th>
|
||||||
<th> </th>
|
<th> </th>
|
||||||
@@ -271,8 +278,12 @@
|
|||||||
{% if race.sessiontype == 'race' %}
|
{% if race.sessiontype == 'race' %}
|
||||||
<th>Boat</th>
|
<th>Boat</th>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<th>Time</th>
|
{% endif %}
|
||||||
<th>Distance</th>
|
<th>Time<a href="?order_by=duration">▼</th>
|
||||||
|
<th>Distance<a href="?order_by=-distance">▼</th>
|
||||||
|
{% if race.coursestandards %}
|
||||||
|
<th>Points<a href="?order_by=-points">▼</a></th>
|
||||||
|
{% endif %}
|
||||||
<th>Details</th>
|
<th>Details</th>
|
||||||
<th> </th>
|
<th> </th>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -285,6 +296,9 @@
|
|||||||
<a href="/rowers/workout/{{ result.workoutid|encode }}/view/entry/{{ result.id }}/">
|
<a href="/rowers/workout/{{ result.workoutid|encode }}/view/entry/{{ result.id }}/">
|
||||||
{{ result.username }}</a></td>
|
{{ result.username }}</a></td>
|
||||||
<td>{{ result.teamname }}</td>
|
<td>{{ result.teamname }}</td>
|
||||||
|
{% if race.coursestandards %}
|
||||||
|
<td>{{ result.entrycategory }}</td>
|
||||||
|
{% else %}
|
||||||
<td>{{ result.age }}</td>
|
<td>{{ result.age }}</td>
|
||||||
<td>{{ result.sex }}</td>
|
<td>{{ result.sex }}</td>
|
||||||
<td>{{ result.weightcategory }}</td>
|
<td>{{ result.weightcategory }}</td>
|
||||||
@@ -299,11 +313,17 @@
|
|||||||
{% if race.sessiontype == 'race' %}
|
{% if race.sessiontype == 'race' %}
|
||||||
<td>{{ result.boattype }}</td>
|
<td>{{ result.boattype }}</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
<td>{{ result.duration |durationprint:"%H:%M:%S.%f" }}</td>
|
<td>{{ result.duration |durationprint:"%H:%M:%S.%f" }}</td>
|
||||||
<td>{{ result.distance }} m</td>
|
<td>{{ result.distance }} m</td>
|
||||||
|
{% if race.coursestandards %}
|
||||||
|
<td>{{ result.points }}</td>
|
||||||
|
{% endif %}
|
||||||
<td>
|
<td>
|
||||||
<a href="/rowers/workout/{{ result.workoutid|encode }}/view/entry/{{ result.id }}/">
|
<a href="/rowers/workout/{{ result.workoutid|encode }}/view/entry/{{ result.id }}/">
|
||||||
Details</a></td>
|
Details</a>
|
||||||
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
{% if race.manager == request.user and not race|is_final %}
|
{% if race.manager == request.user and not race|is_final %}
|
||||||
<a href="/rowers/virtualevent/{{ race.id }}/disqualify/{{ result.id }}/">
|
<a href="/rowers/virtualevent/{{ race.id }}/disqualify/{{ result.id }}/">
|
||||||
@@ -389,22 +409,29 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Team Name</th>
|
<th>Team Name</th>
|
||||||
{% if race.sessiontype == 'race' %}
|
{% if race.coursestandards %}
|
||||||
<th>Class</th>
|
<th>Group</th>
|
||||||
<th>Boat</th>
|
<th>Age</th>
|
||||||
{% else %}
|
{% else %}
|
||||||
<th>Class</th>
|
{% if race.sessiontype == 'race' %}
|
||||||
|
<th>Boat</th>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<th>Class</th>
|
||||||
<th>Age</th>
|
<th>Age</th>
|
||||||
<th>Gender</th>
|
<th>Gender</th>
|
||||||
<th>Weight Category</th>
|
<th>Weight Category</th>
|
||||||
<th>Adaptive</th>
|
<th>Adaptive</th>
|
||||||
|
{% endif %}
|
||||||
</tr>
|
</tr>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for record in records %}
|
{% for record in records %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ record.username }}
|
<td>{{ record.username }}
|
||||||
<td>{{ record.teamname }}</td>
|
<td>{{ record.teamname }}</td>
|
||||||
|
{% if race.coursestandards %}
|
||||||
|
<td>{{ record.entrycategory }}</td>
|
||||||
|
<td>{{ record.age }}</td>
|
||||||
|
{% else %}
|
||||||
<td>{{ record.boatclass }}</td>
|
<td>{{ record.boatclass }}</td>
|
||||||
{% if race.sessiontype == 'race' %}
|
{% if race.sessiontype == 'race' %}
|
||||||
<td>{{ record.boattype }}</td>
|
<td>{{ record.boattype }}</td>
|
||||||
@@ -419,6 +446,7 @@
|
|||||||
{{ record.adaptiveclass }}
|
{{ record.adaptiveclass }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
|
{% endif %}
|
||||||
{% if record.userid == rower.id and 'withdrawbutton' in buttons %}
|
{% if record.userid == rower.id and 'withdrawbutton' in buttons %}
|
||||||
<td>
|
<td>
|
||||||
<a href="/rowers/virtualevent/{{ race.id }}/withdraw/{{ record.id }}" >Withdraw</a>
|
<a href="/rowers/virtualevent/{{ race.id }}/withdraw/{{ record.id }}" >Withdraw</a>
|
||||||
@@ -431,7 +459,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% for record in records %}
|
{% for record in records %}
|
||||||
{% if record.userid == request.user.rower.id %}
|
{% if record.userid == request.user.rower.id and forloop.counter == 1 %}
|
||||||
{% if race.sessiontype == 'race' %}
|
{% if race.sessiontype == 'race' %}
|
||||||
{% if record.emailnotifications %}
|
{% if record.emailnotifications %}
|
||||||
<a href="/rowers/raceregistration/togglenotification/{{ race.id }}">
|
<a href="/rowers/raceregistration/togglenotification/{{ race.id }}">
|
||||||
@@ -541,6 +569,17 @@
|
|||||||
review and reject entries. If you are disqualified in this
|
review and reject entries. If you are disqualified in this
|
||||||
way, you will receive an email with the reason.
|
way, you will receive an email with the reason.
|
||||||
</p>
|
</p>
|
||||||
|
{% if race.coursestandards %}
|
||||||
|
<p>
|
||||||
|
Standard Times are a way to compare results in a race category with
|
||||||
|
a course record or golden standard for that event. A point score is calculated
|
||||||
|
which compares the participant's result with the standard. This offers an
|
||||||
|
engaging way to compete on points across different categories, boat types, and skill
|
||||||
|
levels.
|
||||||
|
If you select a Standard Times set from the drop-down list, race categories will
|
||||||
|
be limited to those in the selected set of Standard Times.
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -49,6 +49,15 @@
|
|||||||
is strongly recommended that you fill out a contact email or phone
|
is strongly recommended that you fill out a contact email or phone
|
||||||
number.
|
number.
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
Standard Times are a way to compare results in a race category with
|
||||||
|
a course record or golden standard for that event. A point score is calculated
|
||||||
|
which compares the participant's result with the standard. This offers an
|
||||||
|
engaging way to compete on points across different categories, boat types, and skill
|
||||||
|
levels.
|
||||||
|
If you select a Standard Times set from the drop-down list, race categories will
|
||||||
|
be limited to those in the selected set of Standard Times.
|
||||||
|
</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,16 @@
|
|||||||
as a Male crew. Check the "Mixed gender" check box to register as a
|
as a Male crew. Check the "Mixed gender" check box to register as a
|
||||||
mixed gender crew (except for 1x where this check box does nothing).
|
mixed gender crew (except for 1x where this check box does nothing).
|
||||||
</p>
|
</p>
|
||||||
|
{% if race.coursestandards %}
|
||||||
|
<p>This race uses standard times and limits the race groups to those where
|
||||||
|
standard times exist. The "Group" form choice will overrule other selections you
|
||||||
|
make in the form (boat type, weight, etc) and your entry will be rejected
|
||||||
|
if the age and gender doesn't match.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
You can check the valid race groups and standard times <a target="_" href="/rowers/standards/{{ race.coursestandards.id }}/">here</a>.
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
<div class="grid_6 alpha">
|
<div class="grid_6 alpha">
|
||||||
<table width="100%">
|
<table width="100%">
|
||||||
{{ form.as_table }}
|
{{ form.as_table }}
|
||||||
|
|||||||
@@ -22,7 +22,9 @@ from rowers import c2stuff, runkeeperstuff
|
|||||||
from rowers.c2stuff import c2_open
|
from rowers.c2stuff import c2_open
|
||||||
from rowers.runkeeperstuff import runkeeper_open
|
from rowers.runkeeperstuff import runkeeper_open
|
||||||
from rowers.rower_rules import is_coach_user, is_workout_user, isplanmember,ispromember
|
from rowers.rower_rules import is_coach_user, is_workout_user, isplanmember,ispromember
|
||||||
from rowers.mytypes import otwtypes
|
from rowers.mytypes import (
|
||||||
|
otwtypes,adaptivetypes,sexcategories,weightcategories,workouttypes,
|
||||||
|
)
|
||||||
from rowers.utils import NoTokenError
|
from rowers.utils import NoTokenError
|
||||||
|
|
||||||
import rowers.payments as payments
|
import rowers.payments as payments
|
||||||
@@ -38,6 +40,50 @@ from django.template.defaultfilters import stringfilter
|
|||||||
|
|
||||||
from six import string_types
|
from six import string_types
|
||||||
|
|
||||||
|
@register.filter
|
||||||
|
def adaptive(s):
|
||||||
|
u = s
|
||||||
|
|
||||||
|
for e,v in adaptivetypes:
|
||||||
|
if e.lower() == u.lower():
|
||||||
|
u = v
|
||||||
|
continue
|
||||||
|
|
||||||
|
return u
|
||||||
|
|
||||||
|
@register.filter
|
||||||
|
def boatclass(s):
|
||||||
|
u = s
|
||||||
|
|
||||||
|
for e,v in workouttypes:
|
||||||
|
if e.lower() == u.lower():
|
||||||
|
u = v
|
||||||
|
continue
|
||||||
|
|
||||||
|
return u
|
||||||
|
|
||||||
|
@register.filter
|
||||||
|
def sex(s):
|
||||||
|
u = s
|
||||||
|
|
||||||
|
for e,v in sexcategories:
|
||||||
|
if e.lower() == u.lower():
|
||||||
|
u = v
|
||||||
|
continue
|
||||||
|
|
||||||
|
return u
|
||||||
|
|
||||||
|
@register.filter
|
||||||
|
def weight(s):
|
||||||
|
u = s
|
||||||
|
|
||||||
|
for e,v in weightcategories:
|
||||||
|
if e.lower() == u.lower():
|
||||||
|
u = v
|
||||||
|
continue
|
||||||
|
|
||||||
|
return u
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def sigdig(value, digits = 3):
|
def sigdig(value, digits = 3):
|
||||||
try:
|
try:
|
||||||
|
|||||||
+9
-1
@@ -201,8 +201,11 @@ urlpatterns = [
|
|||||||
views.virtualevent_results_download_view,name='virtualevent_results_download_view'),
|
views.virtualevent_results_download_view,name='virtualevent_results_download_view'),
|
||||||
re_path(r'^list-workouts/$',views.workouts_view,name='workouts_view'),
|
re_path(r'^list-workouts/$',views.workouts_view,name='workouts_view'),
|
||||||
re_path(r'^list-courses/$',views.courses_view,name='courses_view'),
|
re_path(r'^list-courses/$',views.courses_view,name='courses_view'),
|
||||||
|
re_path(r'^list-standards/$',views.standards_view,name='standards_view'),
|
||||||
re_path(r'^courses/upload/$',views.course_upload_view,name='course_upload_view'),
|
re_path(r'^courses/upload/$',views.course_upload_view,name='course_upload_view'),
|
||||||
re_path(r'^workout/addmanual/(?P<raceid>\d+)$',views.addmanual_view,name='addmanual_view'),
|
re_path(r'^standards/upload/$',views.standards_upload_view,name='standards_upload_view'),
|
||||||
|
re_path(r'^standards/upload/(?P<id>\d+)/$',views.standards_upload_view,name='standards_upload_view'),
|
||||||
|
re_path(r'^workout/addmanual/(?P<raceid>\d+)/$',views.addmanual_view,name='addmanual_view'),
|
||||||
re_path(r'^workout/addmanual/$',views.addmanual_view,name='addmanual_view'),
|
re_path(r'^workout/addmanual/$',views.addmanual_view,name='addmanual_view'),
|
||||||
re_path(r'^team-compare-select/workout/(?P<id>\d+)/team/(?P<teamid>\d+)/user/(?P<userid>\d+)/$',views.team_comparison_select,name='team_comparison_select'),
|
re_path(r'^team-compare-select/workout/(?P<id>\d+)/team/(?P<teamid>\d+)/user/(?P<userid>\d+)/$',views.team_comparison_select,name='team_comparison_select'),
|
||||||
# re_path(r'^team-compare-select/team/(?P<teamid>\d+)/(?P<startdatestring>\d+-\d+-\d+)/(?P<enddatestring>\d+-\d+-\d+)/user/(?P<userid>\d+)/$',views.team_comparison_select,name='team_comparison_select'),
|
# re_path(r'^team-compare-select/team/(?P<teamid>\d+)/(?P<startdatestring>\d+-\d+-\d+)/(?P<enddatestring>\d+-\d+-\d+)/user/(?P<userid>\d+)/$',views.team_comparison_select,name='team_comparison_select'),
|
||||||
@@ -752,6 +755,11 @@ urlpatterns = [
|
|||||||
re_path(r'^courses/(?P<id>\d+)/replace/$',views.course_replace_view,
|
re_path(r'^courses/(?P<id>\d+)/replace/$',views.course_replace_view,
|
||||||
name='course_replace_view'),
|
name='course_replace_view'),
|
||||||
re_path(r'^courses/(?P<id>\d+)/$',views.course_view,name='course_view'),
|
re_path(r'^courses/(?P<id>\d+)/$',views.course_view,name='course_view'),
|
||||||
|
re_path(r'^standards/(?P<id>\d+)/$',views.standard_view,name='standard_view'),
|
||||||
|
re_path(r'^standards/(?P<id>\d+)/download/$',views.standards_download_view,
|
||||||
|
name='standards_download_view'),
|
||||||
|
re_path(r'^standards/(?P<id>\d+)/deactivate/$',views.standard_deactivate_view,
|
||||||
|
name='standard_decativate_view'),
|
||||||
re_path(r'^courses/(?P<id>\d+)/map/$',views.course_map_view,name='course_map_view'),
|
re_path(r'^courses/(?P<id>\d+)/map/$',views.course_map_view,name='course_map_view'),
|
||||||
# URLS to be created
|
# URLS to be created
|
||||||
re_path(r'^help/$',TemplateView.as_view(template_name='help.html'), name='help'),
|
re_path(r'^help/$',TemplateView.as_view(template_name='help.html'), name='help'),
|
||||||
|
|||||||
+368
-16
@@ -5,6 +5,7 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
from rowers.views.statements import *
|
from rowers.views.statements import *
|
||||||
from rowsandall_app.settings import SITE_URL
|
from rowsandall_app.settings import SITE_URL
|
||||||
|
from rowers.scoring import *
|
||||||
|
|
||||||
# List Courses
|
# List Courses
|
||||||
def courses_view(request):
|
def courses_view(request):
|
||||||
@@ -35,6 +36,35 @@ def courses_view(request):
|
|||||||
'rower':r,
|
'rower':r,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# List Courses
|
||||||
|
def standards_view(request):
|
||||||
|
r = getrower(request.user)
|
||||||
|
|
||||||
|
standards = StandardCollection.objects.filter(active=True).order_by("name")
|
||||||
|
|
||||||
|
# add search processing
|
||||||
|
query = request.GET.get('q')
|
||||||
|
if query:
|
||||||
|
query_list = query.split()
|
||||||
|
standards = StandardCollection.objects.filter(
|
||||||
|
reduce(operator.and_,
|
||||||
|
(Q(name__icontains=q) for q in query_list)) |
|
||||||
|
reduce(operator.and_,
|
||||||
|
(Q(notes__icontains=q) for q in query_list))
|
||||||
|
)
|
||||||
|
searchform = SearchForm(initial={'q':query})
|
||||||
|
else:
|
||||||
|
searchform = SearchForm()
|
||||||
|
|
||||||
|
|
||||||
|
return render(request,'list_standards.html',
|
||||||
|
{'standards':standards,
|
||||||
|
'active':'nav-racing',
|
||||||
|
'searchform':searchform,
|
||||||
|
'rower':r,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# for ajax calls
|
# for ajax calls
|
||||||
def course_map_view(request,id=0):
|
def course_map_view(request,id=0):
|
||||||
@@ -249,6 +279,50 @@ def course_view(request,id=0):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def standard_view(request,id=0):
|
||||||
|
try:
|
||||||
|
collection = StandardCollection.objects.get(id=id)
|
||||||
|
except StandardCollection.DoesNotExist:
|
||||||
|
return Http404("Standard Collection does not exist")
|
||||||
|
|
||||||
|
r = getrower(request.user)
|
||||||
|
|
||||||
|
orderby = request.GET.get('order_by')
|
||||||
|
|
||||||
|
if orderby is not None:
|
||||||
|
standards = CourseStandard.objects.filter(
|
||||||
|
standardcollection=collection
|
||||||
|
).order_by(orderby,"-referencespeed","agemax","agemin","sex","name")
|
||||||
|
else:
|
||||||
|
standards = CourseStandard.objects.filter(
|
||||||
|
standardcollection=collection
|
||||||
|
).order_by("-referencespeed","agemax","agemin","sex","name")
|
||||||
|
|
||||||
|
breadcrumbs = [
|
||||||
|
{
|
||||||
|
'url': reverse('virtualevents_view'),
|
||||||
|
'name': 'Challenges'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'url': reverse(standards_view),
|
||||||
|
'name': 'Standards'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'url': reverse(standard_view,kwargs={'id':collection.id}),
|
||||||
|
'name': collection.name
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
return render(request, 'standard_view.html',
|
||||||
|
{
|
||||||
|
'active':'nav-racing',
|
||||||
|
'breadcrumbs':breadcrumbs,
|
||||||
|
'collection':collection,
|
||||||
|
'standards':standards,
|
||||||
|
'rower':r,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
@login_required()
|
@login_required()
|
||||||
@permission_required('racelogo.delete_logo',fn=get_logo_by_pk,raise_exception=True)
|
@permission_required('racelogo.delete_logo',fn=get_logo_by_pk,raise_exception=True)
|
||||||
def logo_delete_view(request,id=0):
|
def logo_delete_view(request,id=0):
|
||||||
@@ -387,7 +461,7 @@ def virtualevent_uploadimage_view(request,id=0):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
# Image upload
|
# Course upload
|
||||||
@login_required()
|
@login_required()
|
||||||
def course_upload_view(request):
|
def course_upload_view(request):
|
||||||
is_ajax = False
|
is_ajax = False
|
||||||
@@ -447,6 +521,125 @@ def course_upload_view(request):
|
|||||||
else:
|
else:
|
||||||
return {'result':0}
|
return {'result':0}
|
||||||
|
|
||||||
|
# Standards deactivate
|
||||||
|
@login_required()
|
||||||
|
def standard_deactivate_view(request,id=0):
|
||||||
|
is_ajax = False
|
||||||
|
if request.is_ajax():
|
||||||
|
is_ajax = True
|
||||||
|
|
||||||
|
r = getrower(request.user)
|
||||||
|
|
||||||
|
try:
|
||||||
|
collection = StandardCollection.objects.get(id=id)
|
||||||
|
except StandardCollection.DoesNotExist:
|
||||||
|
raise Http404("Does not exist")
|
||||||
|
|
||||||
|
if request.user != collection.manager:
|
||||||
|
raise PermissionDenied("You cannot change this set of time standards")
|
||||||
|
|
||||||
|
collection.active = False
|
||||||
|
collection.save()
|
||||||
|
|
||||||
|
url = reverse(standards_view)
|
||||||
|
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
def standards_download_view(request,id=0):
|
||||||
|
try:
|
||||||
|
collection = StandardCollection.objects.get(id=id)
|
||||||
|
except StandardCollection.DoesNotExist:
|
||||||
|
raise Http404("Does not exist")
|
||||||
|
|
||||||
|
filename = 'Standard Times {name} {id} {date}.csv'.format(
|
||||||
|
id=id,
|
||||||
|
name=collection.name,
|
||||||
|
date=timezone.now().strftime("%Y-%m-%d %H:%M:%S %Z")
|
||||||
|
)
|
||||||
|
|
||||||
|
standards = CourseStandard.objects.filter(standardcollection=collection)
|
||||||
|
df = pd.DataFrame.from_records(standards.values())
|
||||||
|
|
||||||
|
response = HttpResponse(df.to_csv())
|
||||||
|
|
||||||
|
response['Content-Disposition'] = 'attachment; filename="%s"' % filename
|
||||||
|
response['Content-Type'] = 'application/octet-stream'
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
# Standards upload
|
||||||
|
@login_required()
|
||||||
|
def standards_upload_view(request,id=0):
|
||||||
|
is_ajax = False
|
||||||
|
if request.is_ajax():
|
||||||
|
is_ajax = True
|
||||||
|
r = getrower(request.user)
|
||||||
|
|
||||||
|
if id != 0:
|
||||||
|
collection = StandardCollection.objects.get(id=id)
|
||||||
|
if request.user != collection.manager:
|
||||||
|
raise PermissionDenied("You cannot change this set of time standards")
|
||||||
|
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = StandardsForm(request.POST,request.FILES)
|
||||||
|
|
||||||
|
if form.is_valid():
|
||||||
|
f = form.cleaned_data['file']
|
||||||
|
name = form.cleaned_data['name']
|
||||||
|
notes = form.cleaned_data['notes']
|
||||||
|
if f is not None:
|
||||||
|
filename,path_and_filename = handle_uploaded_file(f)
|
||||||
|
|
||||||
|
id = save_scoring(name,request.user,path_and_filename,notes=notes,id=id)
|
||||||
|
|
||||||
|
|
||||||
|
os.remove(path_and_filename)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if id==0:
|
||||||
|
url = reverse(standards_view)
|
||||||
|
else:
|
||||||
|
url = reverse(standard_view,kwargs={'id':id})
|
||||||
|
|
||||||
|
if is_ajax:
|
||||||
|
return JSONResponse({'result':1,'url':url})
|
||||||
|
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
else:
|
||||||
|
messages.error(request,'Something went wrong - no file attached')
|
||||||
|
url = reverse(standards_upload_view)
|
||||||
|
if is_ajax:
|
||||||
|
return JSONResponse({'result':0,'url':0})
|
||||||
|
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
else:
|
||||||
|
messages.error(request,'Form is not valid')
|
||||||
|
return render(request,'standard_form.html',
|
||||||
|
{'form':form,
|
||||||
|
'active':'nav-racing',
|
||||||
|
'id':id,
|
||||||
|
})
|
||||||
|
|
||||||
|
else:
|
||||||
|
if not is_ajax:
|
||||||
|
form = StandardsForm()
|
||||||
|
if id != 0:
|
||||||
|
collection = StandardCollection.objects.get(id=id)
|
||||||
|
form = StandardsForm(initial={
|
||||||
|
'name':collection.name,
|
||||||
|
'notes': collection.notes,
|
||||||
|
})
|
||||||
|
return render(request,'standard_form.html',
|
||||||
|
{'form':form,
|
||||||
|
'active':'nav-racing',
|
||||||
|
'id':id,
|
||||||
|
})
|
||||||
|
return {'result':0}
|
||||||
|
|
||||||
|
|
||||||
def virtualevents_view(request):
|
def virtualevents_view(request):
|
||||||
is_ajax = False
|
is_ajax = False
|
||||||
@@ -523,7 +716,6 @@ def virtualevents_view(request):
|
|||||||
country__in=countries
|
country__in=countries
|
||||||
).order_by("startdate","start_time")
|
).order_by("startdate","start_time")
|
||||||
else:
|
else:
|
||||||
|
|
||||||
form = VirtualRaceSelectForm()
|
form = VirtualRaceSelectForm()
|
||||||
|
|
||||||
if is_ajax:
|
if is_ajax:
|
||||||
@@ -935,6 +1127,11 @@ def virtualevent_view(request,id=0):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
adaptiveclass = ['None','PR1','PR2','PR3','FES']
|
adaptiveclass = ['None','PR1','PR2','PR3','FES']
|
||||||
|
|
||||||
|
try:
|
||||||
|
entrycategory = cd['entrycategory']
|
||||||
|
except KeyError:
|
||||||
|
entrycategory = None
|
||||||
|
|
||||||
if race.sessiontype == 'race':
|
if race.sessiontype == 'race':
|
||||||
results = resultobj.objects.filter(
|
results = resultobj.objects.filter(
|
||||||
race=race,
|
race=race,
|
||||||
@@ -945,7 +1142,7 @@ def virtualevent_view(request,id=0):
|
|||||||
weightcategory__in=weightcategory,
|
weightcategory__in=weightcategory,
|
||||||
adaptiveclass__in=adaptiveclass,
|
adaptiveclass__in=adaptiveclass,
|
||||||
age__gte=age_min,
|
age__gte=age_min,
|
||||||
age__lte=age_max
|
age__lte=age_max,
|
||||||
).order_by("duration")
|
).order_by("duration")
|
||||||
else:
|
else:
|
||||||
results = resultobj.objects.filter(
|
results = resultobj.objects.filter(
|
||||||
@@ -956,9 +1153,11 @@ def virtualevent_view(request,id=0):
|
|||||||
weightcategory__in=weightcategory,
|
weightcategory__in=weightcategory,
|
||||||
adaptiveclass__in=adaptiveclass,
|
adaptiveclass__in=adaptiveclass,
|
||||||
age__gte=age_min,
|
age__gte=age_min,
|
||||||
age__lte=age_max
|
age__lte=age_max,
|
||||||
).order_by("duration","-distance")
|
).order_by("duration","-distance")
|
||||||
|
|
||||||
|
if entrycategory is not None:
|
||||||
|
results = results.filter(entrycategory__in=entrycategory)
|
||||||
|
|
||||||
# to-do - add DNS
|
# to-do - add DNS
|
||||||
dns = []
|
dns = []
|
||||||
@@ -985,8 +1184,6 @@ def virtualevent_view(request,id=0):
|
|||||||
else:
|
else:
|
||||||
form = None
|
form = None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
breadcrumbs = [
|
breadcrumbs = [
|
||||||
{
|
{
|
||||||
'url':reverse('virtualevents_view'),
|
'url':reverse('virtualevents_view'),
|
||||||
@@ -1000,6 +1197,10 @@ def virtualevent_view(request,id=0):
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
orderby = request.GET.get('order_by')
|
||||||
|
if orderby is not None:
|
||||||
|
results = results.order_by(orderby)
|
||||||
|
|
||||||
racelogos = race.logos.all()
|
racelogos = race.logos.all()
|
||||||
|
|
||||||
if racelogos:
|
if racelogos:
|
||||||
@@ -1278,6 +1479,12 @@ def virtualevent_addboat_view(request,id=0):
|
|||||||
except VirtualRace.DoesNotExist:
|
except VirtualRace.DoesNotExist:
|
||||||
raise Http404("Virtual Challenge does not exist")
|
raise Http404("Virtual Challenge does not exist")
|
||||||
|
|
||||||
|
categories = None
|
||||||
|
if race.coursestandards is not None:
|
||||||
|
categories = CourseStandard.objects.filter(
|
||||||
|
standardcollection=race.coursestandards).order_by("name")
|
||||||
|
|
||||||
|
|
||||||
if not race_can_adddiscipline(r,race):
|
if not race_can_adddiscipline(r,race):
|
||||||
messages.error(request,"You cannot register for this race")
|
messages.error(request,"You cannot register for this race")
|
||||||
|
|
||||||
@@ -1301,7 +1508,7 @@ def virtualevent_addboat_view(request,id=0):
|
|||||||
# we're still here
|
# we're still here
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
# process form
|
# process form
|
||||||
form = VirtualRaceResultForm(request.POST)
|
form = VirtualRaceResultForm(request.POST,categories=categories)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
cd = form.cleaned_data
|
cd = form.cleaned_data
|
||||||
teamname = cd['teamname']
|
teamname = cd['teamname']
|
||||||
@@ -1323,7 +1530,7 @@ def virtualevent_addboat_view(request,id=0):
|
|||||||
if sex == 'not specified':
|
if sex == 'not specified':
|
||||||
sex = 'male'
|
sex = 'male'
|
||||||
|
|
||||||
if boattype in boattypes and boatclass in boatclasses:
|
if boattype in boattypes and boatclass in boatclasses and race.coursestandards is None:
|
||||||
# check if different sexes
|
# check if different sexes
|
||||||
therecords = records.filter(
|
therecords = records.filter(
|
||||||
boattype=boattype,
|
boattype=boattype,
|
||||||
@@ -1344,6 +1551,49 @@ def virtualevent_addboat_view(request,id=0):
|
|||||||
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
coursestandard = None
|
||||||
|
referencespeed = 5.0
|
||||||
|
|
||||||
|
if race.coursestandards is not None:
|
||||||
|
coursestandard = cd['entrycategory']
|
||||||
|
thegroups = [record.entrycategory for record in records]
|
||||||
|
if coursestandard in thegroups:
|
||||||
|
messages.error(request,"You have already registered in that group")
|
||||||
|
url = reverse('virtualevent_view',
|
||||||
|
kwargs = {
|
||||||
|
'id': race.id
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
referencespeed = coursestandard.referencespeed
|
||||||
|
boattype = coursestandard.boattype
|
||||||
|
boatclass = coursestandard.boatclass
|
||||||
|
weightcategory = coursestandard.weightclass
|
||||||
|
adaptiveclass = coursestandard.adaptiveclass
|
||||||
|
skillclass = coursestandard.skillclass
|
||||||
|
|
||||||
|
returnurl = reverse(virtualevent_register_view,
|
||||||
|
kwargs={'id':race.id})
|
||||||
|
|
||||||
|
if age < coursestandard.agemin:
|
||||||
|
messages.error(request,'You are younger than the minimum age for this group')
|
||||||
|
return HttpResponseRedirect(returnurl)
|
||||||
|
|
||||||
|
if age > coursestandard.agemax:
|
||||||
|
messages.error(request,'You are older than the maximum age for this group')
|
||||||
|
return HttpResponseRedirect(returnurl)
|
||||||
|
|
||||||
|
if sex == 'male' and coursestandard.sex != 'male':
|
||||||
|
messages.error(request,'Men are not allowed to enter this category')
|
||||||
|
return HttpResponseRedirect(returnurl)
|
||||||
|
|
||||||
|
if sex == 'mixed' and coursestandard.sex not in ['mixed','male']:
|
||||||
|
messages.error(request,'Mixed crews are not allowed to enter this category')
|
||||||
|
return HttpResponseRedirect(returnurl)
|
||||||
|
|
||||||
|
|
||||||
record = VirtualRaceResult(
|
record = VirtualRaceResult(
|
||||||
userid=r.id,
|
userid=r.id,
|
||||||
teamname=teamname,
|
teamname=teamname,
|
||||||
@@ -1358,8 +1608,10 @@ def virtualevent_addboat_view(request,id=0):
|
|||||||
boattype=boattype,
|
boattype=boattype,
|
||||||
boatclass=boatclass,
|
boatclass=boatclass,
|
||||||
coursecompleted=False,
|
coursecompleted=False,
|
||||||
|
referencespeed=referencespeed,
|
||||||
|
entrycategory=coursestandard,
|
||||||
sex=sex,
|
sex=sex,
|
||||||
age=age
|
age=age,
|
||||||
)
|
)
|
||||||
|
|
||||||
record.save()
|
record.save()
|
||||||
@@ -1387,7 +1639,13 @@ def virtualevent_addboat_view(request,id=0):
|
|||||||
'adaptiveclass': r.adaptiveclass,
|
'adaptiveclass': r.adaptiveclass,
|
||||||
}
|
}
|
||||||
|
|
||||||
form = VirtualRaceResultForm(initial=initial)
|
categories = None
|
||||||
|
if race.coursestandards is not None:
|
||||||
|
categories = CourseStandard.objects.filter(
|
||||||
|
standardcollection=race.coursestandards).order_by("name")
|
||||||
|
|
||||||
|
|
||||||
|
form = VirtualRaceResultForm(initial=initial,categories=categories)
|
||||||
|
|
||||||
breadcrumbs = [
|
breadcrumbs = [
|
||||||
{
|
{
|
||||||
@@ -1448,6 +1706,11 @@ def virtualevent_register_view(request,id=0):
|
|||||||
except VirtualRace.DoesNotExist:
|
except VirtualRace.DoesNotExist:
|
||||||
raise Http404("Virtual Challenge does not exist")
|
raise Http404("Virtual Challenge does not exist")
|
||||||
|
|
||||||
|
categories = None
|
||||||
|
if race.coursestandards is not None:
|
||||||
|
categories = CourseStandard.objects.filter(
|
||||||
|
standardcollection=race.coursestandards).order_by("name")
|
||||||
|
|
||||||
if not race_can_register(r,race):
|
if not race_can_register(r,race):
|
||||||
messages.error(request,"You cannot register for this race")
|
messages.error(request,"You cannot register for this race")
|
||||||
|
|
||||||
@@ -1461,7 +1724,7 @@ def virtualevent_register_view(request,id=0):
|
|||||||
# we're still here
|
# we're still here
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
# process form
|
# process form
|
||||||
form = VirtualRaceResultForm(request.POST)
|
form = VirtualRaceResultForm(request.POST,categories=categories)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
cd = form.cleaned_data
|
cd = form.cleaned_data
|
||||||
teamname = cd['teamname']
|
teamname = cd['teamname']
|
||||||
@@ -1483,6 +1746,40 @@ def virtualevent_register_view(request,id=0):
|
|||||||
if sex == 'not specified':
|
if sex == 'not specified':
|
||||||
sex = 'male'
|
sex = 'male'
|
||||||
|
|
||||||
|
|
||||||
|
coursestandard = None
|
||||||
|
referencespeed = 5.0
|
||||||
|
|
||||||
|
if race.coursestandards is not None:
|
||||||
|
coursestandard = cd['entrycategory']
|
||||||
|
referencespeed = coursestandard.referencespeed
|
||||||
|
boattype = coursestandard.boattype
|
||||||
|
boatclass = coursestandard.boatclass
|
||||||
|
weightcategory = coursestandard.weightclass
|
||||||
|
adaptiveclass = coursestandard.adaptiveclass
|
||||||
|
skillclass = coursestandard.skillclass
|
||||||
|
|
||||||
|
returnurl = reverse(virtualevent_register_view,
|
||||||
|
kwargs={'id':race.id})
|
||||||
|
|
||||||
|
if age < coursestandard.agemin:
|
||||||
|
messages.error(request,'You are younger than the minimum age for this group')
|
||||||
|
return HttpResponseRedirect(returnurl)
|
||||||
|
|
||||||
|
if age > coursestandard.agemax:
|
||||||
|
messages.error(request,'You are older than the maximum age for this group')
|
||||||
|
return HttpResponseRedirect(returnurl)
|
||||||
|
|
||||||
|
if sex == 'male' and coursestandard.sex != 'male':
|
||||||
|
messages.error(request,'Men are not allowed to enter this category')
|
||||||
|
return HttpResponseRedirect(returnurl)
|
||||||
|
|
||||||
|
if sex == 'mixed' and coursestandard.sex not in ['mixed','male']:
|
||||||
|
messages.error(request,'Mixed crews are not allowed to enter this category')
|
||||||
|
return HttpResponseRedirect(returnurl)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
record = VirtualRaceResult(
|
record = VirtualRaceResult(
|
||||||
userid=r.id,
|
userid=r.id,
|
||||||
teamname=teamname,
|
teamname=teamname,
|
||||||
@@ -1498,7 +1795,9 @@ def virtualevent_register_view(request,id=0):
|
|||||||
boattype=boattype,
|
boattype=boattype,
|
||||||
coursecompleted=False,
|
coursecompleted=False,
|
||||||
sex=sex,
|
sex=sex,
|
||||||
age=age
|
age=age,
|
||||||
|
entrycategory=coursestandard,
|
||||||
|
referencespeed=referencespeed,
|
||||||
)
|
)
|
||||||
|
|
||||||
record.save()
|
record.save()
|
||||||
@@ -1542,7 +1841,12 @@ def virtualevent_register_view(request,id=0):
|
|||||||
'adaptiveclass': r.adaptiveclass,
|
'adaptiveclass': r.adaptiveclass,
|
||||||
}
|
}
|
||||||
|
|
||||||
form = VirtualRaceResultForm(initial=initial)
|
categories = None
|
||||||
|
if race.coursestandards is not None:
|
||||||
|
categories = CourseStandard.objects.filter(
|
||||||
|
standardcollection=race.coursestandards).order_by("name")
|
||||||
|
|
||||||
|
form = VirtualRaceResultForm(initial=initial,categories=categories)
|
||||||
|
|
||||||
breadcrumbs = [
|
breadcrumbs = [
|
||||||
{
|
{
|
||||||
@@ -1644,6 +1948,11 @@ def indoorvirtualevent_register_view(request,id=0):
|
|||||||
except VirtualRace.DoesNotExist:
|
except VirtualRace.DoesNotExist:
|
||||||
raise Http404("Virtual Challenge does not exist")
|
raise Http404("Virtual Challenge does not exist")
|
||||||
|
|
||||||
|
categories = None
|
||||||
|
if race.coursestandards is not None:
|
||||||
|
categories = CourseStandard.objects.filter(
|
||||||
|
standardcollection=race.coursestandards).order_by("name")
|
||||||
|
|
||||||
if not race_can_register(r,race):
|
if not race_can_register(r,race):
|
||||||
messages.error(request,"You cannot register for this race")
|
messages.error(request,"You cannot register for this race")
|
||||||
|
|
||||||
@@ -1657,7 +1966,7 @@ def indoorvirtualevent_register_view(request,id=0):
|
|||||||
# we're still here
|
# we're still here
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
# process form
|
# process form
|
||||||
form = IndoorVirtualRaceResultForm(request.POST)
|
form = IndoorVirtualRaceResultForm(request.POST,categories=categories)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
cd = form.cleaned_data
|
cd = form.cleaned_data
|
||||||
teamname = cd['teamname']
|
teamname = cd['teamname']
|
||||||
@@ -1675,6 +1984,38 @@ def indoorvirtualevent_register_view(request,id=0):
|
|||||||
if sex == 'not specified':
|
if sex == 'not specified':
|
||||||
sex = 'male'
|
sex = 'male'
|
||||||
|
|
||||||
|
coursestandard = None
|
||||||
|
referencespeed = 5.0
|
||||||
|
|
||||||
|
if race.coursestandards is not None:
|
||||||
|
coursestandard = cd['entrycategory']
|
||||||
|
referencespeed = coursestandard.referencespeed
|
||||||
|
boatclass = coursestandard.boatclass
|
||||||
|
weightcategory = coursestandard.weightclass
|
||||||
|
adaptiveclass = coursestandard.adaptiveclass
|
||||||
|
skillclass = coursestandard.skillclass
|
||||||
|
|
||||||
|
returnurl = reverse(virtualevent_register_view,
|
||||||
|
kwargs={'id':race.id})
|
||||||
|
|
||||||
|
if age < coursestandard.agemin:
|
||||||
|
messages.error(request,'You are younger than the minimum age for this group')
|
||||||
|
return HttpResponseRedirect(returnurl)
|
||||||
|
|
||||||
|
if age > coursestandard.agemax:
|
||||||
|
messages.error(request,'You are older than the maximum age for this group')
|
||||||
|
return HttpResponseRedirect(returnurl)
|
||||||
|
|
||||||
|
if sex == 'male' and coursestandard.sex != 'male':
|
||||||
|
messages.error(request,'Men are not allowed to enter this category')
|
||||||
|
return HttpResponseRedirect(returnurl)
|
||||||
|
|
||||||
|
if sex == 'mixed' and coursestandard.sex not in ['mixed','male']:
|
||||||
|
messages.error(request,'Mixed crews are not allowed to enter this category')
|
||||||
|
return HttpResponseRedirect(returnurl)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
record = IndoorVirtualRaceResult(
|
record = IndoorVirtualRaceResult(
|
||||||
userid=r.id,
|
userid=r.id,
|
||||||
teamname=teamname,
|
teamname=teamname,
|
||||||
@@ -1689,7 +2030,9 @@ def indoorvirtualevent_register_view(request,id=0):
|
|||||||
boatclass=boatclass,
|
boatclass=boatclass,
|
||||||
coursecompleted=False,
|
coursecompleted=False,
|
||||||
sex=sex,
|
sex=sex,
|
||||||
age=age
|
age=age,
|
||||||
|
entrycategory=coursestandard,
|
||||||
|
referencespeed=referencespeed
|
||||||
)
|
)
|
||||||
|
|
||||||
record.save()
|
record.save()
|
||||||
@@ -1733,7 +2076,12 @@ def indoorvirtualevent_register_view(request,id=0):
|
|||||||
'adaptiveclass': r.adaptiveclass,
|
'adaptiveclass': r.adaptiveclass,
|
||||||
}
|
}
|
||||||
|
|
||||||
form = IndoorVirtualRaceResultForm(initial=initial)
|
categories = None
|
||||||
|
if race.coursestandards is not None:
|
||||||
|
categories = CourseStandard.objects.filter(
|
||||||
|
standardcollection=race.coursestandards).order_by("name")
|
||||||
|
|
||||||
|
form = IndoorVirtualRaceResultForm(initial=initial,categories=categories)
|
||||||
|
|
||||||
breadcrumbs = [
|
breadcrumbs = [
|
||||||
{
|
{
|
||||||
@@ -1806,6 +2154,7 @@ def indoorvirtualevent_create_view(request):
|
|||||||
evaluation_closure = cd['evaluation_closure']
|
evaluation_closure = cd['evaluation_closure']
|
||||||
contact_phone = cd['contact_phone']
|
contact_phone = cd['contact_phone']
|
||||||
contact_email = cd['contact_email']
|
contact_email = cd['contact_email']
|
||||||
|
coursestandards = cd['coursestandards']
|
||||||
|
|
||||||
# correct times
|
# correct times
|
||||||
|
|
||||||
@@ -1860,6 +2209,7 @@ def indoorvirtualevent_create_view(request):
|
|||||||
sessionvalue = sessionvalue,
|
sessionvalue = sessionvalue,
|
||||||
course=None,
|
course=None,
|
||||||
timezone=timezone_str,
|
timezone=timezone_str,
|
||||||
|
coursestandards=coursestandards,
|
||||||
evaluation_closure=evaluation_closure,
|
evaluation_closure=evaluation_closure,
|
||||||
registration_closure=registration_closure,
|
registration_closure=registration_closure,
|
||||||
contact_phone=contact_phone,
|
contact_phone=contact_phone,
|
||||||
@@ -1946,6 +2296,7 @@ def virtualevent_create_view(request):
|
|||||||
evaluation_closure = cd['evaluation_closure']
|
evaluation_closure = cd['evaluation_closure']
|
||||||
contact_phone = cd['contact_phone']
|
contact_phone = cd['contact_phone']
|
||||||
contact_email = cd['contact_email']
|
contact_email = cd['contact_email']
|
||||||
|
coursestandards = cd['coursestandards']
|
||||||
|
|
||||||
# correct times
|
# correct times
|
||||||
|
|
||||||
@@ -1997,6 +2348,7 @@ def virtualevent_create_view(request):
|
|||||||
evaluation_closure=evaluation_closure,
|
evaluation_closure=evaluation_closure,
|
||||||
registration_closure=registration_closure,
|
registration_closure=registration_closure,
|
||||||
contact_phone=contact_phone,
|
contact_phone=contact_phone,
|
||||||
|
coursestandards=coursestandards,
|
||||||
contact_email=contact_email,
|
contact_email=contact_email,
|
||||||
country = course.country,
|
country = course.country,
|
||||||
manager=request.user,
|
manager=request.user,
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ from rowers.forms import (
|
|||||||
FitnessMetricForm,PredictedPieceFormNoDistance,
|
FitnessMetricForm,PredictedPieceFormNoDistance,
|
||||||
EmailForm, RegistrationForm, RegistrationFormTermsOfService,
|
EmailForm, RegistrationForm, RegistrationFormTermsOfService,
|
||||||
RegistrationFormUniqueEmail,RegistrationFormSex,
|
RegistrationFormUniqueEmail,RegistrationFormSex,
|
||||||
CNsummaryForm,UpdateWindForm,
|
CNsummaryForm,UpdateWindForm,StandardsForm,
|
||||||
UpdateStreamForm,WorkoutMultipleCompareForm,ChartParamChoiceForm,
|
UpdateStreamForm,WorkoutMultipleCompareForm,ChartParamChoiceForm,
|
||||||
FusionMetricChoiceForm,BoxPlotChoiceForm,MultiFlexChoiceForm,
|
FusionMetricChoiceForm,BoxPlotChoiceForm,MultiFlexChoiceForm,
|
||||||
TrendFlexModalForm,WorkoutSplitForm,WorkoutJoinParamForm,
|
TrendFlexModalForm,WorkoutSplitForm,WorkoutJoinParamForm,
|
||||||
@@ -113,7 +113,7 @@ from rowers.models import (
|
|||||||
RaceLogo,RowerBillingAddressForm,PaidPlan,
|
RaceLogo,RowerBillingAddressForm,PaidPlan,
|
||||||
AlertEditForm, ConditionEditForm,
|
AlertEditForm, ConditionEditForm,
|
||||||
PlannedSessionComment,CoachRequest,CoachOffer,
|
PlannedSessionComment,CoachRequest,CoachOffer,
|
||||||
VideoAnalysis,ShareKey,
|
VideoAnalysis,ShareKey,StandardCollection,CourseStandard,
|
||||||
)
|
)
|
||||||
from rowers.models import (
|
from rowers.models import (
|
||||||
RowerPowerForm,RowerForm,GraphImage,AdvancedWorkoutForm,
|
RowerPowerForm,RowerForm,GraphImage,AdvancedWorkoutForm,
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ ALLOWED_HOSTS = CFG['allowed_hosts']
|
|||||||
OAUTH2_PROVIDER_ACCESS_TOKEN_MODEL = 'oauth2_provider.AccessToken'
|
OAUTH2_PROVIDER_ACCESS_TOKEN_MODEL = 'oauth2_provider.AccessToken'
|
||||||
OAUTH2_PROVIDER_APPLICATION_MODEL = 'oauth2_provider.Application'
|
OAUTH2_PROVIDER_APPLICATION_MODEL = 'oauth2_provider.Application'
|
||||||
OAUTH2_PROVIDER_REFRESH_TOKEN_MODEL = 'oauth2_provider.RefreshToken'
|
OAUTH2_PROVIDER_REFRESH_TOKEN_MODEL = 'oauth2_provider.RefreshToken'
|
||||||
|
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
|
|||||||
@@ -112,6 +112,10 @@ th {
|
|||||||
|
|
||||||
.paddedtable td { padding: 1px 20px }
|
.paddedtable td { padding: 1px 20px }
|
||||||
|
|
||||||
|
.shortpadded th { padding: 3px 3px }
|
||||||
|
|
||||||
|
.paddedtable th { padding: 1px 20px }
|
||||||
|
|
||||||
.cortable {
|
.cortable {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user