From 6a9b61bef3057bd6382ffbe599be066362994559 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Thu, 19 Apr 2018 13:28:12 +0200
Subject: [PATCH] register and withdraw done
---
rowers/models.py | 37 ++++++++--
rowers/plannedsessions.py | 107 ++++++++++++++++++++++++++++-
rowers/templates/virtualevent.html | 66 +++++++++++++++++-
rowers/urls.py | 2 +
rowers/views.py | 71 +++++++++++++++++--
5 files changed, 270 insertions(+), 13 deletions(-)
diff --git a/rowers/models.py b/rowers/models.py
index dade1028..20b86584 100644
--- a/rowers/models.py
+++ b/rowers/models.py
@@ -422,6 +422,12 @@ def course_length(course):
return int(totaldist)
+sexcategories = (
+ ('male','male'),
+ ('female','female'),
+ ('not specified','not specified'),
+)
+
# Extension of User with rowing specific data
class Rower(models.Model):
weightcategories = (
@@ -429,11 +435,6 @@ class Rower(models.Model):
('lwt','light-weight'),
)
- sexcategories = (
- ('male','male'),
- ('female','female'),
- ('not specified','not specified'),
- )
stravatypes = (
('Ride','Ride'),
@@ -1066,6 +1067,10 @@ class VirtualRace(PlannedSession):
end_time = models.TimeField(blank=True,null=True)
country = models.CharField(max_length=100,blank=True)
+ timezone = models.CharField(default='UTC',
+ choices=timezones,
+ max_length=100)
+
phone_regex = RegexValidator(
regex=r'^\+?1?\d{9,15}$',
message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed."
@@ -1087,6 +1092,8 @@ class VirtualRace(PlannedSession):
)
return stri
+
+
# Date input utility
class DateInput(forms.DateInput):
@@ -1199,12 +1206,12 @@ class PlannedSessionFormSmall(ModelForm):
'manager': forms.HiddenInput(),
}
+boattypes = types.boattypes
# Workout
class Workout(models.Model):
workouttypes = types.workouttypes
workoutsources = types.workoutsources
- boattypes = types.boattypes
privacychoices = types.privacychoices
user = models.ForeignKey(Rower)
@@ -1317,6 +1324,24 @@ def auto_delete_strokedata_on_delete(sender, instance, **kwargs):
conn.close()
engine.dispose()
+# Virtual Race results (for keeping results when workouts are deleted)
+class VirtualRaceResult(models.Model):
+ user = models.ForeignKey(Rower)
+ username = models.CharField(max_length=150)
+ workout = models.ForeignKey(Workout)
+ race = models.ForeignKey(VirtualRace)
+ duration = models.TimeField(default=3600)
+ boattype = models.CharField(choices=boattypes,max_length=40,
+ default='1x',
+ verbose_name = 'Boat Type'
+ )
+
+ sex = models.CharField(default="not specified",
+ max_length=30,
+ choices=sexcategories,
+ verbose_name='Gender')
+
+
from rowers.metrics import rowingmetrics
strokedatafields = {
diff --git a/rowers/plannedsessions.py b/rowers/plannedsessions.py
index f4c58ad5..7aa5f311 100644
--- a/rowers/plannedsessions.py
+++ b/rowers/plannedsessions.py
@@ -477,6 +477,7 @@ def update_virtualrace(ps,cd):
ps.registration_closure.replace(tzinfo=None)
)
+ ps.timezone = timezone_str
ps.save()
@@ -488,6 +489,110 @@ def race_rower_status(r,race):
is_complete = is_session_complete_ws(ws,race)[1]
- has_registered = r in race.rower
+ has_registered = r in race.rower.all()
return is_complete,has_registered
+
+
+def race_can_submit(r,race):
+ if r not in race.rower.all():
+ return False
+
+ start_time = race.start_time
+ start_date = race.startdate
+ startdatetime = datetime.combine(start_date,start_time)
+ startdatetime = pytz.timezone(race.timezone).localize(
+ startdatetime
+ )
+ evaluation_closure = race.evaluation_closure
+
+
+ if timezone.now() > startdatetime and timezone.now() < evaluation_closure:
+ is_complete,has_registered = race_rower_status(r,race)
+ if is_complete == 'not done':
+ return True
+ else:
+ return False
+ else:
+ return False
+
+ return False
+
+def race_can_resubmit(r,race):
+ if r not in race.rower.all():
+ return False
+
+ start_time = race.start_time
+ start_date = race.startdate
+ startdatetime = datetime.combine(start_date,start_time)
+ startdatetime = pytz.timezone(race.timezone).localize(
+ startdatetime
+ )
+ evaluation_closure = race.evaluation_closure
+
+
+ if timezone.now() > startdatetime and timezone.now() < evaluation_closure:
+ is_complete,has_registered = race_rower_status(r,race)
+ if is_complete in ['partial','completed']:
+ return True
+ else:
+ return False
+ else:
+ return False
+
+ return False
+
+def race_can_withdraw(r,race):
+ if r not in race.rower.all():
+ return False
+
+ start_time = race.start_time
+ start_date = race.startdate
+ startdatetime = datetime.combine(start_date,start_time)
+ startdatetime = pytz.timezone(race.timezone).localize(
+ startdatetime
+ )
+
+ registration_closure = race.registration_closure
+ if registration_closure is not None and registration_closure != '':
+ if timezone.now() > registration_closure:
+ return False
+ elif timezone.now() > startdatetime:
+ return False
+ elif timezone.now() > startdatetime:
+ return False
+
+ return True
+
+def race_can_register(r,race):
+ if r in race.rower.all():
+ return False
+
+ start_time = race.start_time
+ start_date = race.startdate
+ startdatetime = datetime.combine(start_date,start_time)
+ startdatetime = pytz.timezone(race.timezone).localize(
+ startdatetime
+ )
+
+ registration_closure = race.registration_closure
+ if registration_closure is not None and registration_closure != '':
+ if timezone.now() > registration_closure:
+ return False
+ elif timezone.now() > startdatetime:
+ return False
+ elif timezone.now() > startdatetime:
+ return False
+
+ return True
+
+def add_rower_race(r,race):
+ race.rower.add(r)
+ race.save()
+
+ return 1
+
+def remove_rower_race(r,race):
+ race.rower.remove(r)
+
+ return 1
diff --git a/rowers/templates/virtualevent.html b/rowers/templates/virtualevent.html
index 3c50175a..7f7f32d1 100644
--- a/rowers/templates/virtualevent.html
+++ b/rowers/templates/virtualevent.html
@@ -29,6 +29,12 @@
| Course | {{ race.course }} |
+ {% if race.has_registration %}
+
+ | Registration closure |
+ {{ race.registration_closure }} |
+
+ {% endif %}
| Date | {{ race.startdate }} |
@@ -55,9 +61,31 @@
Results
@@ -65,6 +93,42 @@
No results yet
+
+
Rules
+
+ As a rowsandall.com user, you can
+ register to take part in this event.
+ If the race organizer has set a registration deadline, you must
+ register before the deadline. Otherwise, it is sufficient to
+ register before the start of the race window.
+ You can always withdraw from participating before the registration
+ deadline or the start of the race window, if no registration
+ deadline was set.
+
+
+ After the start of the race window and before the submission deadline,
+ you can submit results by linking the race to one of your uploaded
+ workouts. The workout start time must be within the race window
+ and your trajectory must pass through the blue polygons on the course
+ map (in the right order), for your result to be valid.
+
+
+ The results table has a link to a page where details of your workout
+ are shown.
+
+
+ Race results are stored permanently and are not deleted when
+ you delete the respective workout or remove your account.
+ By registering, you agree with this and the race rules.
+
+
+ Virtual Racing on rowsandall.com is honors based. Please be a good
+ sport, submit real results rowed by you, and make sure you set the
+ boat type correctly. For (future functionality) age and gender
+ corrected times, please be sure your gender and birth date are set
+ correctly in your user settings.
+
+
Course
diff --git a/rowers/urls.py b/rowers/urls.py
index 8baf56d0..c28fbbc7 100644
--- a/rowers/urls.py
+++ b/rowers/urls.py
@@ -147,6 +147,8 @@ urlpatterns = [
url(r'^virtualevent/create$',views.virtualevent_create_view),
url(r'^virtualevent/(?P\d+)$',views.virtualevent_view),
url(r'^virtualevent/(?P\d+)/edit$',views.virtualevent_edit_view),
+ url(r'^virtualevent/(?P\d+)/register$',views.virtualevent_register_view),
+ url(r'^virtualevent/(?P\d+)/withdraw$',views.virtualevent_withdraw_view),
url(r'^list-workouts/$',views.workouts_view),
url(r'^list-courses/$',views.courses_view),
url(r'^courses/upload$',views.course_upload_view),
diff --git a/rowers/views.py b/rowers/views.py
index b65ba078..320ac3e3 100644
--- a/rowers/views.py
+++ b/rowers/views.py
@@ -13376,7 +13376,10 @@ def virtualevents_view(request):
)
def virtualevent_view(request,id=0):
- r = getrower(request.user)
+ if not request.user.is_anonymous():
+ r = getrower(request.user)
+ else:
+ r = None
try:
race = VirtualRace.objects.get(id=id)
@@ -13384,7 +13387,21 @@ def virtualevent_view(request,id=0):
raise Http404("Virtual Race does not exist")
script,div = course_map(race.course)
- is_complete,has_registered = race_rower_status(r,race)
+
+ buttons = []
+
+ if not request.user.is_anonymous():
+ if race_can_register(r,race):
+ buttons += ['registerbutton']
+
+ if race_can_submit(r,race):
+ buttons += ['submitbutton']
+
+ if race_can_resubmit(r,race):
+ buttons += ['resubmitbutton']
+
+ if race_can_withdraw(r,race):
+ buttons += ['withdrawbutton']
return render(request,'virtualevent.html',
@@ -13392,11 +13409,54 @@ def virtualevent_view(request,id=0):
'coursescript':script,
'coursediv':div,
'race':race,
- 'rower':r
- 'has_registered':has_registered,
- 'has_rowed':is_complete,
+ 'rower':r,
+ 'buttons':buttons,
})
+@login_required()
+def virtualevent_withdraw_view(request,id=0):
+ r = getrower(request.user)
+ try:
+ race = VirtualRace.objects.get(id=id)
+ except VirtualRace.DoesNotExist:
+ raise Http404("Virtual Race does not exist")
+
+ if race_can_withdraw(r,race):
+ remove_rower_race(r,race)
+ messages.info(request,
+ "You have successfully withdrawn from this race.")
+ else:
+ messages.error(request,"You cannot withdraw from this race")
+
+ url = reverse(virtualevent_view,
+ kwargs = {
+ 'id':race.id
+ })
+
+ return HttpResponseRedirect(url)
+
+@login_required()
+def virtualevent_register_view(request,id=0):
+ r = getrower(request.user)
+ try:
+ race = VirtualRace.objects.get(id=id)
+ except VirtualRace.DoesNotExist:
+ raise Http404("Virtual Race does not exist")
+
+ if race_can_register(r,race):
+ add_rower_race(r,race)
+ messages.info(request,
+ "You have successfully registered for this race. Good luck!")
+ else:
+ messages.error(request,"You cannot register for this race")
+
+ url = reverse(virtualevent_view,
+ kwargs = {
+ 'id':race.id
+ })
+
+ return HttpResponseRedirect(url)
+
@login_required()
def virtualevent_create_view(request):
r = getrower(request.user)
@@ -13451,6 +13511,7 @@ def virtualevent_create_view(request):
course=geocourse,
comment=comment,
sessiontype = 'coursetest',
+ timezone=timezone_str,
has_registration=has_registration,
evaluation_closure=evaluation_closure,
registration_closure=registration_closure,