Private
Public Access
1
0
Files
rowsandall/rowers/views/racesviews.py

3709 lines
121 KiB
Python

from rowers.views.statements import *
from rowsandall_app.settings import SITE_URL
from rowers.scoring import *
from django.contrib.gis.geoip2 import GeoIP2
from django import forms
from rowers.plannedsessions import timefield_to_seconds_duration
from rowers.courses import getnearestraces, getnearestcourses
# List Courses
def courses_view(request):
r = getrower(request.user)
g = GeoIP2()
ip = request.META.get('HTTP_X_REAL_IP', '1.1.1.1')
try:
lat_lon = g.lat_lon(ip)
city = g.city(ip)
except: # pragma: no cover
lat_lon = None
city = {
'city': '',
'country_name': '',
'time_zone': '',
}
courses = GeoCourse.objects.all().order_by("country", "name", "distance")
nearby = request.GET.get('nearby')
if nearby and lat_lon is not None: # pragma: no cover
courses = getnearestcourses(lat_lon, courses)
# add search processing
query = request.GET.get('q')
if query: # pragma: no cover
query_list = query.split()
courses = GeoCourse.objects.filter(
reduce(operator.and_,
(Q(name__icontains=q) for q in query_list)) |
reduce(operator.and_,
(Q(country__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_courses.html',
{'courses': courses,
'active': 'nav-racing',
'searchform': searchform,
'rower': r,
'location': lat_lon,
'city': city['city'],
'country_name': city['country_name'],
'time_zone': city['time_zone'],
})
# 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: # pragma: no cover
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
def course_map_view(request, id=0):
try:
course = GeoCourse.objects.get(id=id)
except GeoCourse.DoesNotExist: # pragma: no cover # pragma: no cover
raise Http404("Course doesn't exist")
script, div = course_map(course)
breadcrumbs = [
{
'url': reverse('virtualevents_view'),
'name': 'Challenges'
},
{
'url': reverse(courses_view),
'name': 'Courses'
},
{
'url': reverse(course_view, kwargs={'id': course.id}),
'name': course.name
},
{
'url': reverse(course_map_view, kwargs={'id': course.id}),
'name': 'Map'
}
]
r = getrower(request.user)
return render(request,
'coursemap.html',
{
'mapdiv': div,
'course': course,
'mapscript': script,
'active': 'nav-racing',
'rower': r,
'breadcrumbs': breadcrumbs,
})
@login_required()
@permission_required('course.delete_course', fn=get_course_by_pk, raise_exception=True)
def course_delete_view(request, id=0):
course = get_object_or_404(GeoCourse, pk=id)
ps = PlannedSession.objects.filter(course=course)
nosessions = len(ps) == 0
if nosessions:
course.delete()
url = reverse(courses_view)
return HttpResponseRedirect(url)
@login_required()
@permission_required('course.change_course', fn=get_course_by_pk, raise_exception=True)
def course_edit_view(request, id=0):
course = get_object_or_404(GeoCourse, pk=id)
r = getrower(request.user)
ps = PlannedSession.objects.filter(course=course)
nosessions = len(ps) == 0
script, div = course_map(course)
if request.method == 'POST':
form = GeoCourseEditForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
country = form.cleaned_data['country']
notes = form.cleaned_data['notes']
course.name = name
course.country = country
course.notes = notes
course.save()
form = GeoCourseEditForm(instance=course)
breadcrumbs = [
{
'url': reverse('virtualevents_view'),
'name': 'Challenges'
},
{
'url': reverse(courses_view),
'name': 'Courses'
},
{
'url': reverse(course_view, kwargs={'id': course.id}),
'name': course.name
},
{
'url': reverse(course_edit_view, kwargs={'id': course.id}),
'name': 'Edit'
}
]
return render(request, 'course_edit_view.html',
{
'course': course,
'active': 'nav-racing',
'breadcrumbs': breadcrumbs,
'mapscript': script,
'mapdiv': div,
'nosessions': nosessions,
'rower': r,
'form': form,
}
)
# @login_required()
def course_view(request, id=0):
try:
course = GeoCourse.objects.get(id=id)
except GeoCourse.DoesNotExist: # pragma: no cover
raise Http404("Course doesn't exist")
r = getrower(request.user)
script, div = course_map(course)
# get results
records = VirtualRaceResult.objects.filter(
course=course,
workoutid__isnull=False,
coursecompleted=True).order_by("duration", "-distance")
if request.user.is_authenticated:
notsharing = Rower.objects.filter(
share_course_results=False).exclude(id=r.id)
else: # pragma: no cover
notsharing = Rower.objects.filter(share_course_results=False)
notsharing_ids = [o.user.id for o in notsharing]
records = records.exclude(userid__in=notsharing_ids)
if 'onlyme' in request.GET: # pragma: no cover
onlyme = request.GET.get('onlyme', False)
if onlyme == 'true':
onlyme = True
if onlyme and request.user.is_authenticated:
records = records.filter(userid=r.user.id)
else:
onlyme = False
form = RaceResultFilterForm(records=records, groups=False)
if request.method == 'POST': # pragma: no cover
form = RaceResultFilterForm(
request.POST, records=records, groups=False)
if form.is_valid():
cd = form.cleaned_data
try:
sex = cd['sex']
except KeyError:
sex = ['female', 'male', 'mixed']
try:
boattype = cd['boattype']
except KeyError:
boattype = mytypes.waterboattype
try:
boatclass = cd['boatclass']
except KeyError:
boatclass = [t for t in mytypes.otwtypes]
age_min = cd['age_min']
age_max = cd['age_max']
try:
weightcategory = cd['weightcategory']
except KeyError:
weightcategory = ['hwt', 'lwt']
try:
adaptiveclass = cd['adaptiveclass']
except KeyError:
adaptiveclass = ['None', 'PR1', 'PR2', 'PR3', 'FES']
records = VirtualRaceResult.objects.filter(
course=course,
workoutid__isnull=False,
coursecompleted=True,
weightcategory__in=weightcategory,
sex__in=sex,
age__gte=age_min,
age__lte=age_max,
boatclass__in=boatclass,
boattype__in=boattype,
adaptiveclass__in=adaptiveclass,
).order_by("duration", "-distance")
breadcrumbs = [
{
'url': reverse('virtualevents_view'),
'name': 'Challenges'
},
{
'url': reverse(courses_view),
'name': 'Courses'
},
{
'url': reverse(course_view, kwargs={'id': course.id}),
'name': course.name
},
]
return render(request, 'course_view.html',
{
'active': 'nav-racing',
'breadcrumbs': breadcrumbs,
'course': course,
'mapscript': script,
'mapdiv': div,
'nosessions': False,
'records': records,
'rower': r,
'form': form,
'onlyme': onlyme,
}
)
def standard_view(request, id=0):
try:
collection = StandardCollection.objects.get(id=id)
except StandardCollection.DoesNotExist: # pragma: no cover
raise Http404("Standard Collection does not exist")
r = getrower(request.user)
allowed = ["-referencespeed", "agemax", "agemin", "sex", "name",
"referencespeed", "-agemax", "-agemin", "-sex", "-name"]
orderby = request.GET.get('order_by')
if orderby not in allowed:
orderby = None
if orderby is not None: # pragma: no cover
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()
@permission_required('racelogo.delete_logo', fn=get_logo_by_pk, raise_exception=True)
def logo_delete_view(request, id=0): # pragma: no cover
logo = get_object_or_404(RaceLogo, pk=id)
if logo.user == request.user:
logo.delete()
messages.info(request, "Logo Deleted")
url = reverse('virtualevents_view')
return HttpResponseRedirect(url)
@login_required()
@permission_required('virtualevent.change_race', fn=get_virtualevent_by_pk, raise_exception=True)
def virtualevent_setlogo_view(request, id=0, logoid=0): # pragma: no cover
race = get_object_or_404(VirtualRace, pk=id)
logo = get_object_or_404(RaceLogo, pk=logoid)
otherlogos = race.logos.all()
for otherlogo in otherlogos:
otherlogo.race.remove(race)
logo.race.add(race)
logo.save()
url = reverse('virtualevent_view',
kwargs={'id': id})
return HttpResponseRedirect(url)
# Image upload to virtual event
@login_required()
def virtualevent_uploadimage_view(request, id=0): # pragma: no cover
is_ajax = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
r = getrower(request.user)
race = get_object_or_404(VirtualRace, pk=id)
logos = RaceLogo.objects.filter(
user=request.user).order_by("-creationdatetime")
breadcrumbs = [
{
'url': reverse('virtualevents_view'),
'name': 'Challenges'
},
{
'url': reverse('virtualevent_view', kwargs={'id': id}),
'name': race.name
},
{
'url': reverse(virtualevent_uploadimage_view,
kwargs={'id': id}),
'name': 'Add Image'
}
]
if request.method == 'POST':
if len(logos) >= 6:
messages.error(request, "You cannot have more than 6 logos")
url = reverse(virtualevent_imageupload_view,
kwargs={'id': id})
return HttpResponseRedirect(url)
form = ImageForm(request.POST, request.FILES)
if form.is_valid():
f = form.cleaned_data['file']
if f is not None:
filename, path_and_filename = handle_uploaded_image(f)
try:
width, height = Image.open(path_and_filename).size
except:
message = "Not a valid image"
messages.error(request, message)
os.remove(path_and_filename)
url = reverse(virtualevent_image_view,
kwargs={'id': id})
if is_ajax:
return JSONResponse({'result': 0, 'url': 0})
else:
return HttpResponseRedirect(url)
otherlogos = race.logos.all()
for logo in otherlogos:
logo.race.remove(race)
logo = RaceLogo(user=request.user,
creationdatetime=timezone.now(),
filename=path_and_filename,
width=width, height=height)
logo.save()
logo.race.add(race)
logo.save()
url = reverse('virtualevent_view',
kwargs={'id': id})
if is_ajax:
return JSONResponse({'result': 1, 'url': url})
else:
return HttpResponseRedirect(url)
else:
messages.error(
request, "Something went wrong - no file attached")
url = reverse(virtualevent_uploadimage_view,
kwargs={'id': id})
if is_ajax:
return JSONResponse({'result': 0, 'url': 1})
else:
return HttpResponseRedirect(url)
else:
form = ImageForm()
if is_ajax:
return {'result': 0}
return render(request, 'logo_form.html',
{'form': form,
'rower': r,
'logos': logos,
'active': 'nav-racing',
'breadcrumbs': breadcrumbs,
'race': race,
})
@login_required()
@permission_required('course.change_course', fn=get_course_by_pk, raise_exception=True)
def course_upload_replace_view(request, id=0):
is_ajax = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
r = getrower(request.user)
course = get_object_or_404(GeoCourse, pk=id)
if request.method == 'POST':
form = CourseForm(request.POST, request.FILES)
if form.is_valid():
f = form.cleaned_data['file']
notes = form.cleaned_data['notes']
country = form.cleaned_data['country']
if f is not None:
filename, path_and_filename = handle_uploaded_file(f)
cs = courses.kmltocourse(path_and_filename)
os.remove(path_and_filename)
if cs and len(cs) > 1: # pragma: no cover
messages.info(
request, 'File contained multiple courses. We use the first one.')
if cs:
course = cs[0]
cname = course['name']
cnotes = notes+'\n\n'+course['description']
polygons = course['polygons']
course = courses.createcourse(
r, cname, polygons, notes=cnotes)
if course.country == 'unknown': # pragma: no cover
course.country = country
course.save()
url = reverse(course_update_confirm,
kwargs={
'newid': course.id,
'id': id,
}
)
if is_ajax: # pragma: no cover
return JSONResponse({'result': 1, 'url': url})
else:
return HttpResponseRedirect(url)
else: # pragma: no cover
messages.error(request, "File does not contain a course")
else: # pragma: no cover
messages.error(request, "No file attached")
else: # pragma: no cover
messages.error(request, "Form is not valid")
else:
form = CourseForm()
form.fields['name'].widget = forms.HiddenInput()
if not is_ajax:
return render(request, 'course_form_update.html',
{'form': form,
'course': course,
'active': 'nav-racing',
})
else: # pragma: no cover
return {'result': 0}
@login_required()
@permission_required('course.change_course', fn=get_course_by_pk, raise_exception=True)
def course_update_confirm(request, id=0, newid=0):
course = get_object_or_404(GeoCourse, pk=id)
course2 = get_object_or_404(GeoCourse, pk=newid)
r = getrower(request.user)
if request.method == 'POST':
form = CourseConfirmForm(request.POST)
if form.is_valid():
doupdate = form.cleaned_data['doupdate']
if doupdate:
_ = courses.replacecourse(course, course2)
messages.info(
request, 'All challenges with this course are updated')
url = reverse(course_view,
kwargs={
'id': course2.id,
})
return HttpResponseRedirect(url)
else: # pragma: no cover
course2.delete()
url = reverse(course_view,
kwargs={
'id': course.id,
})
return HttpResponseRedirect(url)
else:
form = CourseConfirmForm()
# GET call or invalid form
script, div = course_map(course2)
breadcrumbs = [
{
'url': reverse('virtualevents_view'),
'name': 'Challenges'
},
{
'url': reverse(courses_view),
'name': 'Courses'
},
{
'url': reverse(course_view, kwargs={'id': course.id}),
'name': course.name
},
{
'url': reverse(course_upload_replace_view, kwargs={'id': course.id}),
'name': 'Replace Markers'
}
]
return render(request,
'course_replace_confirm.html',
{'course': course,
'form': form,
'active': 'nav-racing',
'breadcrumbs': breadcrumbs,
'rower': r,
'mapdiv': div,
'mapscript': script,
})
# Course upload
@login_required()
def course_upload_view(request):
is_ajax = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
r = getrower(request.user)
if request.method == 'POST':
form = CourseForm(request.POST, request.FILES)
if form.is_valid():
f = form.cleaned_data['file']
name = form.cleaned_data['name']
notes = form.cleaned_data['notes']
country = form.cleaned_data['country']
if f is not None:
filename, path_and_filename = handle_uploaded_file(f)
cs = courses.kmltocourse(path_and_filename)
for course in cs:
cname = name+' - '+course['name']
cnotes = notes+'\n\n'+course['description']
polygons = course['polygons']
course = courses.createcourse(
r, cname, polygons, notes=cnotes)
if course.country == 'unknown': # pragma: no cover
course.country = country
course.save()
os.remove(path_and_filename)
url = reverse(courses_view)
if is_ajax: # pragma: no cover
return JSONResponse({'result': 1, 'url': url})
else:
return HttpResponseRedirect(url)
else: # pragma: no cover
messages.error(
request, 'Something went wrong - no file attached')
url = reverse(course_upload_view)
if is_ajax:
return JSONResponse({'result': 0, 'url': 0})
else:
return HttpResponseRedirect(url)
else: # pragma: no cover
messages.error(request, 'Form is not valid')
return render(request, 'course_form.html',
{'form': form,
})
else:
if not is_ajax:
form = CourseForm()
return render(request, 'course_form.html',
{'form': form,
'active': 'nav-racing',
})
else: # pragma: no cover
return {'result': 0}
# Standards deactivate
@login_required()
def standard_deactivate_view(request, id=0):
try:
collection = StandardCollection.objects.get(id=id)
except StandardCollection.DoesNotExist: # pragma: no cover
raise Http404("Does not exist")
if request.user != collection.manager: # pragma: no cover
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: # pragma: no cover
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 = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
if id != 0: # pragma: no cover
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: # pragma: no cover
url = reverse(standards_view)
else:
url = reverse(standard_view, kwargs={'id': id})
if is_ajax: # pragma: no cover
return JSONResponse({'result': 1, 'url': url})
return HttpResponseRedirect(url)
else: # pragma: no cover
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: # pragma: no cover
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: # pragma: no cover
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} # pragma: no cover
def virtualevents_view(request):
is_ajax = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
g = GeoIP2()
ip = request.META.get('HTTP_X_REAL_IP', '1.1.1.1')
try:
lat_lon = g.lat_lon(ip)
city = g.city(ip)
except: # pragma: no cover
lat_lon = None
city = {
'city': '',
'country_name': '',
'time_zone': '',
}
# default races
races1 = VirtualRace.objects.filter(
startdate__gte=timezone.now(),
)
races2 = VirtualRace.objects.filter(
startdate__lte=timezone.now(),
evaluation_closure__gte=timezone.now()-datetime.timedelta(days=3),
)
races = (races1 | races2).order_by("startdate", "start_time")
if len(races) == 0:
races = VirtualRace.objects.all().order_by("-startdate")
if not request.user.is_anonymous:
r = getrower(request.user)
else:
r = None
if request.method == 'POST':
# process form
form = VirtualRaceSelectForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
country = cd['country']
regattatype = cd['regattatype']
if country == 'All':
countries = VirtualRace.objects.order_by(
'country').values_list('country').distinct()
else: # pragma: no cover
countries = [country,
'Indoor']
if regattatype == 'upcoming':
races1 = VirtualRace.objects.filter(
startdate__gte=timezone.now(),
country__in=countries
)
races2 = VirtualRace.objects.filter(
startdate__lte=timezone.now(),
evaluation_closure__gte=timezone.now(),
country__in=countries
)
races = (races1 | races2).order_by("startdate", "start_time")
elif regattatype == 'previous':
races = VirtualRace.objects.filter(
evaluation_closure__lt=timezone.now(),
country__in=countries
).order_by("-startdate", "-start_time")
elif regattatype == 'ongoing':
races = VirtualRace.objects.filter(
startdate__lte=timezone.now(),
evaluation_closure__gte=timezone.now(),
country__in=countries
).order_by("startdate", "start_time")
elif regattatype == 'my': # pragma: no cover
mysessions = get_my_session_ids(r)
races = VirtualRace.objects.filter(
id__in=mysessions,
country__in=countries
).order_by("startdate", "start_time")
elif regattatype == 'all': # pragma: no cover
races = VirtualRace.objects.filter(
country__in=countries
).order_by("startdate", "start_time")
else:
form = VirtualRaceSelectForm()
nearby = request.GET.get('nearby')
if nearby and lat_lon is not None: # pragma: no cover
races = getnearestraces(lat_lon, races)
if is_ajax: # pragma: no cover
return render(request, 'racelist.html',
{'races': races,
'rower': r,
'location': lat_lon,
'city': city['city'],
'country_name': city['country_name'],
'time_zone': city['time_zone'],
})
breadcrumbs = [
{
'url': reverse('virtualevents_view'),
'name': 'Challenges'
},
]
return render(request, 'virtualevents.html',
{'races': races,
'form': form,
'breadcrumbs': breadcrumbs,
'active': 'nav-racing',
'rower': r,
'location': lat_lon,
'city': city['city'],
'country_name': city['country_name'],
'time_zone': city['time_zone'],
}
)
@login_required()
@permission_required('virtualevent.change_race', fn=get_virtualevent_by_pk, raise_exception=True)
def virtualevent_disqualify_view(request, id=0, recordid=0):
r = getrower(request.user)
race = get_object_or_404(VirtualRace, pk=id)
raceid = race.id
if race.sessiontype == 'race':
recordobj = VirtualRaceResult
else: # pragma: no cover
recordobj = IndoorVirtualRaceResult
# datum moet voor race evaluation date zijn (ook in template controleren)
try:
record = recordobj.objects.get(id=recordid)
except recordobj.DoesNotExist: # pragma: no cover
messages.error(request, "We couldn't find the record")
if timezone.now() > race.evaluation_closure+datetime.timedelta(hours=1): # pragma: no cover
messages.error(
request, "The evaluation is already closed and the results are official")
url = reverse('virtualevent_view', kwargs={'id': raceid})
return HttpResponseRedirect(url)
if request.method == 'POST':
form = DisqualificationForm(request.POST)
if form.is_valid():
message = form.cleaned_data['message']
reason = form.cleaned_data['reason']
disqualifier = disqualifiers[reason]
r = Rower.objects.get(id=record.userid)
name = record.username
_ = myqueue(queue, handle_send_disqualification_email,
r.user.email, name,
disqualifier, message, race.name)
messages.info(
request, "We have invalidated the result for: "+str(record))
record.coursecompleted = False
record.startsecond = 0
record.endsecond = 0
record.save()
url = reverse('virtualevent_view', kwargs={'id': raceid})
return HttpResponseRedirect(url)
else:
form = DisqualificationForm(request.POST)
try:
workout = Workout.objects.get(id=record.workoutid)
except Workout.DoesNotExist: # pragma: no cover
workout = None
script = ''
div = ''
g = []
mapscript = ''
mapdiv = ''
if workout is not None:
g = GraphImage.objects.filter(
workout=workout).order_by("-creationdatetime")
for i in g: # pragma: no cover
try:
width, height = Image.open(i.filename).size
i.width = width
i.height = height
i.save()
except:
pass
script, div = interactive_chart(record.workoutid)
f1 = workout.csvfilename
rowdata = rdata(csvfile=f1)
hascoordinates = 1
if rowdata != 0:
try:
latitude = rowdata.df[' latitude']
if not latitude.std(): # pragma: no cover
hascoordinates = 0
except (KeyError, AttributeError): # pragma: no cover
hascoordinates = 0
else: # pragma: no cover
hascoordinates = 0
if hascoordinates:
mapscript, mapdiv = leaflet_chart(rowdata.df[' latitude'],
rowdata.df[' longitude'],
workout.name)
else: # pragma: no cover
mapscript = ""
mapdiv = ""
breadcrumbs = [
{
'url': reverse('virtualevents_view'),
'name': 'Challenges'
},
{
'url': reverse('virtualevent_view',
kwargs={'id': race.id}),
'name': race.name
},
{
'url': reverse(virtualevent_disqualify_view,
kwargs={'id': id,
'recordid': recordid}),
'name': 'Disqualify Entry'
},
]
buttons = []
if not request.user.is_anonymous:
if race_can_register(r, race): # pragma: no cover
buttons += ['registerbutton']
if race_can_adddiscipline(r, race):
buttons += ['adddisciplinebutton']
if race_can_submit(r, race):
buttons += ['submitbutton']
if race_can_resubmit(r, race): # pragma: no cover
buttons += ['resubmitbutton']
if race_can_withdraw(r, race): # pragma: no cover
buttons += ['withdrawbutton']
if race_can_edit(r, race):
buttons += ['editbutton']
return render(request, "disqualification_view.html",
{'workout': workout,
'active': 'nav-racing',
'graphs': g,
'buttons': buttons,
'interactiveplot': script,
'the_div': div,
'mapscript': mapscript,
'mapdiv': mapdiv,
'form': form,
'race': race,
'breadcrumbs': breadcrumbs,
'record': record,
})
@login_required()
def virtualevent_withdrawresult_view(request, id=0, recordid=0):
r = getrower(request.user)
race = get_object_or_404(VirtualRace, pk=id)
if race.sessiontype == 'race':
recordobj = VirtualRaceResult
else:
recordobj = IndoorVirtualRaceResult
# datum moet voor race evaluation date zijn (ook in template controleren)
try:
record = recordobj.objects.get(id=recordid)
except recordobj.DoesNotExist: # pragma: no cover
messages.error(request, "We couldn't find the record")
if r.id != record.userid: # pragma: no cover
raise PermissionDenied("You are not the owner of this result")
if timezone.now() > race.evaluation_closure+datetime.timedelta(hours=1): # pragma: no cover
messages.error(
request, "The evaluation is already closed and the results are official")
url = reverse('virtualevent_view', kwargs={'id': raceid})
return HttpResponseRedirect(url)
if request.method == 'POST':
form = DisqualificationForm(request.POST)
if form.is_valid():
message = form.cleaned_data['message']
reason = form.cleaned_data['reason']
disqualifier = disqualifiers[reason]
r = Rower.objects.get(id=record.userid)
name = record.username
_ = myqueue(queue, handle_send_withdraw_email,
r.user.email, name,
disqualifier, message, race.name)
messages.info(
request, "We have invalidated the result for: "+str(record))
record.coursecompleted = False
record.startsecond = 0
record.endsecond = 0
record.save()
url = reverse('virtualevent_view', kwargs={'id': id})
return HttpResponseRedirect(url)
else:
form = DisqualificationForm(request.POST)
try: # pragma: no cover
workout = Workout.objects.get(id=record.workoutid)
g = GraphImage.objects.filter(
workout=workout).order_by("-creationdatetime")
for i in g:
try:
width, height = Image.open(i.filename).size
i.width = width
i.height = height
i.save()
except:
pass
script, div = interactive_chart(record.workoutid)
f1 = workout.csvfilename
rowdata = rdata(csvfile=f1)
hascoordinates = 1
if rowdata != 0:
try:
latitude = rowdata.df[' latitude']
if not latitude.std():
hascoordinates = 0
except (KeyError, AttributeError):
hascoordinates = 0
else:
hascoordinates = 0
if hascoordinates:
mapscript, mapdiv = leaflet_chart(rowdata.df[' latitude'],
rowdata.df[' longitude'],
workout.name)
else:
mapscript = ""
mapdiv = ""
except Workout.DoesNotExist: # pragma: no cover
mapscript = ""
mapdiv = ""
workout = None
script = ""
div = ""
g = None
breadcrumbs = [
{
'url': reverse('virtualevents_view'),
'name': 'Challenges'
},
{
'url': reverse('virtualevent_view',
kwargs={'id': race.id}),
'name': race.name
},
{
'url': reverse(virtualevent_disqualify_view,
kwargs={'id': id,
'recordid': recordid}),
'name': 'Disqualify Entry'
},
]
buttons = []
if not request.user.is_anonymous:
if race_can_register(r, race): # pragma: no cover
buttons += ['registerbutton']
if race_can_adddiscipline(r, race):
buttons += ['adddisciplinebutton']
if race_can_submit(r, race):
buttons += ['submitbutton']
if race_can_resubmit(r, race): # pragma: no cover
buttons += ['resubmitbutton']
if race_can_withdraw(r, race): # pragma: no cover
buttons += ['withdrawbutton']
if race_can_edit(r, race):
buttons += ['editbutton']
return render(request, "withdraw_view.html",
{'workout': workout,
'active': 'nav-racing',
'graphs': g,
'buttons': buttons,
'interactiveplot': script,
'the_div': div,
'mapscript': mapscript,
'mapdiv': mapdiv,
'form': form,
'race': race,
'breadcrumbs': breadcrumbs,
'record': record,
})
def virtualevent_view(request, id=0):
results = []
if not request.user.is_anonymous:
r = getrower(request.user)
else: # pragma: no cover
r = None
try:
race = VirtualRace.objects.get(id=id)
except VirtualRace.DoesNotExist: # pragma: no cover
raise Http404("Virtual Challenge does not exist")
if race.sessiontype == 'race':
script, div = course_map(race.course)
resultobj = VirtualRaceResult
else:
script = ''
div = ''
resultobj = IndoorVirtualRaceResult
records = resultobj.objects.filter(race=race)
buttons = []
# to-do - add DNS
dns = []
if timezone.now() > race.evaluation_closure: # pragma: no cover
dns = resultobj.objects.filter(
race=race,
workoutid__isnull=True,
)
dnf = resultobj.objects.filter(
race=race,
workoutid__isnull=False,
coursecompleted=False,
)
if not request.user.is_anonymous:
if race_can_register(r, race):
buttons += ['registerbutton']
if race_can_adddiscipline(r, race):
buttons += ['adddisciplinebutton']
if race_can_submit(r, race):
buttons += ['submitbutton']
if race_can_resubmit(r, race): # pragma: no cover
buttons += ['resubmitbutton']
if race_can_withdraw(r, race):
buttons += ['withdrawbutton']
if race_can_edit(r, race):
buttons += ['editbutton']
if request.method == 'POST': # pragma: no cover
form = RaceResultFilterForm(request.POST, records=records)
if form.is_valid():
cd = form.cleaned_data
try:
sex = cd['sex']
except KeyError:
sex = ['female', 'male', 'mixed']
try:
boattype = cd['boattype']
except KeyError:
boattype = mytypes.waterboattype
try:
boatclass = cd['boatclass']
except KeyError:
if race.sessiontype == 'race':
boatclass = [t for t in mytypes.otwtypes]
else:
boatclass = [t for t in mytypes.otetypes]
age_min = cd['age_min']
age_max = cd['age_max']
try:
weightcategory = cd['weightcategory']
except KeyError:
weightcategory = ['hwt', 'lwt']
try:
adaptiveclass = cd['adaptiveclass']
except KeyError:
adaptiveclass = ['None', 'PR1', 'PR2', 'PR3', 'FES']
try:
entrycategory = cd['entrycategory']
except KeyError:
entrycategory = None
if race.sessiontype == 'race':
results = resultobj.objects.filter(
race=race,
workoutid__isnull=False,
boatclass__in=boatclass,
boattype__in=boattype,
sex__in=sex,
weightcategory__in=weightcategory,
adaptiveclass__in=adaptiveclass,
age__gte=age_min,
age__lte=age_max,
coursecompleted=True,
).order_by("duration")
else:
results = resultobj.objects.filter(
race=race,
workoutid__isnull=False,
boatclass__in=boatclass,
sex__in=sex,
weightcategory__in=weightcategory,
adaptiveclass__in=adaptiveclass,
age__gte=age_min,
age__lte=age_max,
coursecompleted=True,
).order_by("duration", "-distance")
if entrycategory is not None:
results = results.filter(entrycategory__in=entrycategory)
# to-do - add DNS
dns = []
if timezone.now() > race.evaluation_closure:
dns = resultobj.objects.filter(
race=race,
workoutid__isnull=True,
boatclass__in=boatclass,
sex__in=sex,
weightcategory__in=weightcategory,
adaptiveclass__in=adaptiveclass,
age__gte=age_min,
age__lte=age_max
)
else:
results = resultobj.objects.filter(
race=race,
workoutid__isnull=False,
coursecompleted=True,
).order_by("duration", "-distance")
if results:
form = RaceResultFilterForm(records=records)
else:
form = None
breadcrumbs = [
{
'url': reverse('virtualevents_view'),
'name': 'Challenges'
},
{
'url': reverse('virtualevent_view',
kwargs={'id': race.id}
),
'name': race.name
}
]
allowed = ["duration", "distance", "-distance",
"points", "-points", "-duration", "-distance"]
orderby = request.GET.get('order_by')
if orderby not in allowed:
orderby = None
if orderby is not None: # pragma: no cover
try:
results = results.order_by(orderby)
except AttributeError:
pass
racelogos = race.logos.all()
if racelogos: # pragma: no cover
racelogo = racelogos[0]
else:
racelogo = None
comments = PlannedSessionComment.objects.filter(
plannedsession=race).order_by("created")
return render(request, 'virtualevent.html',
{
'coursescript': script,
'coursediv': div,
'breadcrumbs': breadcrumbs,
'race': race,
'rower': r,
'results': results,
'buttons': buttons,
'dns': dns,
'dnf': dnf,
'records': records,
'racelogo': racelogo,
'form': form,
'active': 'nav-racing',
'comments': comments
})
def do_encode(x):
try:
return encoder.encode_hex(int(x))
except:
return x
@login_required()
@permission_required('virtualevent.change_race', fn=get_virtualevent_by_pk, raise_exception=True)
def virtualevent_results_download_view(request, id=0):
try:
race = VirtualRace.objects.get(id=id)
except VirtualRace.DoesNotExist: # pragma: no cover
raise Http404("Virtual Challenge does not exist")
if race.sessiontype == 'race':
resultobj = VirtualRaceResult
else: # pragma: no cover
resultobj = IndoorVirtualRaceResult
records = resultobj.objects.filter(race=race)
filename = 'Challenge Results {name} {id} {date}.csv'.format(
id=id,
name=race.name,
date=timezone.now().strftime("%Y-%m-%d %H:%M:%S %Z")
)
df = pd.DataFrame.from_records(records.values())
df['workoutid'] = df['workoutid'].apply(lambda x: do_encode(x))
response = HttpResponse(df.to_csv())
response['Content-Disposition'] = 'attachment; filename="%s"' % filename
response['Content-Type'] = 'application/octet-stream'
return response
def virtualevent_ranking_view(request, id=0):
results = []
if not request.user.is_anonymous:
r = getrower(request.user)
else: # pragma: no cover
r = None
try:
race = VirtualRace.objects.get(id=id)
except VirtualRace.DoesNotExist: # pragma: no cover
raise Http404("Virtual Challenge does not exist")
if race.sessiontype == 'race':
script, div = course_map(race.course)
resultobj = VirtualRaceResult
else:
script = ''
div = ''
resultobj = IndoorVirtualRaceResult
records = resultobj.objects.filter(race=race)
buttons = []
# to-do - add DNS
dns = []
if timezone.now() > race.evaluation_closure: # pragma: no cover
dns = resultobj.objects.filter(
race=race,
workoutid__isnull=True,
)
if not request.user.is_anonymous:
if race_can_register(r, race): # pragma: no cover
buttons += ['registerbutton']
if race_can_adddiscipline(r, race):
buttons += ['adddisciplinebutton']
if race_can_submit(r, race):
buttons += ['submitbutton']
if race_can_resubmit(r, race): # pragma: no cover
buttons += ['resubmitbutton']
if race_can_withdraw(r, race): # pragma: no cover
buttons += ['withdrawbutton']
if race_can_edit(r, race):
buttons += ['editbutton']
if request.method == 'POST': # pragma: no cover
form = RaceResultFilterForm(request.POST, records=records)
if form.is_valid():
cd = form.cleaned_data
try:
sex = cd['sex']
except KeyError:
sex = ['female', 'male', 'mixed']
try:
boattype = cd['boattype']
except KeyError:
boattype = mytypes.waterboattype
try:
boatclass = cd['boatclass']
except KeyError:
if race.sessiontype == 'race':
boatclass = [t for t in mytypes.otwtypes]
else:
boatclass = [t for t in mytypes.otetypes]
age_min = cd['age_min']
age_max = cd['age_max']
try:
weightcategory = cd['weightcategory']
except KeyError:
weightcategory = ['hwt', 'lwt']
try:
adaptiveclass = cd['adaptiveclass']
except KeyError:
adaptiveclass = ['None', 'PR1', 'PR2', 'PR3', 'FES']
if race.sessiontype == 'race':
results = resultobj.objects.filter(
race=race,
workoutid__isnull=False,
boatclass__in=boatclass,
boattype__in=boattype,
sex__in=sex,
weightcategory__in=weightcategory,
adaptiveclass__in=adaptiveclass,
age__gte=age_min,
age__lte=age_max
).order_by("duration")
else:
results = resultobj.objects.filter(
race=race,
workoutid__isnull=False,
boatclass__in=boatclass,
sex__in=sex,
weightcategory__in=weightcategory,
adaptiveclass__in=adaptiveclass,
age__gte=age_min,
age__lte=age_max
).order_by("duration", "-distance")
# to-do - add DNS
dns = []
if timezone.now() > race.evaluation_closure:
dns = resultobj.objects.filter(
race=race,
workoutid__isnull=True,
boatclass__in=boatclass,
sex__in=sex,
weightcategory__in=weightcategory,
adaptiveclass__in=adaptiveclass,
age__gte=age_min,
age__lte=age_max
)
else:
results = resultobj.objects.filter(
race=race,
workoutid__isnull=False,
coursecompleted=True,
).order_by("duration", "-distance")
if results:
form = RaceResultFilterForm(records=records)
else: # pragma: no cover
form = None
breadcrumbs = [
{
'url': reverse('virtualevents_view'),
'name': 'Challenges'
},
{
'url': reverse('virtualevent_view',
kwargs={'id': race.id}
),
'name': race.name
}
]
racelogos = race.logos.all()
if racelogos: # pragma: no cover
racelogo = racelogos[0]
else:
racelogo = None
return render(request, 'virtualeventranking.html',
{
'coursescript': script,
'coursediv': div,
'breadcrumbs': breadcrumbs,
'race': race,
'rower': r,
'results': results,
'buttons': buttons,
'dns': dns,
'records': records,
'racelogo': racelogo,
'form': form,
'active': 'nav-racing',
})
@login_required()
def virtualevent_withdraw_view(request, id=0, recordid=None):
r = getrower(request.user)
try:
race = VirtualRace.objects.get(id=id)
except VirtualRace.DoesNotExist: # pragma: no cover
raise Http404("Virtual Challenge does not exist")
if race_can_withdraw(r, race):
remove_rower_race(r, race, recordid=recordid)
messages.info(request,
"You have successfully withdrawn from this race.")
else: # pragma: no cover
messages.error(request, "You cannot withdraw from this race")
url = reverse('virtualevent_view',
kwargs={
'id': race.id
})
return HttpResponseRedirect(url)
@login_required()
def virtualevent_addboat_view(request, id=0):
r = getrower(request.user)
try:
race = VirtualRace.objects.get(id=id)
except VirtualRace.DoesNotExist: # pragma: no cover
raise Http404("Virtual Challenge does not exist")
if race.sessiontype in ['race']:
resultobj = VirtualRaceResult
else: # pragma: no cover
resultobj = IndoorVirtualRaceResult
categories = None
hasinitial, boattype, boatclass, adaptiveclass, weightclass, sex, referencespeed, initialcategory = default_class(
r, None, race)
if race.coursestandards is not None:
categories = CourseStandard.objects.filter(
standardcollection=race.coursestandards).order_by("name")
if not race_can_adddiscipline(r, race): # pragma: no cover
messages.error(request, "You cannot register for this race")
url = reverse('virtualevent_view',
kwargs={
'id': race.id
})
return HttpResponseRedirect(url)
records = resultobj.objects.filter(
userid=r.id,
race=race
)
boattypes = [record.boattype for record in records]
boatclasses = [record.boatclass for record in records]
# we're still here
if request.method == 'POST':
# process form
form = VirtualRaceResultForm(request.POST, categories=categories)
if form.is_valid():
cd = form.cleaned_data
teamname = cd['teamname']
boattype = cd['boattype']
boatclass = cd['boatclass']
weightcategory = cd['weightcategory']
adaptiveclass = cd['adaptiveclass']
age = cd['age']
mix = cd['mix']
acceptsocialmedia = cd['acceptsocialmedia']
sex = r.sex
if boattype == '1x' and r.birthdate:
age = calculate_age(r.birthdate)
sex = r.sex
if sex == 'not specified':
sex = 'male'
if mix: # pragma: no cover
sex = 'mixed'
if boattype in boattypes and boatclass in boatclasses and race.coursestandards is None: # pragma: no cover
# check if different sexes
therecords = records.filter(
boattype=boattype,
boatclass=boatclass)
thesexes = [record.sex for record in therecords]
if sex in thesexes:
messages.error(
request,
"You have already registered in that boat class/type"
)
url = reverse('virtualevent_view',
kwargs={
'id': race.id
}
)
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: # pragma: no cover
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
returnurl = reverse(virtualevent_register_view,
kwargs={'id': race.id})
if age < coursestandard.agemin: # pragma: no cover
messages.error(
request, 'You are younger than the minimum age for this group')
return HttpResponseRedirect(returnurl)
if age > coursestandard.agemax: # pragma: no cover
messages.error(
request, 'You are older than the maximum age for this group')
return HttpResponseRedirect(returnurl)
if sex == 'male' and coursestandard.sex != 'male': # pragma: no cover
messages.error(
request, 'Men are not allowed to enter this category')
return HttpResponseRedirect(returnurl)
if sex == 'mixed' and coursestandard.sex not in ['mixed', 'male']: # pragma: no cover
messages.error(
request, 'Mixed crews are not allowed to enter this category')
return HttpResponseRedirect(returnurl)
record = resultobj(
userid=r.id,
teamname=teamname,
race=race,
username=u'{f} {l}'.format(
f=r.user.first_name,
l=r.user.last_name
),
weightcategory=weightcategory,
adaptiveclass=adaptiveclass,
duration=datetime.time(0, 0),
boattype=boattype,
boatclass=boatclass,
coursecompleted=False,
referencespeed=referencespeed,
entrycategory=coursestandard,
sex=sex,
age=age,
acceptsocialmedia=acceptsocialmedia,
)
record.save()
add_rower_race(r, race)
# send email about opt out
if not acceptsocialmedia:
_ = myqueue(
queue,
handle_sendemail_optout,
race.manager.email, race.manager.first_name,
r.user.first_name+' '+r.user.last_name,
race.name, race.id,
)
messages.info(
request,
"You have successfully registered for this race. Good luck!"
)
otherrecords = resultobj.objects.filter(
race=race).exclude(userid=r.id)
registereduserids = [otherrecord.userid for otherrecord in otherrecords]
for otherrecord in otherrecords:
try:
otheruser = Rower.objects.get(id=otherrecord.userid)
othername = otheruser.user.first_name+' '+otheruser.user.last_name
registeredname = r.user.first_name+' '+r.user.last_name
if otherrecord.emailnotifications:
_ = myqueue(
queue,
handle_sendemail_raceregistration,
otheruser.user.email, othername,
registeredname,
race.name,
race.id
)
except Rower.DoesNotExist: # pragma: no cover
pass
followers = VirtualRaceFollower.objects.filter(race=race)
for follower in followers:
othername = ''
if follower.user:
othername = follower.user.first_name+' '+follower.user.last_name
registeredname = r.user.first_name+' '+r.user.last_name
email = follower.emailaddress
try:
if follower.user.id not in registereduserids:
_ = myqueue(
queue,
handle_sendemail_raceregistration,
email, othername,
registeredname, race.name, race.id,
)
registereduserids.append(follower.user.id)
except AttributeError:
pass
url = reverse('virtualevent_view',
kwargs={
'id': race.id
})
return HttpResponseRedirect(url)
else:
if hasinitial:
initial = {
'age': calculate_age(r.birthdate),
'boattype': boattype,
'boatclass': boatclass,
'adaptiveclass': adaptiveclass,
'weightclass': weightclass,
'sex': sex,
'entrycategory': initialcategory,
}
else: # pragma: no cover
initial = {
'age': calculate_age(r.birthdate),
'weightcategory': r.weightcategory,
'adaptiveclass': r.adaptiveclass,
}
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 = [
{
'url': reverse('virtualevents_view'),
'name': 'Challenges'
},
{
'url': reverse('virtualevent_view',
kwargs={'id': race.id}
),
'name': race.name
},
{
'url': reverse('virtualevent_addboat_view',
kwargs={'id': race.id}
),
'name': 'Add Discipline'
}
]
buttons = []
if not request.user.is_anonymous:
if race_can_register(r, race): # pragma: no cover
buttons += ['registerbutton']
if race_can_adddiscipline(r, race):
buttons += ['adddisciplinebutton']
if race_can_submit(r, race):
buttons += ['submitbutton']
if race_can_resubmit(r, race): # pragma: no cover
buttons += ['resubmitbutton']
if race_can_withdraw(r, race):
buttons += ['withdrawbutton']
if race_can_edit(r, race):
buttons += ['editbutton']
return render(request, 'virtualeventregister.html',
{
'form': form,
'buttons': buttons,
'breadcrumbs': breadcrumbs,
'race': race,
'userid': r.user.id,
'active': 'nav-racing',
})
@login_required()
def virtualevent_register_view(request, id=0):
r = getrower(request.user)
try:
race = VirtualRace.objects.get(id=id)
except VirtualRace.DoesNotExist: # pragma: no cover
raise Http404("Virtual Challenge does not exist")
categories = None
hasinitial, boattype, boatclass, adaptiveclass, weightclass, sex, referencespeed, initialcategory = default_class(
r, None, race)
if race.coursestandards is not None:
categories = CourseStandard.objects.filter(
standardcollection=race.coursestandards).order_by("name")
if not race_can_register(r, race):
messages.error(request, "You cannot register for this race")
url = reverse('virtualevent_view',
kwargs={
'id': race.id
})
return HttpResponseRedirect(url)
if race.sessiontype == 'race':
resultobj = VirtualRaceResult
else: # pragma: no cover
resultobj = IndoorVirtualRaceResult
# we're still here
if request.method == 'POST':
# process form
form = VirtualRaceResultForm(request.POST, categories=categories)
if form.is_valid():
cd = form.cleaned_data
teamname = cd['teamname']
boattype = cd['boattype']
boatclass = cd['boatclass']
weightcategory = cd['weightcategory']
adaptiveclass = cd['adaptiveclass']
age = cd['age']
mix = cd['mix']
acceptsocialmedia = cd['acceptsocialmedia']
sex = r.sex
if boattype == '1x' and r.birthdate:
age = calculate_age(r.birthdate)
sex = r.sex
if sex == 'not specified':
sex = 'male'
if mix: # pragma: no cover
sex = 'mixed'
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
returnurl = reverse(virtualevent_register_view,
kwargs={'id': race.id})
if age < coursestandard.agemin: # pragma: no cover
messages.error(
request, 'You are younger than the minimum age for this group')
return HttpResponseRedirect(returnurl)
if age > coursestandard.agemax: # pragma: no cover
messages.error(
request, 'You are older than the maximum age for this group')
return HttpResponseRedirect(returnurl)
if sex == 'male' and coursestandard.sex != 'male': # pragma: no cover
messages.error(
request, 'Men are not allowed to enter this category')
return HttpResponseRedirect(returnurl)
if sex == 'mixed' and coursestandard.sex not in ['mixed', 'male']: # pragma: no cover
messages.error(
request, 'Mixed crews are not allowed to enter this category')
return HttpResponseRedirect(returnurl)
record = resultobj(
userid=r.id,
teamname=teamname,
race=race,
username=u'{f} {l}'.format(
f=r.user.first_name,
l=r.user.last_name
),
weightcategory=weightcategory,
adaptiveclass=adaptiveclass,
duration=datetime.time(0, 0),
boatclass=boatclass,
boattype=boattype,
coursecompleted=False,
sex=sex,
age=age,
entrycategory=coursestandard,
referencespeed=referencespeed,
acceptsocialmedia=acceptsocialmedia,
)
record.save()
add_rower_race(r, race)
# send email about opt out
if not acceptsocialmedia:
_ = myqueue(
queue,
handle_sendemail_optout,
race.manager.email, race.manager.first_name,
r.user.first_name+' '+r.user.last_name,
race.name, race.id,
)
# remove followers
myfollows = VirtualRaceFollower.objects.filter(
user=r.user, race=race)
for f in myfollows: # pragma: no cover
f.delete()
otherrecords = resultobj.objects.filter(
race=race).exclude(userid=r.id)
for otherrecord in otherrecords:
try:
otheruser = Rower.objects.get(id=otherrecord.userid)
othername = otheruser.user.first_name+' '+otheruser.user.last_name
registeredname = r.user.first_name+' '+r.user.last_name
if otherrecord.emailnotifications:
_ = myqueue(
queue,
handle_sendemail_raceregistration,
otheruser.user.email, othername,
registeredname,
race.name,
race.id
)
except Rower.DoesNotExist: # pragma: no cover
pass
followers = VirtualRaceFollower.objects.filter(race=race)
for follower in followers: # pragma: no cover
othername = ''
if follower.user:
othername = follower.user.first_name+' '+follower.user.last_name
registeredname = r.user.first_name+' '+r.user.last_name
email = follower.emailaddress
_ = myqueue(
queue,
handle_sendemail_raceregistration,
email, othername,
registeredname, race.name, race.id,
)
messages.info(
request,
"You have successfully registered for this race. Good luck!"
)
url = reverse('virtualevent_view',
kwargs={
'id': race.id
})
return HttpResponseRedirect(url)
else:
if hasinitial:
initial = {
'age': calculate_age(r.birthdate),
'boattype': boattype,
'boatclass': boatclass,
'adaptiveclass': adaptiveclass,
'weightclass': weightclass,
'sex': sex,
'entrycategory': initialcategory,
}
else: # pragma: no cover
initial = {
'age': calculate_age(r.birthdate),
'weightcategory': r.weightcategory,
'adaptiveclass': r.adaptiveclass,
}
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 = [
{
'url': reverse('virtualevents_view'),
'name': 'Challenges'
},
{
'url': reverse('virtualevent_view',
kwargs={'id': race.id}
),
'name': race.name
},
{
'url': reverse(virtualevent_register_view,
kwargs={'id': race.id}
),
'name': 'Register'
}
]
buttons = []
if not request.user.is_anonymous:
if race_can_register(r, race):
buttons += ['registerbutton']
if race_can_adddiscipline(r, race): # pragma: no cover
buttons += ['adddisciplinebutton']
if race_can_submit(r, race):
buttons += ['submitbutton']
if race_can_resubmit(r, race): # pragma: no cover
buttons += ['resubmitbutton']
if race_can_withdraw(r, race): # pragma: no cover
buttons += ['withdrawbutton']
if race_can_edit(r, race):
buttons += ['editbutton']
return render(request, 'virtualeventregister.html',
{
'form': form,
'buttons': buttons,
'breadcrumbs': breadcrumbs,
'race': race,
'userid': r.user.id,
})
@login_required()
def virtualevent_toggle_email_view(request, id=0):
r = getrower(request.user)
race = VirtualRace.objects.get(id=id)
records = VirtualRaceResult.objects.filter(userid=r.id, race=race)
if True in [record.emailnotifications for record in records]:
newsetting = False
else: # pragma: no cover
newsetting = True
for record in records:
record.emailnotifications = newsetting
record.save()
url = reverse('virtualevent_view',
kwargs={'id': race.id})
return HttpResponseRedirect(url)
@login_required()
def indoorvirtualevent_toggle_email_view(request, id=0):
r = getrower(request.user)
race = VirtualRace.objects.get(id=id)
records = IndoorVirtualRaceResult.objects.filter(userid=r.id,
race=race)
if True in [record.emailnotifications for record in records]:
newsetting = False
else: # pragma: no cover
newsetting = True
for record in records:
record.emailnotifications = newsetting
record.save()
url = reverse('virtualevent_view',
kwargs={'id': race.id})
return HttpResponseRedirect(url)
@login_required()
def indoorvirtualevent_register_view(request, id=0):
r = getrower(request.user)
try:
race = VirtualRace.objects.get(id=id)
except VirtualRace.DoesNotExist: # pragma: no cover
raise Http404("Virtual Challenge does not exist")
categories = None
if race.coursestandards is not None: # pragma: no cover
categories = CourseStandard.objects.filter(
standardcollection=race.coursestandards).order_by("name")
if not race_can_register(r, race):
messages.error(request, "You cannot register for this race")
url = reverse('virtualevent_view',
kwargs={
'id': race.id
})
return HttpResponseRedirect(url)
# we're still here
if request.method == 'POST':
# process form
form = IndoorVirtualRaceResultForm(request.POST, categories=categories)
if form.is_valid():
cd = form.cleaned_data
teamname = cd['teamname']
weightcategory = cd['weightcategory']
adaptiveclass = cd['adaptiveclass']
age = cd['age']
boatclass = cd['boatclass']
acceptsocialmedia = cd['acceptsocialmedia']
sex = r.sex
if r.birthdate:
age = calculate_age(r.birthdate)
sex = r.sex
if sex == 'not specified':
sex = 'male'
coursestandard = None
referencespeed = 5.0
if race.coursestandards is not None: # pragma: no cover
coursestandard = cd['entrycategory']
referencespeed = coursestandard.referencespeed
boatclass = coursestandard.boatclass
weightcategory = coursestandard.weightclass
adaptiveclass = coursestandard.adaptiveclass
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(
userid=r.id,
teamname=teamname,
race=race,
username=u'{f} {l}'.format(
f=r.user.first_name,
l=r.user.last_name
),
weightcategory=weightcategory,
adaptiveclass=adaptiveclass,
duration=datetime.time(0, 0),
boatclass=boatclass,
coursecompleted=False,
sex=sex,
age=age,
entrycategory=coursestandard,
referencespeed=referencespeed,
acceptsocialmedia=acceptsocialmedia,
)
record.save()
add_rower_race(r, race)
# send email about opt out
if not acceptsocialmedia:
_ = myqueue(
queue,
handle_sendemail_optout,
race.manager.email, race.manager.first_name,
r.user.first_name+' '+r.user.last_name,
race.name, race.id,
)
# remove followers
myfollows = VirtualRaceFollower.objects.filter(
user=r.user, race=race)
for f in myfollows: # pragma: no cover
f.delete()
otherrecords = IndoorVirtualRaceResult.objects.filter(
race=race).exclude(userid=r.id)
for otherrecord in otherrecords:
try:
otheruser = Rower.objects.get(id=otherrecord.userid)
othername = otheruser.user.first_name+' '+otheruser.user.last_name
registeredname = r.user.first_name+' '+r.user.last_name
if otherrecord.emailnotifications:
_ = myqueue(
queue,
handle_sendemail_raceregistration,
otheruser.user.email, othername,
registeredname,
race.name,
race.id
)
except Rower.DoesNotExist: # pragma: no cover
pass
followers = VirtualRaceFollower.objects.filter(race=race)
for follower in followers: # pragma: no cover
othername = ''
if follower.user:
othername = follower.user.first_name+' '+follower.user.last_name
registeredname = r.user.first_name+' '+r.user.last_name
email = follower.emailaddress
_ = myqueue(
queue,
handle_sendemail_raceregistration,
email, othername,
registeredname, race.name, race.id,
)
messages.info(
request,
"You have successfully registered for this race. Good luck!"
)
url = reverse('virtualevent_view',
kwargs={
'id': race.id
})
return HttpResponseRedirect(url)
else:
initial = {
'age': calculate_age(r.birthdate),
'weightcategory': r.weightcategory,
'adaptiveclass': r.adaptiveclass,
}
categories = None
if race.coursestandards is not None: # pragma: no cover
categories = CourseStandard.objects.filter(
standardcollection=race.coursestandards).order_by("name")
form = IndoorVirtualRaceResultForm(
initial=initial, categories=categories)
breadcrumbs = [
{
'url': reverse('virtualevents_view'),
'name': 'Challenges'
},
{
'url': reverse('virtualevent_view',
kwargs={'id': race.id}
),
'name': race.name
},
{
'url': reverse(indoorvirtualevent_register_view,
kwargs={'id': race.id}
),
'name': 'Register'
}
]
buttons = []
if not request.user.is_anonymous:
if race_can_register(r, race):
buttons += ['registerbutton']
if race_can_adddiscipline(r, race): # pragma: no cover
buttons += ['adddisciplinebutton']
if race_can_submit(r, race):
buttons += ['submitbutton']
if race_can_resubmit(r, race): # pragma: no cover
buttons += ['resubmitbutton']
if race_can_withdraw(r, race): # pragma: no cover
buttons += ['withdrawbutton']
if race_can_edit(r, race):
buttons += ['editbutton']
return render(request, 'virtualeventregister.html',
{
'form': form,
'buttons': buttons,
'race': race,
'breadcrumbs': breadcrumbs,
'userid': r.user.id,
})
@login_required()
def indoorvirtualevent_create_view(request):
r = getrower(request.user)
if request.method == 'POST':
racecreateform = IndoorVirtualRaceForm(request.POST)
if racecreateform.is_valid():
cd = racecreateform.cleaned_data
startdate = cd['startdate']
start_time = cd['start_time']
enddate = cd['enddate']
end_time = cd['end_time']
comment = cd['comment']
sessionunit = cd['sessionunit']
sessionvalue = cd['sessionvalue']
name = cd['name']
registration_form = cd['registration_form']
registration_closure = cd['registration_closure']
evaluation_closure = cd['evaluation_closure']
contact_phone = cd['contact_phone']
contact_email = cd['contact_email']
coursestandards = cd['coursestandards']
# correct times
timezone_str = cd['timezone']
startdatetime = datetime.datetime.combine(startdate, start_time)
enddatetime = datetime.datetime.combine(enddate, end_time)
startdatetime = pytz.timezone(timezone_str).localize(
startdatetime
)
enddatetime = pytz.timezone(timezone_str).localize(
enddatetime
)
evaluation_closure = pytz.timezone(timezone_str).localize(
evaluation_closure.replace(tzinfo=None)
)
if registration_form == 'manual': # pragma: no cover
try:
registration_closure = pytz.timezone(
timezone_str
).localize(
registration_closure.replace(tzinfo=None)
)
except AttributeError:
registration_closure = startdatetime
elif registration_form == 'windowstart': # pragma: no cover
registration_closure = startdatetime
elif registration_form == 'windowend': # pragma: no cover
registration_closure = enddatetime
else:
registration_closure = evaluation_closure
if sessionunit == 'min': # pragma: no cover
sessionmode = 'time'
else:
sessionmode = 'distance'
vs = VirtualRace(
name=name,
startdate=startdate,
preferreddate=startdate,
start_time=start_time,
enddate=enddate,
end_time=end_time,
comment=comment,
sessiontype='indoorrace',
sessionunit=sessionunit,
sessionmode=sessionmode,
sessionvalue=sessionvalue,
course=None,
timezone=timezone_str,
coursestandards=coursestandards,
evaluation_closure=evaluation_closure,
registration_closure=registration_closure,
contact_phone=contact_phone,
contact_email=contact_email,
country='Indoor',
manager=request.user,
)
vs.save()
announcementshort = "New Virtual Indoor Challenge on rowsandall.com: {name}".format(
name=name,
)
announcement = announcementshort + " {siteurl}/rowers/virtualevent/{raceid}/".format(
siteurl=SITE_URL,
raceid=vs.id
)
if len(announcement) > 250: # pragma: no cover
announcement = announcementshort
sa = SiteAnnouncement(
announcement=announcement,
)
sa.save()
url = reverse('virtualevents_view')
return HttpResponseRedirect(url)
else:
racecreateform = IndoorVirtualRaceForm(timezone=r.defaulttimezone)
breadcrumbs = [
{
'url': reverse('virtualevents_view'),
'name': 'Challenges'
},
{
'url': reverse('indoorvirtualevent_create_view',
),
'name': 'New Indoor Virtual Regatta'
},
]
return render(request, 'indoorvirtualeventcreate.html',
{
'form': racecreateform,
'breadcrumbs': breadcrumbs,
'rower': r,
'active': 'nav-racing',
})
@login_required()
def fastestvirtualevent_create_view(request):
r = getrower(request.user)
if request.method == 'POST':
racecreateform = IndoorVirtualRaceForm(request.POST)
if racecreateform.is_valid():
cd = racecreateform.cleaned_data
startdate = cd['startdate']
start_time = cd['start_time']
enddate = cd['enddate']
end_time = cd['end_time']
comment = cd['comment']
sessionunit = cd['sessionunit']
sessionvalue = cd['sessionvalue']
name = cd['name']
registration_form = cd['registration_form']
registration_closure = cd['registration_closure']
evaluation_closure = cd['evaluation_closure']
contact_phone = cd['contact_phone']
contact_email = cd['contact_email']
coursestandards = cd['coursestandards']
# correct times
timezone_str = cd['timezone']
startdatetime = datetime.datetime.combine(startdate, start_time)
enddatetime = datetime.datetime.combine(enddate, end_time)
startdatetime = pytz.timezone(timezone_str).localize(
startdatetime
)
enddatetime = pytz.timezone(timezone_str).localize(
enddatetime
)
evaluation_closure = pytz.timezone(timezone_str).localize(
evaluation_closure.replace(tzinfo=None)
)
if registration_form == 'manual': # pragma: no cover
try:
registration_closure = pytz.timezone(
timezone_str
).localize(
registration_closure.replace(tzinfo=None)
)
except AttributeError:
registration_closure = startdatetime
elif registration_form == 'windowstart': # pragma: no cover
registration_closure = startdatetime
elif registration_form == 'windowend': # pragma: no cover
registration_closure = enddatetime
else:
registration_closure = evaluation_closure
if sessionunit == 'min': # pragma: no cover
sessionmode = 'time'
sessiontype = 'fastest_time'
else:
sessionmode = 'distance'
sessiontype = 'fastest_distance'
vs = VirtualRace(
name=name,
startdate=startdate,
preferreddate=startdate,
start_time=start_time,
enddate=enddate,
end_time=end_time,
comment=comment,
sessiontype=sessiontype,
sessionunit=sessionunit,
sessionmode=sessionmode,
sessionvalue=sessionvalue,
course=None,
timezone=timezone_str,
coursestandards=coursestandards,
evaluation_closure=evaluation_closure,
registration_closure=registration_closure,
contact_phone=contact_phone,
contact_email=contact_email,
country='Indoor',
manager=request.user,
)
vs.save()
if vs.sessiontype == 'fastest_distance':
vs.approximate_distance = vs.sessionvalue
vs.save()
announcementshort = "New Virtual Challenge on rowsandall.com: {name}".format(
name=name,
)
announcement = announcementshort + " {siteurl}/rowers/virtualevent/{raceid}/".format(
siteurl=SITE_URL,
raceid=vs.id
)
if len(announcement) > 250: # pragma: no cover
announcement = announcementshort
sa = SiteAnnouncement(
announcement=announcement,
)
sa.save()
url = reverse('virtualevents_view')
return HttpResponseRedirect(url)
else:
racecreateform = IndoorVirtualRaceForm(timezone=r.defaulttimezone)
breadcrumbs = [
{
'url': reverse('virtualevents_view'),
'name': 'Challenges'
},
{
'url': reverse('indoorvirtualevent_create_view',
),
'name': 'New Indoor Virtual Regatta'
},
]
return render(request, 'fastestvirtualeventcreate.html',
{
'form': racecreateform,
'breadcrumbs': breadcrumbs,
'rower': r,
'active': 'nav-racing',
})
@login_required()
def virtualevent_create_view(request):
r = getrower(request.user)
if request.method == 'POST':
racecreateform = VirtualRaceForm(request.POST)
if racecreateform.is_valid():
cd = racecreateform.cleaned_data
startdate = cd['startdate']
start_time = cd['start_time']
enddate = cd['enddate']
end_time = cd['end_time']
comment = cd['comment']
course = cd['course']
name = cd['name']
registration_form = cd['registration_form']
registration_closure = cd['registration_closure']
evaluation_closure = cd['evaluation_closure']
contact_phone = cd['contact_phone']
contact_email = cd['contact_email']
coursestandards = cd['coursestandards']
# correct times
geocourse = GeoCourse.objects.get(id=course.id)
timezone_str = get_course_timezone(geocourse)
startdatetime = datetime.datetime.combine(startdate, start_time)
enddatetime = datetime.datetime.combine(enddate, end_time)
startdatetime = pytz.timezone(timezone_str).localize(
startdatetime
)
enddatetime = pytz.timezone(timezone_str).localize(
enddatetime
)
evaluation_closure = pytz.timezone(timezone_str).localize(
evaluation_closure.replace(tzinfo=None)
)
if registration_form == 'manual': # pragma: no cover
try:
registration_closure = pytz.timezone(
timezone_str
).localize(
registration_closure.replace(tzinfo=None)
)
except AttributeError:
registration_closure = startdatetime
elif registration_form == 'windowstart': # pragma: no cover
registration_closure = startdatetime
elif registration_form == 'windowend': # pragma: no cover
registration_closure = enddatetime
else:
registration_closure = evaluation_closure
vs = VirtualRace(
name=name,
startdate=startdate,
preferreddate=startdate,
start_time=start_time,
enddate=enddate,
end_time=end_time,
course=geocourse,
comment=comment,
sessiontype='race',
timezone=timezone_str,
evaluation_closure=evaluation_closure,
registration_closure=registration_closure,
contact_phone=contact_phone,
coursestandards=coursestandards,
contact_email=contact_email,
country=course.country,
manager=request.user,
)
vs.save()
announcementshort = "New Virtual Challenge on rowsandall.com: {name} on course {course}".format(
name=name,
course=course.name,
)
announcement = announcementshort + " {siteurl}/rowers/virtualevent/{raceid}/".format(
siteurl=SITE_URL,
raceid=vs.id
)
if len(announcement) > 250: # pragma: no cover
announcement = announcementshort
sa = SiteAnnouncement(
announcement=announcement,
)
sa.save()
url = reverse('virtualevents_view')
return HttpResponseRedirect(url)
else:
racecreateform = VirtualRaceForm()
breadcrumbs = [
{
'url': reverse('virtualevents_view'),
'name': 'Challenges'
},
{
'url': reverse(virtualevent_create_view,
),
'name': 'New Virtual Regatta'
},
]
return render(request, 'virtualeventcreate.html',
{
'form': racecreateform,
'breadcrumbs': breadcrumbs,
'rower': r,
'active': 'nav-racing',
})
@login_required()
@permission_required('virtualevent.change_race', fn=get_virtualevent_by_pk, raise_exception=True)
def virtualevent_edit_view(request, id=0):
r = getrower(request.user)
race = get_object_or_404(VirtualRace, pk=id)
start_time = race.start_time
start_date = race.startdate
startdatetime = datetime.datetime.combine(start_date, start_time)
startdatetime = pytz.timezone(race.timezone).localize(
startdatetime
)
end_time = race.end_time
end_date = race.enddate
enddatetime = datetime.datetime.combine(end_date, end_time)
enddatetime = pytz.timezone(race.timezone).localize(
enddatetime
)
if timezone.now() > enddatetime: # pragma: no cover
messages.error(
request, "You cannot edit a race after the end of the race window")
url = reverse('virtualevent_view',
kwargs={
'id': race.id,
})
if request.method == 'POST':
racecreateform = VirtualRaceForm(request.POST, instance=race)
if racecreateform.is_valid():
cd = racecreateform.cleaned_data
res, message = update_virtualrace(race, cd)
if res:
messages.info(request, message)
else: # pragma: no cover
messages.error(request, message)
url = reverse('virtualevent_view',
kwargs={
'id': race.id
})
return HttpResponseRedirect(url)
else:
racecreateform = VirtualRaceForm(instance=race)
breadcrumbs = [
{
'url': reverse('virtualevents_view'),
'name': 'Challenges'
},
{
'url': reverse('virtualevent_view',
kwargs={'id': race.id}
),
'name': race.name
},
{
'url': reverse(virtualevent_edit_view,
kwargs={'id': race.id}
),
'name': 'Edit'
}
]
buttons = []
if not request.user.is_anonymous:
if race_can_register(r, race):
buttons += ['registerbutton']
if race_can_adddiscipline(r, race): # pragma: no cover
buttons += ['adddisciplinebutton']
if race_can_submit(r, race): # pragma: no cover
buttons += ['submitbutton']
if race_can_resubmit(r, race): # pragma: no cover
buttons += ['resubmitbutton']
if race_can_withdraw(r, race): # pragma: no cover
buttons += ['withdrawbutton']
if race_can_edit(r, race):
buttons += ['editbutton']
return render(request, 'virtualeventedit.html',
{
'form': racecreateform,
'breadcrumbs': breadcrumbs,
'buttons': buttons,
'rower': r,
'race': race,
})
@login_required()
@permission_required('virtualevent.change_race', fn=get_virtualevent_by_pk, raise_exception=True)
def indoorvirtualevent_edit_view(request, id=0):
r = getrower(request.user)
race = get_object_or_404(VirtualRace, pk=id)
start_time = race.start_time
start_date = race.startdate
startdatetime = datetime.datetime.combine(start_date, start_time)
startdatetime = pytz.timezone(race.timezone).localize(
startdatetime
)
end_time = race.end_time
end_date = race.enddate
enddatetime = datetime.datetime.combine(end_date, end_time)
enddatetime = pytz.timezone(race.timezone).localize(
enddatetime
)
if timezone.now() > enddatetime: # pragma: no cover
messages.error(
request, "You cannot edit a race after the end of the race window")
url = reverse('virtualevent_view',
kwargs={
'id': race.id,
})
if request.method == 'POST':
racecreateform = IndoorVirtualRaceForm(request.POST, instance=race)
if racecreateform.is_valid():
cd = racecreateform.cleaned_data
res, message = update_indoorvirtualrace(race, cd)
if res:
messages.info(request, message)
else: # pragma: no cover
messages.error(request, message)
url = reverse('virtualevent_view',
kwargs={
'id': race.id
})
return HttpResponseRedirect(url)
else:
racecreateform = IndoorVirtualRaceForm(instance=race)
breadcrumbs = [
{
'url': reverse('virtualevents_view'),
'name': 'Challenges'
},
{
'url': reverse('virtualevent_view',
kwargs={'id': race.id}
),
'name': race.name
},
{
'url': reverse(indoorvirtualevent_edit_view,
kwargs={'id': race.id}
),
'name': 'Edit'
}
]
buttons = []
if not request.user.is_anonymous:
if race_can_register(r, race):
buttons += ['registerbutton']
if race_can_adddiscipline(r, race): # pragma: no cover
buttons += ['adddisciplinebutton']
if race_can_submit(r, race): # pragma: no cover
buttons += ['submitbutton']
if race_can_resubmit(r, race): # pragma: no cover
buttons += ['resubmitbutton']
if race_can_withdraw(r, race): # pragma: no cover
buttons += ['withdrawbutton']
if race_can_edit(r, race):
buttons += ['editbutton']
return render(request, 'virtualeventedit.html',
{
'form': racecreateform,
'buttons': buttons,
'breadcrumbs': breadcrumbs,
'rower': r,
'race': race,
})
@login_required()
def virtualevent_submit_result_view(request, id=0, workoutid=0):
r = getrower(request.user)
try:
race = VirtualRace.objects.get(id=id)
except VirtualRace.DoesNotExist: # pragma: no cover
raise Http404("Virtual Challenge does not exist")
start_time = race.start_time
start_date = race.startdate
startdatetime = datetime.datetime.combine(start_date, start_time)
startdatetime = pytz.timezone(race.timezone).localize(startdatetime)
end_time = race.end_time
end_date = race.enddate
enddatetime = datetime.datetime.combine(end_date, end_time)
enddatetime = pytz.timezone(race.timezone).localize(enddatetime)
can_submit = race_can_submit(r, race) or race_can_resubmit(r, race)
if race.sessiontype == 'race':
resultobj = VirtualRaceResult
else:
resultobj = IndoorVirtualRaceResult
records = resultobj.objects.filter(
userid=r.id,
race=race
)
if records.count() == 0: # pragma: no cover
(
hasinitial,
boattype,
boatclass,
adaptiveclass,
weightclass,
sex,
referencespeed,
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,
referencespeed=referencespeed,
)
record.save()
records = [record]
entrychoices = []
for record in records:
rtpl = (record.id, record.__str__())
entrychoices.append(rtpl)
entries = {}
entries['choices'] = entrychoices
entries['initial'] = [records[0].id]
if not can_submit: # pragma: no cover
messages.error(request, 'You cannot submit a result to this race')
url = reverse('virtualevent_view',
kwargs={
'id': id
}
)
return HttpResponseRedirect(url)
ws = Workout.objects.filter(
user=r,
# workouttype__in=mytypes.rowtypes,
startdatetime__gte=startdatetime,
startdatetime__lte=enddatetime,
distance__gte=race.approximate_distance,
).order_by("-date", "-startdatetime", "id")
if not ws: # pragma: no cover
messages.info(
request,
'You have no workouts executed during the race window. Please upload a result or enter it manually.'
)
url = reverse('virtualevent_view',
kwargs={
'id': id
})
return HttpResponseRedirect(url)
initialworkouts = [w.id for w in Workout.objects.filter(
user=r, plannedsession=race
)]
workoutdata = {}
workoutdata['initial'] = []
choices = []
for w in ws:
wtpl = (w.id, w.__str__())
choices.append(wtpl)
if w.id in initialworkouts: # pragma: no cover
workoutdata['initial'].append(w.id)
workoutdata['choices'] = tuple(choices)
if request.method == 'POST':
w_form = WorkoutRaceSelectForm(workoutdata, entries, request.POST)
if w_form.is_valid():
selectedworkout = w_form.cleaned_data['workouts']
splitsecond = 0
recordid = w_form.cleaned_data['record']
else:
selectedworkout = None
if selectedworkout is not None:
workouts = Workout.objects.filter(id=selectedworkout)
if race.sessiontype == 'race':
result, comments, errors, jobid = add_workout_race(
workouts, race, r,
splitsecond=splitsecond, recordid=recordid)
elif race.sessiontype in ['fastest_time', 'fastest_distance']: # pragma: no cover
result, comments, errors, jobid = add_workout_fastestrace(
workouts, race, r, recordid=recordid
)
else:
result, comments, errors, jobid = add_workout_indoorrace(
workouts, race, r, recordid=recordid)
for c in comments:
messages.info(request, c)
for er in errors:
messages.error(request, er)
if jobid:
try:
request.session['async_tasks'] += [(jobid, 'submit_race')]
except KeyError:
request.session['async_tasks'] = [(jobid, 'submit_race')]
messages.info(
request, "We are evaluating your result."
" The page will reload when we're done. Your result will show up if you adhered"
" to the course")
if result:
otherrecords = resultobj.objects.filter(
race=race).exclude(userid=r.id)
if not jobid:
messages.info(request, "Result submitted successfully.")
for otherrecord in otherrecords:
try:
otheruser = Rower.objects.get(id=otherrecord.userid)
othername = otheruser.user.first_name+' '+otheruser.user.last_name
registeredname = r.user.first_name+' '+r.user.last_name
if otherrecord.emailnotifications:
_ = myqueue(
queue,
handle_sendemail_racesubmission,
otheruser.user.email, othername,
registeredname,
race.name,
race.id
)
except Rower.DoesNotExist: # pragma: no cover
pass
followers = VirtualRaceFollower.objects.filter(race=race)
for follower in followers: # pragma: no cover
othername = ''
if follower.user:
othername = follower.user.first_name+' '+follower.user.last_name
registeredname = r.user.first_name+' '+r.user.last_name
email = follower.emailaddress
_ = myqueue(
queue,
handle_sendemail_racesubmission,
email, othername,
registeredname, race.name, race.id,
)
# redirect to race page
url = reverse('virtualevent_view',
kwargs={
'id': race.id
})
return HttpResponseRedirect(url)
else:
if workoutid:
workoutdata['initial'] = encoder.decode_hex(workoutid)
w_form = WorkoutRaceSelectForm(workoutdata, entries)
breadcrumbs = [
{
'url': reverse('virtualevents_view'),
'name': 'Challenges'
},
{
'url': reverse('virtualevent_view',
kwargs={'id': race.id}
),
'name': race.name
},
{
'url': reverse(virtualevent_submit_result_view,
kwargs={'id': race.id}
),
'name': 'Submit Result'
}
]
buttons = []
if not request.user.is_anonymous:
if race_can_register(r, race): # pragma: no cover
buttons += ['registerbutton']
if race_can_adddiscipline(r, race):
buttons += ['adddisciplinebutton']
if race_can_submit(r, race):
buttons += ['submitbutton']
if race_can_resubmit(r, race): # pragma: no cover
buttons += ['resubmitbutton']
if race_can_withdraw(r, race): # pragma: no cover
buttons += ['withdrawbutton']
if race_can_edit(r, race):
buttons += ['editbutton']
return render(request, 'race_submit.html',
{
'race': race,
'buttons': buttons,
'workouts': ws,
'breadcrumbs': breadcrumbs,
'active': 'nav-racing',
'rower': r,
'w_form': w_form,
})
def addfollower_view(request, id=0):
try:
race = VirtualRace.objects.get(id=id)
except VirtualRace.DoesNotExist: # pragma: no cover
raise Http404("Virtual Challenge does not exist")
if not request.user.is_anonymous:
follower = VirtualRaceFollower(
user=request.user,
race=race,
emailaddress=request.user.email
)
follower.save()
messages.info(
request, "You will receive challenge notifications per email")
url = reverse(virtualevent_view,
kwargs={'id': id})
return HttpResponseRedirect(url)
# Anonymous
if request.method == 'POST': # pragma: no cover
form = FollowerForm(request.POST)
if form.is_valid():
email = form.cleaned_data['emailaddress']
follower = VirtualRaceFollower(
race=race,
emailaddress=email
)
follower.save()
messages.info(
request, "You will receive challenge notifications per email")
url = reverse(virtualevent_view,
kwargs={'id': id})
return HttpResponseRedirect(url)
else: # pragma: no cover
form = FollowerForm()
breadcrumbs = [
{
'url': reverse('virtualevents_view'),
'name': 'Challenges'
},
{
'url': reverse('virtualevent_view',
kwargs={'id': race.id}
),
'name': race.name
},
{
'url': reverse(addfollower_view,
kwargs={'id': race.id}
),
'name': 'Follow'
}
] # pragma: no cover
return render(request, 'followerform.html',
{
'form': form,
'active': 'nav-racing',
'breadcrumbs': breadcrumbs,
}
) # pragma: no cover
@login_required()
def virtualevent_entry_edit_view(request, id=0, entryid=0):
r = getrower(request.user)
try:
race = VirtualRace.objects.get(id=id)
except VirtualRace.DoesNotExist: # pragma: no cover
raise Http404("Virtual Challenge does not exist")
if not race_can_editentry(r, race): # pragma: no cover
messages.error(
request, 'You cannot change your entries for this challenge')
url = reverse('virtualevent_view',
kwargs={'id': race.id}
)
return HttpResponseRedirect(url)
categories = None
if race.coursestandards is not None:
categories = CourseStandard.objects.filter(
standardcollection=race.coursestandards).order_by("name")
if race.sessiontype == 'race':
resultobj = VirtualRaceResult
formobj = VirtualRaceResultForm
elif race.sessiontype in ['fastest_distance', 'fastest_time']: # pragma: no cover
resultobj = IndoorVirtualRaceResult
formobj = VirtualRaceResultForm
else: # pragma: no cover
resultobj = IndoorVirtualRaceResult
formobj = IndoorVirtualRaceResultForm
records = resultobj.objects.filter(
userid=r.id,
race=race
).exclude(id=entryid)
try:
record = resultobj.objects.get(id=entryid)
except resultobj.DoesNotExist: # pragma: no cover
raise Http404("Could not find your entry")
if request.method == 'POST':
form = formobj(request.POST, categories=categories)
if form.is_valid():
cd = form.cleaned_data
teamname = cd['teamname']
try:
boattype = cd['boattype']
except KeyError: # pragma: no cover
boattype = None
boatclass = cd['boatclass']
weightcategory = cd['weightcategory']
adaptiveclass = cd['adaptiveclass']
age = cd['age']
try:
mix = cd['mix']
except KeyError: # pragma: no cover
mix = None
acceptsocialmedia = cd['acceptsocialmedia']
sex = r.sex
if mix: # pragma: no cover
sex = 'mixed'
if boattype == '1x' and r.birthdate:
age = calculate_age(r.birthdate)
if sex == 'not specified':
sex = 'male'
coursestandard = None
referencespeed = 5.0
returnurl = reverse(virtualevent_entry_edit_view,
kwargs={'id': race.id,
'entryid': record.id})
if race.coursestandards is not None:
coursestandard = cd['entrycategory']
referencespeed = coursestandard.referencespeed
boattype = coursestandard.boattype
boatclass = coursestandard.boatclass
weightcategory = coursestandard.weightclass
adaptiveclass = coursestandard.adaptiveclass
if age < coursestandard.agemin: # pragma: no cover
messages.error(
request, 'You are younger than the minimum age for this group')
return HttpResponseRedirect(returnurl)
if age > coursestandard.agemax: # pragma: no cover
messages.error(
request, 'You are older than the maximum age for this group')
return HttpResponseRedirect(returnurl)
if sex == 'male' and coursestandard.sex != 'male': # pragma: no cover
messages.error(
request, 'Men are not allowed to enter this category')
return HttpResponseRedirect(returnurl)
if sex == 'mixed' and coursestandard.sex not in ['mixed', 'male']: # pragma: no cover
messages.error(
request, 'Mixed crews are not allowed to enter this category')
return HttpResponseRedirect(returnurl)
if record.workoutid: # pragma: no cover
try:
w = Workout.objects.get(id=record.workoutid)
except Workout.DoesNotExist: # pragma: no cover
w = None
if w is not None:
if boattype != w.boattype:
messages.error(
request, 'You cannot change boat type to a different one than your row')
return HttpResponseRedirect(returnurl)
if boatclass != w.workouttype:
messages.error(
request, 'You cannot change the class to a different one than your row')
return HttpResponseRedirect(returnurl)
if weightcategory != w.weightcategory:
messages.error(
request, 'You cannot change weight class to a different one than your row')
return HttpResponseRedirect(returnurl)
if adaptiveclass != w.adaptiveclass:
messages.error(
request, 'You cannot change adaptive class to a different one than your row')
return HttpResponseRedirect(returnurl)
else:
if boattype != record.boattype:
messages.error(
request, 'You cannot change boat type to a different one ')
return HttpResponseRedirect(returnurl)
if boatclass != record.boatclass:
messages.error(
request, 'You cannot change the class to a different one ')
return HttpResponseRedirect(returnurl)
if weightcategory != record.weightcategory:
messages.error(
request, 'You cannot change weight class to a different one ')
return HttpResponseRedirect(returnurl)
if adaptiveclass != record.adaptiveclass:
messages.error(
request, 'You cannot change adaptive class to a different one ')
return HttpResponseRedirect(returnurl)
if record.points != 0: # pragma: no cover
if race.sessiontype == 'race':
coursedistance = race.course.distance
else:
coursedistance = record.distance
v = coursedistance / \
timefield_to_seconds_duration(record.duration)
points = 100.*(2-(referencespeed/v))
record.points = points
record.teamname = teamname
record.weightcategory = weightcategory
record.adaptiveclass = adaptiveclass
record.boatclass = boatclass
if race.sessiontype == 'race':
record.boattype = boattype
record.mix = mix
record.sex = sex
record.age = age
record.entrycategory = coursestandard
record.referencespeed = referencespeed
record.acceptsocialmedia = acceptsocialmedia
duplicates = False
for otherrecord in records:
if record.isduplicate(otherrecord): # pragma: no cover
duplicates = True
if duplicates: # pragma: no cover
messages.error(request, "You have already entered this group")
return HttpResponseRedirect(returnurl)
else:
record.save()
messages.info(
request,
"You have successfully altered your entry for this race. Good luck!"
)
url = reverse('virtualevent_view',
kwargs={
'id': race.id
})
return HttpResponseRedirect(url)
else:
form = formobj(instance=record, categories=categories)
breadcrumbs = [
{
'url': reverse('virtualevents_view'),
'name': 'Challenges'
},
{
'url': reverse('virtualevent_view',
kwargs={'id': race.id}
),
'name': race.name
},
{
'url': reverse(virtualevent_entry_edit_view,
kwargs={'id': race.id,
'entryid': entryid}
),
'name': 'Follow'
}
]
buttons = []
if not request.user.is_anonymous:
if race_can_register(r, race): # pragma: no cover
buttons += ['registerbutton']
if race_can_adddiscipline(r, race):
buttons += ['adddisciplinebutton']
if race_can_submit(r, race):
buttons += ['submitbutton']
if race_can_resubmit(r, race): # pragma: no cover
buttons += ['resubmitbutton']
if race_can_withdraw(r, race): # pragma: no cover
buttons += ['withdrawbutton']
if race_can_edit(r, race):
buttons += ['editbutton']
return render(request, 'entryedit.html',
{
'form': form,
'active': 'nav-racing',
'breadcrumbs': breadcrumbs,
'userid': r.user.id,
'race': race,
})