3897 lines
127 KiB
Python
3897 lines
127 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,coursetokml, coursestokml
|
|
from random import sample
|
|
|
|
# landing page for challenges & courses
|
|
def courses_challenges_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_courses = getnearestcourses(lat_lon, courses, whatisnear=2000)
|
|
liked_courses = GeoCourse.objects.filter(followers=r)
|
|
courses = GeoCourse.objects.filter(id__in=[course.id for course in nearby_courses]) | liked_courses
|
|
|
|
if courses.count() >= 3:
|
|
courses = sample(list(courses),3)
|
|
else:
|
|
courses = GeoCourse.objects.all().order_by("country", "name", "distance")
|
|
|
|
coursesdicts = []
|
|
for course in courses:
|
|
script, div = course_map(course)
|
|
coursesdicts.append({
|
|
'course': course,
|
|
'script': script,
|
|
'div': div,
|
|
})
|
|
|
|
allchallenges = VirtualRace.objects.all().order_by("-startdate")
|
|
totalnrchallenges = allchallenges.count()
|
|
challenges = VirtualRace.objects.filter(startdate__gte=timezone.now())
|
|
challenges2 = VirtualRace.objects.filter(startdate__lte=timezone.now(),
|
|
evaluation_closure__gte=timezone.now()-datetime.timedelta(days=3))
|
|
|
|
challenges = challenges | challenges2
|
|
count = 3
|
|
if totalnrchallenges > count:
|
|
allchallenges = list(allchallenges)
|
|
while len(challenges) < count:
|
|
try:
|
|
challenges = list(challenges)+sample(allchallenges, count-len(challenges))
|
|
except ValueError:
|
|
count = count-1
|
|
challenges = list(set(challenges))
|
|
else:
|
|
challenges = VirtualRace.objects.all()
|
|
count = challenges.count()
|
|
|
|
challenges = sample(list(challenges),count)
|
|
|
|
challengesdicts = []
|
|
for challenge in challenges:
|
|
script = ''
|
|
div = ''
|
|
if challenge.course:
|
|
script, div = course_map(challenge.course)
|
|
|
|
challengesdicts.append(
|
|
{
|
|
'script': script,
|
|
'div': div,
|
|
'challenge': challenge,
|
|
}
|
|
)
|
|
|
|
breadcrumbs = [
|
|
{
|
|
'url': reverse('courses_challenges_view'),
|
|
'name': 'Courses and Challenges'
|
|
}
|
|
]
|
|
|
|
|
|
return render(request, "courses_challenges.html",
|
|
{
|
|
'coursesdicts': coursesdicts,
|
|
'rower': r,
|
|
'challengesdicts': challengesdicts,
|
|
'breadcrumbs': breadcrumbs,
|
|
})
|
|
|
|
|
|
# List Courses
|
|
def courses_view(request):
|
|
r = getrower(request.user)
|
|
g = GeoIP2()
|
|
|
|
if request.method == 'POST':
|
|
try:
|
|
tdict = dict(request.POST.lists())
|
|
ids = tdict['courseid']
|
|
courseids = [int(id) for id in ids]
|
|
|
|
kmlstring = coursestokml(courseids)
|
|
kmlfilename = 'courses.kml'
|
|
response = HttpResponse(kmlstring)
|
|
response['Content-Disposition'] = 'attachment; filename="{filename}"'.format(
|
|
filename=kmlfilename)
|
|
response['Content-Type'] = 'application/octet-stream'
|
|
|
|
return response
|
|
|
|
except KeyError:
|
|
pass
|
|
except ValueError:
|
|
pass
|
|
|
|
|
|
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')
|
|
liked = request.GET.get('liked')
|
|
|
|
|
|
if nearby and lat_lon is not None: # pragma: no cover
|
|
courses = getnearestcourses(lat_lon, courses)
|
|
|
|
if liked:
|
|
courses = GeoCourse.objects.filter(followers=r)
|
|
|
|
# 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_follow_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)
|
|
course.followers.add(r)
|
|
messages.info(request,"You have liked {c}. If you use CrewNerd, you can sync your course list to CrewNerd".format(c=course))
|
|
|
|
if request_is_ajax(request):
|
|
return JSONResponse({"course": course.id})
|
|
|
|
url = reverse("course_view", kwargs={'id':course.id})
|
|
return HttpResponseRedirect(url)
|
|
|
|
@login_required()
|
|
def course_unfollow_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)
|
|
course.followers.remove(r)
|
|
messages.info(request,"You have stopped following {c}.".format(c=course))
|
|
|
|
if request_is_ajax(request):
|
|
return JSONResponse({"course": course.id})
|
|
|
|
url = reverse("courses_view")
|
|
return HttpResponseRedirect(url)
|
|
|
|
def course_view(request, id=0, workoutid=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")
|
|
|
|
# get own training results
|
|
if not request.user.is_anonymous:
|
|
ownrecords = CourseTestResult.objects.filter(
|
|
courseid = course.id,
|
|
userid = r.id,
|
|
coursecompleted=True
|
|
).order_by("duration", "-distance")
|
|
else:
|
|
ownrecords = []
|
|
|
|
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,
|
|
'ownrecords': ownrecords,
|
|
'rower': r,
|
|
'form': form,
|
|
'onlyme': onlyme,
|
|
'workoutid': workoutid,
|
|
}
|
|
)
|
|
|
|
|
|
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)
|
|
try:
|
|
cs = courses.kmltocourse(path_and_filename)
|
|
except ParseError:
|
|
os.remove(path_and_filename)
|
|
messages.error(
|
|
request, 'Something went wrong - error parsing the file')
|
|
url = reverse(course_upload_view)
|
|
|
|
if is_ajax:
|
|
return JSONResponse({'result': 0, 'url': 0})
|
|
else:
|
|
return HttpResponseRedirect(url)
|
|
|
|
for course in cs:
|
|
cname = name+' - '+course['name']
|
|
try:
|
|
cnotes = notes+'\n\n'+course['description']
|
|
except TypeError:
|
|
try:
|
|
cnotes = notes
|
|
except TypeError:
|
|
try:
|
|
cnotes = course['description']
|
|
except TypeError:
|
|
cnotes = ''
|
|
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')
|
|
participate = request.GET.get('participate')
|
|
|
|
if nearby and lat_lon is not None: # pragma: no cover
|
|
races = getnearestraces(lat_lon, races)
|
|
|
|
if participate and r is not None:
|
|
ress = VirtualRaceResult.objects.filter(userid=r.id).order_by("-race__evaluation_closure")
|
|
races = [res.race for res in ress if res.race is not None]
|
|
|
|
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").exclude(workoutsource='strava')
|
|
|
|
if not ws: # pragma: no cover
|
|
messages.info(
|
|
request,
|
|
'You have no eligible 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:
|
|
messages.error(request,"Error in form")
|
|
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:
|
|
try:
|
|
w = Workout.objects.get(id=workoutid)
|
|
if w.workoutsource != 'strava':
|
|
workoutdata['initial'] = encoder.decode_hex(workoutid)
|
|
except Workout.DoesNotExist:
|
|
pass
|
|
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,
|
|
})
|