From 49886571518edbe71084fc61e63aefc2b5de0433 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Wed, 22 Jun 2022 19:59:33 +0200
Subject: [PATCH 01/19] boatmovers init
---
boatmovers/__init__.py | 0
boatmovers/admin.py | 36 ++++++++++++
boatmovers/apps.py | 6 ++
boatmovers/migrations/0001_initial.py | 58 +++++++++++++++++++
.../0002_alter_athlete_unique_together.py | 17 ++++++
.../migrations/0003_auto_20220622_1753.py | 28 +++++++++
boatmovers/migrations/__init__.py | 0
boatmovers/models.py | 48 +++++++++++++++
boatmovers/tests.py | 3 +
boatmovers/views.py | 3 +
rowsandall_app/settings.py | 1 +
11 files changed, 200 insertions(+)
create mode 100644 boatmovers/__init__.py
create mode 100644 boatmovers/admin.py
create mode 100644 boatmovers/apps.py
create mode 100644 boatmovers/migrations/0001_initial.py
create mode 100644 boatmovers/migrations/0002_alter_athlete_unique_together.py
create mode 100644 boatmovers/migrations/0003_auto_20220622_1753.py
create mode 100644 boatmovers/migrations/__init__.py
create mode 100644 boatmovers/models.py
create mode 100644 boatmovers/tests.py
create mode 100644 boatmovers/views.py
diff --git a/boatmovers/__init__.py b/boatmovers/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/boatmovers/admin.py b/boatmovers/admin.py
new file mode 100644
index 00000000..07ac9e1b
--- /dev/null
+++ b/boatmovers/admin.py
@@ -0,0 +1,36 @@
+from django.contrib import admin
+from.models import Athlete, Crew, Race, Result
+# Register your models here.
+
+class AthleteInline(admin.StackedInline):
+ model = Athlete
+
+class AthleteAdmin(admin.ModelAdmin):
+ list_display = ('first_name', 'last_name', 'birth_year')
+
+class CrewInline(admin.StackedInline):
+ model = Athlete
+
+class CrewAdmin(admin.ModelAdmin):
+ list_display = ('name',)
+
+class RaceInline(admin.StackedInline):
+ model = Race
+
+class RaceAdmin(admin.ModelAdmin):
+ list_display = ('name',)
+
+class ResultInline(admin.StackedInline):
+ model = Result
+
+class ResultAdmin(admin.ModelAdmin):
+ list_display = ('race','crew','order')
+
+
+
+
+
+admin.site.register(Athlete, AthleteAdmin)
+admin.site.register(Crew, CrewAdmin)
+admin.site.register(Race, RaceAdmin)
+admin.site.register(Result, ResultAdmin)
diff --git a/boatmovers/apps.py b/boatmovers/apps.py
new file mode 100644
index 00000000..eb3806d9
--- /dev/null
+++ b/boatmovers/apps.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class BoatmoversConfig(AppConfig):
+ default_auto_field = 'django.db.models.BigAutoField'
+ name = 'boatmovers'
diff --git a/boatmovers/migrations/0001_initial.py b/boatmovers/migrations/0001_initial.py
new file mode 100644
index 00000000..f9b5cbb7
--- /dev/null
+++ b/boatmovers/migrations/0001_initial.py
@@ -0,0 +1,58 @@
+# Generated by Django 3.2.12 on 2022-06-22 17:41
+
+import boatmovers.models
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Athlete',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('first_name', models.CharField(max_length=200)),
+ ('last_name', models.CharField(max_length=200)),
+ ('club', models.CharField(max_length=200)),
+ ('trueskill_mu', models.FloatField(default=25.0)),
+ ('trueskill_sigma', models.FloatField(default=8.333)),
+ ('birth_year', models.IntegerField(default=1972)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Crew',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=200)),
+ ('athletes', models.ManyToManyField(to='boatmovers.Athlete')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Race',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('date', models.DateField(default=boatmovers.models.current_day)),
+ ('crew_size', models.IntegerField(default=1)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Result',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('order', models.PositiveIntegerField()),
+ ('crew', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='boatmovers.crew')),
+ ('race', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='boatmovers.race')),
+ ],
+ ),
+ migrations.AddField(
+ model_name='race',
+ name='resultlist',
+ field=models.ManyToManyField(through='boatmovers.Result', to='boatmovers.Crew'),
+ ),
+ ]
diff --git a/boatmovers/migrations/0002_alter_athlete_unique_together.py b/boatmovers/migrations/0002_alter_athlete_unique_together.py
new file mode 100644
index 00000000..7572d257
--- /dev/null
+++ b/boatmovers/migrations/0002_alter_athlete_unique_together.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.2.12 on 2022-06-22 17:49
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('boatmovers', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AlterUniqueTogether(
+ name='athlete',
+ unique_together={('first_name', 'last_name', 'birth_year')},
+ ),
+ ]
diff --git a/boatmovers/migrations/0003_auto_20220622_1753.py b/boatmovers/migrations/0003_auto_20220622_1753.py
new file mode 100644
index 00000000..bc367b79
--- /dev/null
+++ b/boatmovers/migrations/0003_auto_20220622_1753.py
@@ -0,0 +1,28 @@
+# Generated by Django 3.2.12 on 2022-06-22 17:53
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('boatmovers', '0002_alter_athlete_unique_together'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='race',
+ name='name',
+ field=models.CharField(default='Race1', max_length=200),
+ preserve_default=False,
+ ),
+ migrations.AddField(
+ model_name='race',
+ name='resulturl',
+ field=models.URLField(null=True),
+ ),
+ migrations.AlterUniqueTogether(
+ name='race',
+ unique_together={('date', 'name')},
+ ),
+ ]
diff --git a/boatmovers/migrations/__init__.py b/boatmovers/migrations/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/boatmovers/models.py b/boatmovers/models.py
new file mode 100644
index 00000000..07dae6cb
--- /dev/null
+++ b/boatmovers/models.py
@@ -0,0 +1,48 @@
+from django.db import models
+import datetime
+from django.utils import timezone
+
+def current_day(ttz=None):
+ if ttz is None:
+ return (datetime.datetime.now(tz=timezone.utc)).date()
+ return datetime.datetime.utcnow().astimezone(pytz.timezone(ttz)).date()
+
+# Create your models here.
+class Athlete(models.Model):
+ first_name = models.CharField(max_length=200)
+ last_name = models.CharField(max_length=200)
+ club = models.CharField(max_length=200)
+ trueskill_mu = models.FloatField(default=25.)
+ trueskill_sigma = models.FloatField(default=8.333)
+ birth_year = models.IntegerField(default=1972)
+
+ class Meta:
+ unique_together = ('first_name','last_name','birth_year')
+
+ def __str__(self):
+ return u'{f} {l}'.format(f = self.first_name, l=self.last_name)
+
+class Crew(models.Model):
+ athletes = models.ManyToManyField(Athlete)
+ name = models.CharField(max_length=200)
+
+ def __str__(self):
+ return u'{n}'.format(n=self.name)
+
+class Race(models.Model):
+ name = models.CharField(max_length=200)
+ resulturl = models.URLField(null=True)
+ date = models.DateField(default=current_day)
+ resultlist = models.ManyToManyField(Crew,through='Result')
+ crew_size = models.IntegerField(default=1)
+
+ class Meta:
+ unique_together = ('date','name')
+
+ def __str__(self):
+ return self.name
+
+class Result(models.Model):
+ crew = models.ForeignKey(Crew, on_delete=models.CASCADE)
+ race = models.ForeignKey(Race, on_delete=models.CASCADE)
+ order = models.PositiveIntegerField()
diff --git a/boatmovers/tests.py b/boatmovers/tests.py
new file mode 100644
index 00000000..7ce503c2
--- /dev/null
+++ b/boatmovers/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/boatmovers/views.py b/boatmovers/views.py
new file mode 100644
index 00000000..91ea44a2
--- /dev/null
+++ b/boatmovers/views.py
@@ -0,0 +1,3 @@
+from django.shortcuts import render
+
+# Create your views here.
diff --git a/rowsandall_app/settings.py b/rowsandall_app/settings.py
index 164c9153..f3c29dcd 100644
--- a/rowsandall_app/settings.py
+++ b/rowsandall_app/settings.py
@@ -49,6 +49,7 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
INSTALLED_APPS = [
'rowers',
'survey',
+ 'boatmovers',
# 'cvkbrno',
'django.contrib.admin',
'django.contrib.auth',
From 6ddef33385eca446fd6124f05c86ff2e760243a7 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Wed, 22 Jun 2022 21:34:29 +0200
Subject: [PATCH 02/19] create form
---
.../migrations/0004_auto_20220622_1835.py | 22 +
boatmovers/migrations/0005_athlete_gender.py | 19 +
boatmovers/models.py | 14 +
.../templates/boatmovers/athlete_form.html | 4 +
boatmovers/urls.py | 9 +
boatmovers/views.py | 12 +
cvkbrno/views.py | 2144 ++++++++---------
rowsandall_app/settings.py | 7 +-
rowsandall_app/urls.py | 3 +-
9 files changed, 1155 insertions(+), 1079 deletions(-)
create mode 100644 boatmovers/migrations/0004_auto_20220622_1835.py
create mode 100644 boatmovers/migrations/0005_athlete_gender.py
create mode 100644 boatmovers/templates/boatmovers/athlete_form.html
create mode 100644 boatmovers/urls.py
diff --git a/boatmovers/migrations/0004_auto_20220622_1835.py b/boatmovers/migrations/0004_auto_20220622_1835.py
new file mode 100644
index 00000000..94691a93
--- /dev/null
+++ b/boatmovers/migrations/0004_auto_20220622_1835.py
@@ -0,0 +1,22 @@
+# Generated by Django 3.2.12 on 2022-06-22 18:35
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('boatmovers', '0003_auto_20220622_1753'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='race',
+ name='verified',
+ field=models.BooleanField(default=False),
+ ),
+ migrations.AlterUniqueTogether(
+ name='result',
+ unique_together={('crew', 'race', 'order')},
+ ),
+ ]
diff --git a/boatmovers/migrations/0005_athlete_gender.py b/boatmovers/migrations/0005_athlete_gender.py
new file mode 100644
index 00000000..41de5e0a
--- /dev/null
+++ b/boatmovers/migrations/0005_athlete_gender.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.2.12 on 2022-06-22 18:48
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('boatmovers', '0004_auto_20220622_1835'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='athlete',
+ name='gender',
+ field=models.CharField(choices=[('m', 'M'), ('f', 'F')], default='m', max_length=200),
+ preserve_default=False,
+ ),
+ ]
diff --git a/boatmovers/models.py b/boatmovers/models.py
index 07dae6cb..10ffea51 100644
--- a/boatmovers/models.py
+++ b/boatmovers/models.py
@@ -1,4 +1,5 @@
from django.db import models
+from django import forms
import datetime
from django.utils import timezone
@@ -15,6 +16,7 @@ class Athlete(models.Model):
trueskill_mu = models.FloatField(default=25.)
trueskill_sigma = models.FloatField(default=8.333)
birth_year = models.IntegerField(default=1972)
+ gender = models.CharField(max_length=200, choices=(('m','M'),('f','F')))
class Meta:
unique_together = ('first_name','last_name','birth_year')
@@ -22,6 +24,14 @@ class Athlete(models.Model):
def __str__(self):
return u'{f} {l}'.format(f = self.first_name, l=self.last_name)
+ def get_absolute_url(self):
+ return "/athlete/%i/" % self.id
+
+class athleteForm(forms.ModelForm):
+ class Meta:
+ model = Athlete
+ fields = ['first_name','last_name','club','birth_year']
+
class Crew(models.Model):
athletes = models.ManyToManyField(Athlete)
name = models.CharField(max_length=200)
@@ -35,6 +45,7 @@ class Race(models.Model):
date = models.DateField(default=current_day)
resultlist = models.ManyToManyField(Crew,through='Result')
crew_size = models.IntegerField(default=1)
+ verified = models.BooleanField(default=False)
class Meta:
unique_together = ('date','name')
@@ -46,3 +57,6 @@ class Result(models.Model):
crew = models.ForeignKey(Crew, on_delete=models.CASCADE)
race = models.ForeignKey(Race, on_delete=models.CASCADE)
order = models.PositiveIntegerField()
+
+ class Meta:
+ unique_together = ('crew','race','order')
diff --git a/boatmovers/templates/boatmovers/athlete_form.html b/boatmovers/templates/boatmovers/athlete_form.html
new file mode 100644
index 00000000..a9b32c5f
--- /dev/null
+++ b/boatmovers/templates/boatmovers/athlete_form.html
@@ -0,0 +1,4 @@
+
diff --git a/boatmovers/urls.py b/boatmovers/urls.py
new file mode 100644
index 00000000..46028e74
--- /dev/null
+++ b/boatmovers/urls.py
@@ -0,0 +1,9 @@
+from django.conf import settings
+from django.conf.urls import url, include
+from django.urls import path, re_path
+
+import boatmovers.views as views
+
+urlpatterns = [
+ url(r'athlete/add/$',views.AthleteCreateView.as_view(),name='athlete_add'),
+]
diff --git a/boatmovers/views.py b/boatmovers/views.py
index 91ea44a2..3e98e380 100644
--- a/boatmovers/views.py
+++ b/boatmovers/views.py
@@ -1,3 +1,15 @@
from django.shortcuts import render
# Create your views here.
+from django.views.generic.edit import CreateView
+from boatmovers.models import Athlete
+
+class AthleteCreateView(CreateView):
+ model = Athlete
+ fields = [
+ 'first_name',
+ 'last_name',
+ 'birth_year',
+ 'gender',
+ 'club',
+ ]
diff --git a/cvkbrno/views.py b/cvkbrno/views.py
index 8caeeca8..4075a23a 100644
--- a/cvkbrno/views.py
+++ b/cvkbrno/views.py
@@ -64,29 +64,29 @@ def distancecount(u):
# sum km own rows
theoutings = Outing.objects.filter(rower=member).filter(status="completed")
for o in theoutings:
- cumdistance += o.distance
- oyear = o.starttime.year
- oweek = o.starttime.date().isocalendar()[1]
- omonth = o.starttime.month
- if thisyear == oyear:
- yeardistance += o.distance
- if thismonth == omonth:
- monthdistance += o.distance
- if weeknr == oweek:
- weekdistance += o.distance
+ cumdistance += o.distance
+ oyear = o.starttime.year
+ oweek = o.starttime.date().isocalendar()[1]
+ omonth = o.starttime.month
+ if thisyear == oyear:
+ yeardistance += o.distance
+ if thismonth == omonth:
+ monthdistance += o.distance
+ if weeknr == oweek:
+ weekdistance += o.distance
theoutings = Outing.objects.filter(otherrowers=member).filter(status="completed")
for o in theoutings:
- cumdistance += o.distance
- oyear = o.starttime.year
- oweek = o.starttime.date().isocalendar()[1]
- omonth = o.starttime.month
- if thisyear == oyear:
- yeardistance += o.distance
- if thismonth == omonth:
- monthdistance += o.distance
- if weeknr == oweek:
- weekdistance += o.distance
+ cumdistance += o.distance
+ oyear = o.starttime.year
+ oweek = o.starttime.date().isocalendar()[1]
+ omonth = o.starttime.month
+ if thisyear == oyear:
+ yeardistance += o.distance
+ if thismonth == omonth:
+ monthdistance += o.distance
+ if weeknr == oweek:
+ weekdistance += o.distance
return [cumdistance,yeardistance,monthdistance,weekdistance]
@@ -102,16 +102,16 @@ def distancecountb(boat):
# sum km own rows
theoutings = Outing.objects.filter(boat=boat).filter(status="completed")
for o in theoutings:
- cumdistance += o.distance
- oyear = o.starttime.year
- oweek = o.starttime.date().isocalendar()[1]
- omonth = o.starttime.month
- if thisyear == oyear:
- yeardistance += o.distance
- if thismonth == omonth:
- monthdistance += o.distance
- if weeknr == oweek:
- weekdistance += o.distance
+ cumdistance += o.distance
+ oyear = o.starttime.year
+ oweek = o.starttime.date().isocalendar()[1]
+ omonth = o.starttime.month
+ if thisyear == oyear:
+ yeardistance += o.distance
+ if thismonth == omonth:
+ monthdistance += o.distance
+ if weeknr == oweek:
+ weekdistance += o.distance
return [cumdistance,yeardistance,monthdistance,weekdistance]
@@ -123,7 +123,7 @@ def getmembers_json(u):
members = Member.objects.all().filter(contributions=True).filter(club=THISCLUB).exclude(user=u).order_by('user__last_name')
dd = {}
for m in members:
- dd[m.user.id] = m.user.first_name+' '+m.user.last_name
+ dd[m.user.id] = m.user.first_name+' '+m.user.last_name
return json.dumps(dd)
@@ -134,63 +134,63 @@ def thisclub_member(user):
def thisclub_admin(user):
if user.is_authenticated():
- member = Member.objects.get(user=user)
- result = user.is_authenticated() and member.club==THISCLUB and \
- (member.status in ["administrator","coach"])
+ member = Member.objects.get(user=user)
+ result = user.is_authenticated() and member.club==THISCLUB and \
+ (member.status in ["administrator","coach"])
else:
- result = False
+ result = False
return result
def conflicting_reservations(boat,starttime,endtime):
thisboatoutings = Outing.objects.filter(boat=boat).exclude(status="completed")
-
+
check = False
message = ""
# starttime = LOCALTIMEZONE.localize(starttime)
-
+
for outing in thisboatoutings:
- if (outing.status == "active"):
- if outing.starttime+datetime.timedelta(hours=OUTINGDURATIONHOURS)>starttime:
- check = True
- message = _("Boat is on the water at that time")
- if (outing.status == "race"):
- # if boat goes on transport in two hours from reservation time
- if (outing.starttime < starttime+datetime.timedelta(hours=RACEBLOCKHOURS)):
- check = True
- message = _("Boat is planned to go on transport at that time")
- # if boat is out racing during reservation time
- if (outing.endtime > starttime):
- check = True
- message = _("Boat is at races at that time")
- # if boat is already back frmo racing during reservation time
- if (outing.endtime <= starttime):
- check = False
- message = ""
- if (outing.status == "reservation"):
- # check if our reservation end time is before
- # or our reservation start time is
- # after this reservation
-
- if (outing.starttime < endtime and outing.endtime > starttime):
- check = True
- message = _("Conflicting reservations")
+ if (outing.status == "active"):
+ if outing.starttime+datetime.timedelta(hours=OUTINGDURATIONHOURS)>starttime:
+ check = True
+ message = _("Boat is on the water at that time")
+ if (outing.status == "race"):
+ # if boat goes on transport in two hours from reservation time
+ if (outing.starttime < starttime+datetime.timedelta(hours=RACEBLOCKHOURS)):
+ check = True
+ message = _("Boat is planned to go on transport at that time")
+ # if boat is out racing during reservation time
+ if (outing.endtime > starttime):
+ check = True
+ message = _("Boat is at races at that time")
+ # if boat is already back frmo racing during reservation time
+ if (outing.endtime <= starttime):
+ check = False
+ message = ""
+ if (outing.status == "reservation"):
+ # check if our reservation end time is before
+ # or our reservation start time is
+ # after this reservation
- if (outing.endtime > starttime) and (outing.starttime < starttime):
- check = True
- message = _("Conflicting reservations")
- if (outing.status == "race"):
- # check if our reservation end time is before
- # or our reservation start time is
- # after this reservation
-
- if (outing.starttime-datetime.timedelta(RACEBLOCKHOURS) < endtime and outing.endtime > starttime):
- check = True
- message = _("Boat will go to races at that time")
+ if (outing.starttime < endtime and outing.endtime > starttime):
+ check = True
+ message = _("Conflicting reservations")
- if (outing.endtime > starttime) and (outing.starttime-datetime.timedelta(RACEBLOCKHOURS) < starttime):
- check = True
- message = _("Boat is at races at that time")
+ if (outing.endtime > starttime) and (outing.starttime < starttime):
+ check = True
+ message = _("Conflicting reservations")
+ if (outing.status == "race"):
+ # check if our reservation end time is before
+ # or our reservation start time is
+ # after this reservation
+
+ if (outing.starttime-datetime.timedelta(RACEBLOCKHOURS) < endtime and outing.endtime > starttime):
+ check = True
+ message = _("Boat will go to races at that time")
+
+ if (outing.endtime > starttime) and (outing.starttime-datetime.timedelta(RACEBLOCKHOURS) < starttime):
+ check = True
+ message = _("Boat is at races at that time")
return check,message
@@ -198,18 +198,18 @@ def cleanoldreservations():
reservations = Outing.objects.filter(status="reservation")
now = timezone.now()
for reservation in reservations:
- dt = reservation.starttime
- if dt < now-datetime.timedelta(minutes=RESERVATIONEXPIRYMINUTES):
- reservation.delete()
+ dt = reservation.starttime
+ if dt < now-datetime.timedelta(minutes=RESERVATIONEXPIRYMINUTES):
+ reservation.delete()
# code to change boats that go on transport and remove boats that have returned from transport
races = Outing.objects.filter(status="race")
for race in races:
- if now > race.starttime-datetime.timedelta(hours=RACEBLOCKHOURS):
- race.boat.status="races"
- race.boat.save()
- if now > race.endtime:
- race.boat.status="hangar"
- race.boat.save()
+ if now > race.starttime-datetime.timedelta(hours=RACEBLOCKHOURS):
+ race.boat.status="races"
+ race.boat.save()
+ if now > race.endtime:
+ race.boat.status="hangar"
+ race.boat.save()
def get_damagedboats():
damagedboats = Boat.objects.filter(status="damaged")
@@ -224,38 +224,38 @@ def get_availableboats(m,t):
# add boats from allowed categories
for category in m.categories.all():
- thiscategoryboats = hangarboats.filter(categories=category)
- for theboat in thiscategoryboats:
- thisboatreservations = Outing.objects.filter(status="reservation",boat=theboat)
- addboat = True
- # the below should go to a subroutine
- # do not allow to add boats that go on transport or are reserved
- # in the near future
- for res in thisboatreservations:
- if (res.starttime < starttime+datetime.timedelta(hours=OUTINGDURATIONHOURS)):
- addboat = False
- if res.rower == m:
- addboat = True
- if (res.endtime):
- if (res.endtime > starttime):
- addboat = False
- if res.rower == m:
- addboat=True
- thisboatrace = Outing.objects.filter(status="race",boat=theboat)
- for race in thisboatrace:
- if (race.starttime < starttime+datetime.timedelta(hours=RACEBLOCKHOURS)) and (race.endtime > starttime):
- addboat = False
- race.boat.status="races"
- race.boat.save()
- if (race.endtime < starttime):
- addboat = True
- race.boat.status="hangar"
- race.boat.save()
+ thiscategoryboats = hangarboats.filter(categories=category)
+ for theboat in thiscategoryboats:
+ thisboatreservations = Outing.objects.filter(status="reservation",boat=theboat)
+ addboat = True
+ # the below should go to a subroutine
+ # do not allow to add boats that go on transport or are reserved
+ # in the near future
+ for res in thisboatreservations:
+ if (res.starttime < starttime+datetime.timedelta(hours=OUTINGDURATIONHOURS)):
+ addboat = False
+ if res.rower == m:
+ addboat = True
+ if (res.endtime):
+ if (res.endtime > starttime):
+ addboat = False
+ if res.rower == m:
+ addboat=True
+ thisboatrace = Outing.objects.filter(status="race",boat=theboat)
+ for race in thisboatrace:
+ if (race.starttime < starttime+datetime.timedelta(hours=RACEBLOCKHOURS)) and (race.endtime > starttime):
+ addboat = False
+ race.boat.status="races"
+ race.boat.save()
+ if (race.endtime < starttime):
+ addboat = True
+ race.boat.status="hangar"
+ race.boat.save()
+
+ if addboat:
+ allowedboats += [theboat]
- if addboat:
- allowedboats += [theboat]
-
return list(set(allowedboats))
@@ -272,7 +272,7 @@ def get_availableboats_reservation(m,t):
# add boats from available categories
for category in m.categories.all():
- allowedboats += hangarboats.filter(categories=category)
+ allowedboats += hangarboats.filter(categories=category)
return list(set(allowedboats))
@@ -297,18 +297,18 @@ def login_user_view(request,activeoutings=get_active_outings(),reservations=get_
request.session[translation.LANGUAGE_SESSION_KEY] = USER_LANGUAGE
username = password = ''
if request.POST:
- username = request.POST['username']
- password = request.POST['password']
+ username = request.POST['username']
+ password = request.POST['password']
- user = authenticate(username=username, password=password)
- if user is not None:
+ user = authenticate(username=username, password=password)
+ if user is not None:
if user.is_active:
login(request, user)
- url = reverse(base_view)
+ url = reverse(base_view)
return HttpResponseRedirect(url)
return render(request,'cvkbrno_login.html',
- {'activeoutings':get_active_outings(),
- 'reservations':get_future_reservations()})
+ {'activeoutings':get_active_outings(),
+ 'reservations':get_future_reservations()})
def change_language_view(request,languagecode):
USER_LANGUAGE = languagecode
@@ -325,12 +325,12 @@ def base_view(request):
member = Member.objects.get(user=request.user)
activeoutings = Outing.objects.filter(status="active",rower=member)
if (len(activeoutings)!=0):
- # we are still out
- url = reverse(closeouting_view)
- return HttpResponseRedirect(url)
+ # we are still out
+ url = reverse(closeouting_view)
+ return HttpResponseRedirect(url)
else:
- url = reverse(createouting_view)
- return HttpResponseRedirect(url)
+ url = reverse(createouting_view)
+ return HttpResponseRedirect(url)
@@ -343,7 +343,7 @@ def logout_then_login(request):
url = reverse(base_view)
return HttpResponseRedirect(url)
-
+
@user_passes_test(thisclub_admin,login_url="/cvkbrno/login")
def boats_admin_view(request,message="",successmessage=""):
@@ -351,13 +351,13 @@ def boats_admin_view(request,message="",successmessage=""):
theboats = Boat.objects.all().order_by("boatcode")
theoutings = Outing.objects.exclude(status="reservation").exclude(status="race").order_by("-starttime")[0:20]
return render(request,
- TEMPLATEPREFIX+'boats_admin.html',
- {'theboats':theboats,
- 'theoutings':theoutings,
- 'message':message,
- 'successmessage':successmessage,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
+ TEMPLATEPREFIX+'boats_admin.html',
+ {'theboats':theboats,
+ 'theoutings':theoutings,
+ 'message':message,
+ 'successmessage':successmessage,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
@user_passes_test(thisclub_admin,login_url="/cvkbrno/login")
@@ -365,12 +365,12 @@ def categories_admin_view(request,message="",successmessage=""):
cleanoldreservations()
thecats = BoatCategory.objects.all().order_by("name")
return render(request,
- TEMPLATEPREFIX+'categories_admin.html',
- {'thecats':thecats,
- 'message':message,
- 'successmessage':successmessage,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
+ TEMPLATEPREFIX+'categories_admin.html',
+ {'thecats':thecats,
+ 'message':message,
+ 'successmessage':successmessage,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
@user_passes_test(thisclub_admin,login_url="/cvkbrno/login")
def members_admin_view(request,message="",successmessage=""):
@@ -379,126 +379,126 @@ def members_admin_view(request,message="",successmessage=""):
return render(request,
- TEMPLATEPREFIX+'members_admin.html',
- {'themembers':themembers,
- 'message':message,
- 'successmessage':successmessage,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
-
+ TEMPLATEPREFIX+'members_admin.html',
+ {'themembers':themembers,
+ 'message':message,
+ 'successmessage':successmessage,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
+
@user_passes_test(thisclub_admin,login_url="/cvkbrno/login")
def members_work_admin_view(request,message="",successmessage=""):
cleanoldreservations()
theworks = MemberWork.objects.filter(status='planned')
return render(request,
- TEMPLATEPREFIX+'memberswork_admin.html',
- {'theworks':theworks,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
+ TEMPLATEPREFIX+'memberswork_admin.html',
+ {'theworks':theworks,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
@user_passes_test(thisclub_admin,login_url="/cvkbrno/login")
def members_work_add_view(request,message="",successmessage=""):
cleanoldreservations()
if request.method == 'POST':
- # Form was submitted
- form = MemberWorkCreateForm(request.POST)
+ # Form was submitted
+ form = MemberWorkCreateForm(request.POST)
- if form.is_valid():
- # do something
- res = addmemberwork(request.POST)
- func = res[0]
- message = res[1]
- successmessage = res[2]
- theid = res[3]
- kwargs = {}
- if successmessage != "":
- kwargs['successmessage'] = successmessage.encode('utf8')
- if message != "":
- kwargs['message'] = message.encode('utf8')
+ if form.is_valid():
+ # do something
+ res = addmemberwork(request.POST)
+ func = res[0]
+ message = res[1]
+ successmessage = res[2]
+ theid = res[3]
+ kwargs = {}
+ if successmessage != "":
+ kwargs['successmessage'] = successmessage.encode('utf8')
+ if message != "":
+ kwargs['message'] = message.encode('utf8')
- theworks = MemberWork.objects.filter(status='planned')
+ theworks = MemberWork.objects.filter(status='planned')
# args['theworks'] = theworks
- url = reverse(func,kwargs = kwargs)
-
- return HttpResponseRedirect(url)
- else:
- return render(request,
- TEMPLATEPREFIX+'memberswork_add_form.html',
- {'form':form,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user),
- }
- )
-
+ url = reverse(func,kwargs = kwargs)
+
+ return HttpResponseRedirect(url)
else:
- form = MemberWorkCreateForm()
- if (message != ""):
- return render(request,
- TEMPLATEPREFIX+'memberswork_add_form.html',
- {'form':form,
- 'message':message,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
- )
- else:
-
- return render(request,
- TEMPLATEPREFIX+'memberswork_add_form.html',
- {'form':form,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
- )
+ return render(request,
+ TEMPLATEPREFIX+'memberswork_add_form.html',
+ {'form':form,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user),
+ }
+ )
+
+ else:
+ form = MemberWorkCreateForm()
+ if (message != ""):
+ return render(request,
+ TEMPLATEPREFIX+'memberswork_add_form.html',
+ {'form':form,
+ 'message':message,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
+ )
+ else:
+
+ return render(request,
+ TEMPLATEPREFIX+'memberswork_add_form.html',
+ {'form':form,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
+ )
@user_passes_test(thisclub_admin,login_url="/cvkbrno/login")
def boats_admin_delete_confirm_view(request,id):
theboat = Boat.objects.get(id=id)
return render(request,
- TEMPLATEPREFIX+'boat_delete_confirm.html',
- {'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
+ TEMPLATEPREFIX+'boat_delete_confirm.html',
+ {'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
@user_passes_test(thisclub_admin,login_url="/cvkbrno/login")
def outing_admin_view(request,id):
theouting = Outing.objects.get(id=id)
return render(request,
- TEMPLATEPREFIX+'outing_admin.html',
- {'outing':theouting,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
+ TEMPLATEPREFIX+'outing_admin.html',
+ {'outing':theouting,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
@user_passes_test(thisclub_admin,login_url="/cvkbrno/login")
def categories_admin_delete_confirm_view(request,id):
thecategory = BoatCategory.objects.get(id=id)
return render(request,
- TEMPLATEPREFIX+'categories_delete_confirm.html',
- {'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
+ TEMPLATEPREFIX+'categories_delete_confirm.html',
+ {'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
@user_passes_test(thisclub_admin,login_url="/cvkbrno/login")
def members_admin_delete_confirm_view(request,id):
themember = Member.objects.get(id=id)
return render(request,
- TEMPLATEPREFIX+'members_delete_confirm.html',
- {'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
+ TEMPLATEPREFIX+'members_delete_confirm.html',
+ {'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
@user_passes_test(thisclub_admin,login_url="/cvkbrno/login")
def boats_admin_delete_view(request,id):
try:
- theboat = Boat.objects.get(id=id)
- theboat.delete()
+ theboat = Boat.objects.get(id=id)
+ theboat.delete()
except:
- pass
+ pass
url = reverse(boats_admin_view,kwargs={
- 'successmessage': _("boat deleted").encode('utf8'),
- })
+ 'successmessage': _("boat deleted").encode('utf8'),
+ })
return HttpResponseRedirect(url)
@@ -506,29 +506,29 @@ def boats_admin_delete_view(request,id):
@user_passes_test(thisclub_admin,login_url="/cvkbrno/login")
def members_admin_delete_view(request,id):
try:
- themember = Member.objects.get(id=id)
- themember.user.delete()
- themember.delete()
+ themember = Member.objects.get(id=id)
+ themember.user.delete()
+ themember.delete()
except:
- pass
+ pass
url = reverse(members_admin_view,kwargs={
- 'successmessage': _("member deleted").encode('utf8'),
- })
+ 'successmessage': _("member deleted").encode('utf8'),
+ })
return HttpResponseRedirect(url)
@user_passes_test(thisclub_admin,login_url="/cvkbrno/login")
def categories_admin_delete_view(request,id):
try:
- thecategory = BoatCategory.objects.get(id=id)
- thecategory.delete()
+ thecategory = BoatCategory.objects.get(id=id)
+ thecategory.delete()
except:
- pass
+ pass
url = reverse(categories_admin_view,kwargs={
- 'successmessage': _("category deleted").encode('utf8'),
- })
+ 'successmessage': _("category deleted").encode('utf8'),
+ })
return HttpResponseRedirect(url)
@@ -537,417 +537,417 @@ def categories_admin_delete_view(request,id):
@user_passes_test(thisclub_admin,login_url="/cvkbrno/login")
def boats_admin_add_view(request,message="",successmessage=""):
if request.method == 'POST':
- # Form was submitted
- form = BoatEditForm(request.POST)
+ # Form was submitted
+ form = BoatEditForm(request.POST)
- if form.is_valid():
- # do something
- res = addboat(request.POST)
- func = res[0]
- message = res[1]
- successmessage = res[2]
- theid = res[3]
- kwargs = {}
- if successmessage != "":
- kwargs['successmessage'] = successmessage.encode('utf8')
- if message != "":
- kwargs['message'] = message.encode('utf8')
- if theid != 0:
- kwargs['id'] = int(theid)
- url = reverse(func,kwargs = kwargs)
-
- return HttpResponseRedirect(url)
- else:
- return render(request,
- TEMPLATEPREFIX+'boat_add_form.html',
- {'form':form,
- 'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user),
- }
- )
-
+ if form.is_valid():
+ # do something
+ res = addboat(request.POST)
+ func = res[0]
+ message = res[1]
+ successmessage = res[2]
+ theid = res[3]
+ kwargs = {}
+ if successmessage != "":
+ kwargs['successmessage'] = successmessage.encode('utf8')
+ if message != "":
+ kwargs['message'] = message.encode('utf8')
+ if theid != 0:
+ kwargs['id'] = int(theid)
+ url = reverse(func,kwargs = kwargs)
+
+ return HttpResponseRedirect(url)
else:
- form = BoatEditForm()
- if (message != ""):
- return render(request,
- TEMPLATEPREFIX+'boat_add_form.html',
- {'form':form,
- 'message':message,
- 'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
- )
- else:
-
- return render(request,
- TEMPLATEPREFIX+'boat_add_form.html',
- {'form':form,
- 'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
- )
+ return render(request,
+ TEMPLATEPREFIX+'boat_add_form.html',
+ {'form':form,
+ 'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user),
+ }
+ )
+
+ else:
+ form = BoatEditForm()
+ if (message != ""):
+ return render(request,
+ TEMPLATEPREFIX+'boat_add_form.html',
+ {'form':form,
+ 'message':message,
+ 'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
+ )
+ else:
+
+ return render(request,
+ TEMPLATEPREFIX+'boat_add_form.html',
+ {'form':form,
+ 'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
+ )
@user_passes_test(thisclub_admin,login_url="/cvkbrno/login")
def members_admin_add_view(request,message="",successmessage=""):
if request.method == 'POST':
- # Form was submitted
- form = MemberEditForm(request.POST)
+ # Form was submitted
+ form = MemberEditForm(request.POST)
- if form.is_valid():
- # do something
- res = addmember(request.POST)
- func = res[0]
- message = res[1]
- successmessage = res[2]
- theid = res[3]
- kwargs = {}
- if successmessage != "":
- kwargs['successmessage'] = successmessage
- if message != "":
- kwargs['message'] = message
- if theid != 0:
- kwargs['id'] = int(theid)
- url = reverse(func,kwargs = kwargs)
-
- return HttpResponseRedirect(url)
- else:
- memberform = form
- userform = UserCreateForm()
- passwordconfirmform = PassWordConfirmForm()
- return render(request,
- TEMPLATEPREFIX+'member_add_form.html',
- {'form1':memberform,
- 'form2':userform,
- 'form3':passwordconfirmform,
- 'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
- )
-
+ if form.is_valid():
+ # do something
+ res = addmember(request.POST)
+ func = res[0]
+ message = res[1]
+ successmessage = res[2]
+ theid = res[3]
+ kwargs = {}
+ if successmessage != "":
+ kwargs['successmessage'] = successmessage
+ if message != "":
+ kwargs['message'] = message
+ if theid != 0:
+ kwargs['id'] = int(theid)
+ url = reverse(func,kwargs = kwargs)
+
+ return HttpResponseRedirect(url)
else:
- memberform = MemberEditForm()
- userform = UserCreateForm()
- passwordconfirmform = PassWordConfirmForm()
- if (message != ""):
- return render(request,
- TEMPLATEPREFIX+'member_add_form.html',
- {'form1':memberform,
- 'form2':userform,
- 'form3':passwordconfirmform,
- 'message':message,
- 'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
- )
- else:
-
- return render(request,
- TEMPLATEPREFIX+'member_add_form.html',
- {'form1':memberform,
- 'form2':userform,
- 'form3':passwordconfirmform,
- 'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
- )
+ memberform = form
+ userform = UserCreateForm()
+ passwordconfirmform = PassWordConfirmForm()
+ return render(request,
+ TEMPLATEPREFIX+'member_add_form.html',
+ {'form1':memberform,
+ 'form2':userform,
+ 'form3':passwordconfirmform,
+ 'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
+ )
+
+ else:
+ memberform = MemberEditForm()
+ userform = UserCreateForm()
+ passwordconfirmform = PassWordConfirmForm()
+ if (message != ""):
+ return render(request,
+ TEMPLATEPREFIX+'member_add_form.html',
+ {'form1':memberform,
+ 'form2':userform,
+ 'form3':passwordconfirmform,
+ 'message':message,
+ 'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
+ )
+ else:
+
+ return render(request,
+ TEMPLATEPREFIX+'member_add_form.html',
+ {'form1':memberform,
+ 'form2':userform,
+ 'form3':passwordconfirmform,
+ 'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
+ )
@user_passes_test(thisclub_admin,login_url="/cvkbrno/login")
def categories_admin_add_view(request,message="",successmessage=""):
if request.method == 'POST':
- # Form was submitted
- form = BoatCategoryEditForm(request.POST)
+ # Form was submitted
+ form = BoatCategoryEditForm(request.POST)
- if form.is_valid():
- # do something
- message = ""
- successmessage = ""
- name = request.POST['name']
- thecategory = BoatCategory(name=name)
- thecategory.save()
- kwargs = {}
- if message != "":
- kwargs['message'] = message
- if successmessage != '':
- kwargs['successmessage'] = successmessage
+ if form.is_valid():
+ # do something
+ message = ""
+ successmessage = ""
+ name = request.POST['name']
+ thecategory = BoatCategory(name=name)
+ thecategory.save()
+ kwargs = {}
+ if message != "":
+ kwargs['message'] = message
+ if successmessage != '':
+ kwargs['successmessage'] = successmessage
- url = reverse(categories_admin_view,kwargs=kwargs)
-
- return HttpResponseRedirect(url)
- else:
- return render(request,
- TEMPLATEPREFIX+'category_add_form.html',
- {'form':form,
- 'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
- )
+ url = reverse(categories_admin_view,kwargs=kwargs)
+
+ return HttpResponseRedirect(url)
+ else:
+ return render(request,
+ TEMPLATEPREFIX+'category_add_form.html',
+ {'form':form,
+ 'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
+ )
else:
- form = BoatCategoryEditForm()
- if (message != ""):
- return render(request,
- TEMPLATEPREFIX+'category_add_form.html',
- {'form':form,
- 'message':message,
- 'successmessage':successmessage,
- 'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
- )
- else:
-
- return render(request,
- TEMPLATEPREFIX+'category_add_form.html',
- {'form':form,
- 'successmessage':successmessage,
- 'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
- )
-
+ form = BoatCategoryEditForm()
+ if (message != ""):
+ return render(request,
+ TEMPLATEPREFIX+'category_add_form.html',
+ {'form':form,
+ 'message':message,
+ 'successmessage':successmessage,
+ 'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
+ )
+ else:
+
+ return render(request,
+ TEMPLATEPREFIX+'category_add_form.html',
+ {'form':form,
+ 'successmessage':successmessage,
+ 'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
+ )
+
@user_passes_test(thisclub_admin,login_url="/cvkbrno/login")
def boats_admin_edit_view(request,id,message="",successmessage=""):
theboat = Boat.objects.get(id=id)
if request.method == 'POST':
- # Form was submitted
- form = BoatEditForm(request.POST)
+ # Form was submitted
+ form = BoatEditForm(request.POST)
- if form.is_valid():
- res = editboat(request.POST,theboat)
- func = res[0]
- message = res[1]
- successmessage = res[2]
- theid = res[3]
- kwargs = {}
- if successmessage != "":
- kwargs['successmessage'] = successmessage
- if message != "":
- kwargs['message'] = message
- if theid != 0:
- kwargs['id'] = int(theid)
- url = reverse(func,kwargs = kwargs)
-
- return HttpResponseRedirect(url)
- else:
- theoutings = Outing.objects.exclude(status="reservation").filter(boat=theboat).order_by("-starttime")[0:20]
- return render(request,
- TEMPLATEPREFIX+'boat_edit_form.html',
- {'form':form,
- 'theoutings':theoutings,
- 'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
- )
-
+ if form.is_valid():
+ res = editboat(request.POST,theboat)
+ func = res[0]
+ message = res[1]
+ successmessage = res[2]
+ theid = res[3]
+ kwargs = {}
+ if successmessage != "":
+ kwargs['successmessage'] = successmessage
+ if message != "":
+ kwargs['message'] = message
+ if theid != 0:
+ kwargs['id'] = int(theid)
+ url = reverse(func,kwargs = kwargs)
+
+ return HttpResponseRedirect(url)
else:
- form = BoatEditForm(instance=theboat)
- theoutings = Outing.objects.exclude(status="reservation").filter(boat=theboat).order_by("-starttime")[0:20]
- if (message != ""):
- return render(request,
- TEMPLATEPREFIX+'boat_edit_form.html',
- {'form':form,
- 'message':message,
- 'theoutings':theoutings,
- 'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
- )
- else:
-
- return render(request,
- TEMPLATEPREFIX+'boat_edit_form.html',
- {'form':form,
- 'theoutings':theoutings,
- 'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
- )
+ theoutings = Outing.objects.exclude(status="reservation").filter(boat=theboat).order_by("-starttime")[0:20]
+ return render(request,
+ TEMPLATEPREFIX+'boat_edit_form.html',
+ {'form':form,
+ 'theoutings':theoutings,
+ 'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
+ )
+
+ else:
+ form = BoatEditForm(instance=theboat)
+ theoutings = Outing.objects.exclude(status="reservation").filter(boat=theboat).order_by("-starttime")[0:20]
+ if (message != ""):
+ return render(request,
+ TEMPLATEPREFIX+'boat_edit_form.html',
+ {'form':form,
+ 'message':message,
+ 'theoutings':theoutings,
+ 'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
+ )
+ else:
+
+ return render(request,
+ TEMPLATEPREFIX+'boat_edit_form.html',
+ {'form':form,
+ 'theoutings':theoutings,
+ 'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
+ )
@user_passes_test(thisclub_admin,login_url="/cvkbrno/login")
def members_work_edit_view(request,id,message="",successmessage=""):
thework = MemberWork.objects.get(id=id)
if request.method == 'POST':
- # Form was submitted
- form = MemberWorkCreateForm(request.POST)
+ # Form was submitted
+ form = MemberWorkCreateForm(request.POST)
- if form.is_valid():
- res = editmemberwork(request.POST,thework)
- func = res[0]
- message = res[1]
- successmessage = res[2]
- theid = res[3]
- kwargs = {}
- if successmessage != "":
- kwargs['successmessage'] = successmessage
- if message != "":
- kwargs['message'] = message
- if theid != 0:
- kwargs['id'] = int(theid)
- url = reverse(func,kwargs = kwargs)
-
- return HttpResponseRedirect(url)
- else:
- return render(request,
- TEMPLATEPREFIX+'memberwork_edit_form.html',
- {'form':form,
- 'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
- )
-
+ if form.is_valid():
+ res = editmemberwork(request.POST,thework)
+ func = res[0]
+ message = res[1]
+ successmessage = res[2]
+ theid = res[3]
+ kwargs = {}
+ if successmessage != "":
+ kwargs['successmessage'] = successmessage
+ if message != "":
+ kwargs['message'] = message
+ if theid != 0:
+ kwargs['id'] = int(theid)
+ url = reverse(func,kwargs = kwargs)
+
+ return HttpResponseRedirect(url)
else:
- form = MemberWorkCreateForm(instance=thework)
- if (message != ""):
- return render(request,
- TEMPLATEPREFIX+'memberwork_edit_form.html',
- {'form':form,
- 'message':message,
- 'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
- )
- else:
-
- return render(request,
- TEMPLATEPREFIX+'memberwork_edit_form.html',
- {'form':form,
- 'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
- )
+ return render(request,
+ TEMPLATEPREFIX+'memberwork_edit_form.html',
+ {'form':form,
+ 'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
+ )
+
+ else:
+ form = MemberWorkCreateForm(instance=thework)
+ if (message != ""):
+ return render(request,
+ TEMPLATEPREFIX+'memberwork_edit_form.html',
+ {'form':form,
+ 'message':message,
+ 'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
+ )
+ else:
+
+ return render(request,
+ TEMPLATEPREFIX+'memberwork_edit_form.html',
+ {'form':form,
+ 'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
+ )
@user_passes_test(thisclub_admin,login_url="/cvkbrno/login")
def members_admin_edit_view(request,id,message="",successmessage=""):
themember = Member.objects.get(id=id)
if request.method == 'POST':
- # Form was submitted
- form = MemberEditForm(request.POST)
+ # Form was submitted
+ form = MemberEditForm(request.POST)
- if form.is_valid():
- res = editmember(request.POST,themember)
- func = res[0]
- message = res[1]
- successmessage = res[2]
- theid = res[3]
- kwargs = {}
- if successmessage != "":
- kwargs['successmessage'] = successmessage
- if message != "":
- kwargs['message'] = message
- if theid != 0:
- kwargs['id'] = int(theid)
- url = reverse(func,kwargs = kwargs)
-
- return HttpResponseRedirect(url)
- else:
- return render(request,
- TEMPLATEPREFIX+'member_edit_form.html',
- {'form1':memberform,
- 'form2':userform,
- 'id':id,
- 'username': themember.user.username,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
- )
+ if form.is_valid():
+ res = editmember(request.POST,themember)
+ func = res[0]
+ message = res[1]
+ successmessage = res[2]
+ theid = res[3]
+ kwargs = {}
+ if successmessage != "":
+ kwargs['successmessage'] = successmessage
+ if message != "":
+ kwargs['message'] = message
+ if theid != 0:
+ kwargs['id'] = int(theid)
+ url = reverse(func,kwargs = kwargs)
-
+ return HttpResponseRedirect(url)
else:
- memberform = MemberEditForm(instance=themember)
- userform = UserEditForm(instance=themember.user)
- if (message != ""):
- return render(request,
- TEMPLATEPREFIX+'member_edit_form.html',
- {'form1':memberform,
- 'form2':userform,
- 'username': themember.user.username,
- 'message':message,
- 'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
- )
- else:
-
- return render(request,
- TEMPLATEPREFIX+'member_edit_form.html',
- {'form1':memberform,
- 'form2':userform,
- 'username': themember.user.username,
- 'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
- )
+ return render(request,
+ TEMPLATEPREFIX+'member_edit_form.html',
+ {'form1':memberform,
+ 'form2':userform,
+ 'id':id,
+ 'username': themember.user.username,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
+ )
+
+
+ else:
+ memberform = MemberEditForm(instance=themember)
+ userform = UserEditForm(instance=themember.user)
+ if (message != ""):
+ return render(request,
+ TEMPLATEPREFIX+'member_edit_form.html',
+ {'form1':memberform,
+ 'form2':userform,
+ 'username': themember.user.username,
+ 'message':message,
+ 'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
+ )
+ else:
+
+ return render(request,
+ TEMPLATEPREFIX+'member_edit_form.html',
+ {'form1':memberform,
+ 'form2':userform,
+ 'username': themember.user.username,
+ 'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
+ )
@user_passes_test(thisclub_admin,login_url="/cvkbrno/login")
def categories_admin_edit_view(request,id,message="",successmessage=""):
thecategory = BoatCategory.objects.get(id=id)
if request.method == 'POST':
- # Form was submitted
- form = BoatCategoryEditForm(request.POST)
+ # Form was submitted
+ form = BoatCategoryEditForm(request.POST)
- if form.is_valid():
- # do something
- message = ""
- successmessage = ""
- name = request.POST['name']
- thecategory.name = name
- thecategory.save()
+ if form.is_valid():
+ # do something
+ message = ""
+ successmessage = ""
+ name = request.POST['name']
+ thecategory.name = name
+ thecategory.save()
-
- if (message != ""):
- url = reverse(categories_admin_view,
- kwargs = {
- 'successmessage': _('Changes saved'),
- 'message': message
- })
- else:
- url = reverse(categories_admin_view,
- kwargs = {
- 'successmessage': _('Changes saved'),
- })
-
- return HttpResponseRedirect(url)
- else:
- return render(request,
- TEMPLATEPREFIX+'categories_edit_form.html',
- {'form':form,
- 'successmessage':successmessage,
- 'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
- )
+
+ if (message != ""):
+ url = reverse(categories_admin_view,
+ kwargs = {
+ 'successmessage': _('Changes saved'),
+ 'message': message
+ })
+ else:
+ url = reverse(categories_admin_view,
+ kwargs = {
+ 'successmessage': _('Changes saved'),
+ })
+
+ return HttpResponseRedirect(url)
else:
- form = BoatCategoryEditForm(instance=thecategory)
- if (message != ""):
- return render(request,
- TEMPLATEPREFIX+'categories_edit_form.html',
- {'form':form,
- 'message':message,
- 'successmessage':successmessage,
- 'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
- )
- else:
-
- return render(request,
- TEMPLATEPREFIX+'categories_edit_form.html',
- {'form':form,
- 'successmessage':successmessage,
- 'id':id,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
- )
+ return render(request,
+ TEMPLATEPREFIX+'categories_edit_form.html',
+ {'form':form,
+ 'successmessage':successmessage,
+ 'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
+ )
+ else:
+ form = BoatCategoryEditForm(instance=thecategory)
+ if (message != ""):
+ return render(request,
+ TEMPLATEPREFIX+'categories_edit_form.html',
+ {'form':form,
+ 'message':message,
+ 'successmessage':successmessage,
+ 'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
+ )
+ else:
+
+ return render(request,
+ TEMPLATEPREFIX+'categories_edit_form.html',
+ {'form':form,
+ 'successmessage':successmessage,
+ 'id':id,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,}
+ )
@user_passes_test(thisclub_member,login_url="/cvkbrno/login")
def meterboard_view(request,message="",successmessage="",sortby="year"):
try:
- sortby = request.GET['sortby']
+ sortby = request.GET['sortby']
except KeyError:
- pass
+ pass
now = timezone.now()
members = getclubmembers()
boats = Boat.objects.all()
@@ -956,47 +956,47 @@ def meterboard_view(request,message="",successmessage="",sortby="year"):
theoutings = Outing.objects.exclude(status="reservation").exclude(status="race").order_by("-starttime")[0:20]
for member in members:
- cumdist,yeardist,monthdist,weekdist = distancecount(member.user)
- df2 = pd.DataFrame(
- {
- 'Cumulative Distance':[cumdist],
- 'This Year':[yeardist],
- 'This Month':[monthdist],
- 'This Week':[weekdist],
- },
- index = [member]
- )
- df = df.append(df2)
+ cumdist,yeardist,monthdist,weekdist = distancecount(member.user)
+ df2 = pd.DataFrame(
+ {
+ 'Cumulative Distance':[cumdist],
+ 'This Year':[yeardist],
+ 'This Month':[monthdist],
+ 'This Week':[weekdist],
+ },
+ index = [member]
+ )
+ df = df.append(df2)
for boat in boats:
- cumdist,yeardist,monthdist,weekdist = distancecountb(boat)
- df3 = pd.DataFrame(
- {
- 'Cumulative':[cumdist],
- 'This Year':[yeardist],
- 'This Month':[monthdist],
- 'This Week':[weekdist],
- },
- index = [boat]
- )
- dfb = dfb.append(df3)
+ cumdist,yeardist,monthdist,weekdist = distancecountb(boat)
+ df3 = pd.DataFrame(
+ {
+ 'Cumulative':[cumdist],
+ 'This Year':[yeardist],
+ 'This Month':[monthdist],
+ 'This Week':[weekdist],
+ },
+ index = [boat]
+ )
+ dfb = dfb.append(df3)
sortorder = ['This Year', 'This Month', 'This Week']
if sortby == 'month':
- sortorder = ['This Month','This Year','This Week']
+ sortorder = ['This Month','This Year','This Week']
if sortby == 'week':
- sortorder = ['This Week','This Year','This Month']
-
+ sortorder = ['This Week','This Year','This Month']
+
data = df.sort_values(by=sortorder,ascending=False).to_html(classes='listtable paddedtable',columns=['This Year','This Month','This Week'])
datab = dfb.sort_values(by=sortorder,ascending=False).to_html(classes='listtable paddedtable',columns=['This Year','This Month','This Week'])
return render(request,
- TEMPLATEPREFIX+'meterboard.html',
- {'data':data,
- 'datab':datab,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
-
-
+ TEMPLATEPREFIX+'meterboard.html',
+ {'data':data,
+ 'datab':datab,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
+
+
@user_passes_test(thisclub_member,login_url="/cvkbrno/login")
def createouting_view(request,message="",successmessage=""):
@@ -1009,195 +1009,195 @@ def createouting_view(request,message="",successmessage=""):
# You are still out
if (len(activeoutings)!=0):
- # we are still out
- errormessg = _("You still have an active outing. Check in first.").encode('utf8')
- url = reverse(closeouting_view,
- kwargs = {
- 'message':str(errormessg),
- })
+ # we are still out
+ errormessg = _("You still have an active outing. Check in first.").encode('utf8')
+ url = reverse(closeouting_view,
+ kwargs = {
+ 'message':str(errormessg),
+ })
- return HttpResponseRedirect(url)
+ return HttpResponseRedirect(url)
# You have submitted the form
if request.method == 'POST':
- # Form was submitted
- form = OutingForm(request.POST)
- # form is valid
- if form.is_valid():
- # Get values from form
- dist = request.POST['distance']
- boat = Boat.objects.get(id=request.POST['boat'])
- boat.status = "water"
- boat.save()
- additionalcrew = []
- if boat.nrseats>1:
- for i in range(boat.nrseats-1):
- snr = i+2
- try:
- crewid = int(request.POST['crew'+str(snr)])
- except:
- message = _("You must select additional crew members for this boat")
- return render(request,
- TEMPLATEPREFIX+'outing_form.html',
- {'form':form,
- 'theboats':theboats,
- 'reservations':get_future_reservations(),
- 'races':get_future_races(),
- 'damagedboats':get_damagedboats(),
- 'plannedwork':plannedwork,
- 'member':member,
- 'message':message,
- 'jsonmembers':getmembers_json(request.user),
- 'successmessage':successmessage,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
- additionalcrew.append(Member.objects.get(user__id=crewid))
- # remove duplicates
- additionalcrew = list(set(additionalcrew))
+ # Form was submitted
+ form = OutingForm(request.POST)
+ # form is valid
+ if form.is_valid():
+ # Get values from form
+ dist = request.POST['distance']
+ boat = Boat.objects.get(id=request.POST['boat'])
+ boat.status = "water"
+ boat.save()
+ additionalcrew = []
+ if boat.nrseats>1:
+ for i in range(boat.nrseats-1):
+ snr = i+2
+ try:
+ crewid = int(request.POST['crew'+str(snr)])
+ except:
+ message = _("You must select additional crew members for this boat")
+ return render(request,
+ TEMPLATEPREFIX+'outing_form.html',
+ {'form':form,
+ 'theboats':theboats,
+ 'reservations':get_future_reservations(),
+ 'races':get_future_races(),
+ 'damagedboats':get_damagedboats(),
+ 'plannedwork':plannedwork,
+ 'member':member,
+ 'message':message,
+ 'jsonmembers':getmembers_json(request.user),
+ 'successmessage':successmessage,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
+ additionalcrew.append(Member.objects.get(user__id=crewid))
+ # remove duplicates
+ additionalcrew = list(set(additionalcrew))
-
- starttime = timezone.now()
- myreservations = Outing.objects.filter(status="reservation",
- rower=member,
- starttime__year=today.year,
- starttime__month=today.month,
- starttime__day=today.day).order_by("starttime")
- # form is valid and you have some reservation (for today)
- if len(myreservations) != 0:
- nextreservation=myreservations.first()
- # you are taking the boat that you reserved
+ starttime = timezone.now()
+ myreservations = Outing.objects.filter(status="reservation",
+ rower=member,
+ starttime__year=today.year,
+ starttime__month=today.month,
+ starttime__day=today.day).order_by("starttime")
- if (nextreservation.boat == boat):
- nextreservation.starttime = starttime
- nextreservation.status = "active"
- nextreservation.distance = dist
- nextreservation.save()
- for member in additionalcrew:
- nextreservation.otherrowers.add(member)
- nextreservation.save()
- # you are taking another boat
- else:
- o = Outing(starttime=starttime,rower=member,
- boat=boat,distance=dist,
- status="active")
- o.save()
- for member in additionalcrew:
- o.otherrowers.add(member)
- o.save()
- # form is valid and you have no reservations
- else:
- o = Outing(starttime=starttime,rower=member,boat=boat,
- distance=dist,
- status="active")
- o.save()
- for member in additionalcrew:
- o.otherrowers.add(member)
- o.save()
- if not settings.DEBUG:
- logout(request)
- url = reverse(base_view)
- return HttpResponseRedirect(url)
- # You have not submitted a form with errors
- else:
- return render(request,
- TEMPLATEPREFIX+'outing_form.html',
- {'form':form,
- 'theboats':theboats,
- 'reservations':get_future_reservations(),
- 'races':get_future_races(),
- 'member':member,
- 'damagedboats':get_damagedboats(),
- 'plannedwork':plannedwork,
- 'message':message,
- 'jsonmembers':getmembers_json(request.user),
- 'successmessage':successmessage,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
+ # form is valid and you have some reservation (for today)
+ if len(myreservations) != 0:
+ nextreservation=myreservations.first()
+ # you are taking the boat that you reserved
+
+ if (nextreservation.boat == boat):
+ nextreservation.starttime = starttime
+ nextreservation.status = "active"
+ nextreservation.distance = dist
+ nextreservation.save()
+ for member in additionalcrew:
+ nextreservation.otherrowers.add(member)
+ nextreservation.save()
+ # you are taking another boat
+ else:
+ o = Outing(starttime=starttime,rower=member,
+ boat=boat,distance=dist,
+ status="active")
+ o.save()
+ for member in additionalcrew:
+ o.otherrowers.add(member)
+ o.save()
+ # form is valid and you have no reservations
+ else:
+ o = Outing(starttime=starttime,rower=member,boat=boat,
+ distance=dist,
+ status="active")
+ o.save()
+ for member in additionalcrew:
+ o.otherrowers.add(member)
+ o.save()
+ if not settings.DEBUG:
+ logout(request)
+ url = reverse(base_view)
+ return HttpResponseRedirect(url)
+ # You have not submitted a form with errors
+ else:
+ return render(request,
+ TEMPLATEPREFIX+'outing_form.html',
+ {'form':form,
+ 'theboats':theboats,
+ 'reservations':get_future_reservations(),
+ 'races':get_future_races(),
+ 'member':member,
+ 'damagedboats':get_damagedboats(),
+ 'plannedwork':plannedwork,
+ 'message':message,
+ 'jsonmembers':getmembers_json(request.user),
+ 'successmessage':successmessage,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
# You have not submitted the form
else:
- form = OutingForm(
- initial={'distance':12,
- }
- )
- today = timezone.now().date()
- myreservations = Outing.objects.filter(status="reservation",
- rower=member,
- starttime__year=today.year,
- starttime__month=today.month,
- starttime__day=today.day).order_by("starttime")
+ form = OutingForm(
+ initial={'distance':12,
+ }
+ )
+ today = timezone.now().date()
+ myreservations = Outing.objects.filter(status="reservation",
+ rower=member,
+ starttime__year=today.year,
+ starttime__month=today.month,
+ starttime__day=today.day).order_by("starttime")
- form = OutingForm(
- initial={
- 'distance':12,
- })
- return render(request,
- TEMPLATEPREFIX+'outing_form.html',
- {'form':form,
- 'theboats':theboats,
- 'reservations':get_future_reservations(),
- 'member':member,
- 'races':get_future_races(),
- 'damagedboats':get_damagedboats(),
- 'plannedwork':plannedwork,
- 'message':message,
- 'successmessage':successmessage,
- 'jsonmembers':getmembers_json(request.user),
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
+ form = OutingForm(
+ initial={
+ 'distance':12,
+ })
+ return render(request,
+ TEMPLATEPREFIX+'outing_form.html',
+ {'form':form,
+ 'theboats':theboats,
+ 'reservations':get_future_reservations(),
+ 'member':member,
+ 'races':get_future_races(),
+ 'damagedboats':get_damagedboats(),
+ 'plannedwork':plannedwork,
+ 'message':message,
+ 'successmessage':successmessage,
+ 'jsonmembers':getmembers_json(request.user),
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
+
-
@user_passes_test(thisclub_member,login_url="/cvkbrno/login")
def closeouting_view(request,message="",successmessage=""):
cleanoldreservations()
member = Member.objects.get(user=request.user)
activeoutings = Outing.objects.filter(rower=member,status="active")
if (len(activeoutings)==0):
- # no active outings
- errormessg = _("You have no active outings. Go rowing first.").encode('utf8')
- url = reverse(createouting_view,
- kwargs = {
- 'message':str(errormessg),
- })
+ # no active outings
+ errormessg = _("You have no active outings. Go rowing first.").encode('utf8')
+ url = reverse(createouting_view,
+ kwargs = {
+ 'message':str(errormessg),
+ })
- return HttpResponseRedirect(url)
+ return HttpResponseRedirect(url)
if request.method == 'POST':
- # Form was submitted
- form = OutingCloseForm(request.POST)
- if form.is_valid():
- # Get values from form
- dist = request.POST['distance']
- comment = request.POST['comment']
- endtime = timezone.now()
- damagecheck = request.POST['damagecheck']
- o = Outing.objects.get(rower=member,status="active")
- if (damagecheck == "No"):
- o.boat.status = _("damaged")
- o.boat.comment += "\n"+timezone.localtime(timezone.now()).strftime('%Y-%m-%d %H:%M:%S')
- o.boat.comment += " "+comment
- else:
- o.boat.status = "hangar"
- o.boat.save()
- o.endtime = endtime
- o.comment = comment
- o.distance = dist
- o.status = "completed"
- o.save()
- if not settings.DEBUG:
- logout(request)
- url = reverse(base_view)
- return HttpResponseRedirect(url)
-
+ # Form was submitted
+ form = OutingCloseForm(request.POST)
+ if form.is_valid():
+ # Get values from form
+ dist = request.POST['distance']
+ comment = request.POST['comment']
+ endtime = timezone.now()
+ damagecheck = request.POST['damagecheck']
+ o = Outing.objects.get(rower=member,status="active")
+ if (damagecheck == "No"):
+ o.boat.status = _("damaged")
+ o.boat.comment += "\n"+timezone.localtime(timezone.now()).strftime('%Y-%m-%d %H:%M:%S')
+ o.boat.comment += " "+comment
+ else:
+ o.boat.status = "hangar"
+ o.boat.save()
+ o.endtime = endtime
+ o.comment = comment
+ o.distance = dist
+ o.status = "completed"
+ o.save()
+ if not settings.DEBUG:
+ logout(request)
+ url = reverse(base_view)
+ return HttpResponseRedirect(url)
+
else:
- outing = Outing.objects.get(rower=member,status="active")
- form = OutingCloseForm()
- return render(request,
- TEMPLATEPREFIX+'outing_closeform.html',
- {'form':form,
- 'outing':outing,
- 'thisclub_admin':thisclub_admin(request.user),
- 'message':message,
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
+ outing = Outing.objects.get(rower=member,status="active")
+ form = OutingCloseForm()
+ return render(request,
+ TEMPLATEPREFIX+'outing_closeform.html',
+ {'form':form,
+ 'outing':outing,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'message':message,
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
def get_races(datum):
allraces = Races.objects.filter(enddatetime__gt=datum)
@@ -1208,13 +1208,13 @@ def transport_view(request,message="",successmessage=""):
cleanoldreservations()
theraces = get_future_races()
return render(request,
- TEMPLATEPREFIX+'races_list.html',
- {'races':theraces,
- 'thisclub_admin':thisclub_admin(request.user),
- 'message':message,
- 'successmessage':successmessage,
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,
- })
+ TEMPLATEPREFIX+'races_list.html',
+ {'races':theraces,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'message':message,
+ 'successmessage':successmessage,
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,
+ })
@user_passes_test(thisclub_admin,login_url="/cvkbrno/login")
@@ -1223,102 +1223,102 @@ def transport_add_view(request,message="",successmessage=""):
member = Member.objects.get(user=request.user)
theboats = Boat.objects.all().order_by("boatcode")
if request.method=='POST':
- #Form was submitted
- form = RacesEditForm(request.POST)
- if form.is_valid():
- # Get values from form
- name = form.cleaned_data['name']
- startdate = form.cleaned_data['startdate']
- starttime = form.cleaned_data['starttime']
- enddate = form.cleaned_data['enddate']
- endtime = form.cleaned_data['endtime']
- transportboats = form.cleaned_data['transportboats']
+ #Form was submitted
+ form = RacesEditForm(request.POST)
+ if form.is_valid():
+ # Get values from form
+ name = form.cleaned_data['name']
+ startdate = form.cleaned_data['startdate']
+ starttime = form.cleaned_data['starttime']
+ enddate = form.cleaned_data['enddate']
+ endtime = form.cleaned_data['endtime']
+ transportboats = form.cleaned_data['transportboats']
- startdatetime = (str(startdate) + ' ' + str(starttime))
- startdatetime = datetime.datetime.strptime(startdatetime,
- "%Y-%m-%d %H:%M:%S")
- startdatetime = timezone.make_aware(startdatetime,
- timezone=LOCALTIMEZONE)
- enddatetime = (str(enddate) + ' ' + str(endtime))
- enddatetime = datetime.datetime.strptime(enddatetime,
- "%Y-%m-%d %H:%M:%S")
- enddatetime = timezone.make_aware(enddatetime,
- timezone=LOCALTIMEZONE)
+ startdatetime = (str(startdate) + ' ' + str(starttime))
+ startdatetime = datetime.datetime.strptime(startdatetime,
+ "%Y-%m-%d %H:%M:%S")
+ startdatetime = timezone.make_aware(startdatetime,
+ timezone=LOCALTIMEZONE)
+ enddatetime = (str(enddate) + ' ' + str(endtime))
+ enddatetime = datetime.datetime.strptime(enddatetime,
+ "%Y-%m-%d %H:%M:%S")
+ enddatetime = timezone.make_aware(enddatetime,
+ timezone=LOCALTIMEZONE)
- r = Races(name=name,
- startdatetime=startdatetime,
- enddatetime=enddatetime)
+ r = Races(name=name,
+ startdatetime=startdatetime,
+ enddatetime=enddatetime)
- r.save()
- for b in transportboats:
- r.transportboats.add(b)
- o = Outing(starttime=startdatetime,
- endtime=enddatetime,
- distance=0,
- comment=name,
- boat=b,
- rower=member,
- status="race")
- o.save()
- o.race.add(r)
- o.save()
+ r.save()
+ for b in transportboats:
+ r.transportboats.add(b)
+ o = Outing(starttime=startdatetime,
+ endtime=enddatetime,
+ distance=0,
+ comment=name,
+ boat=b,
+ rower=member,
+ status="race")
+ o.save()
+ o.race.add(r)
+ o.save()
- r.save()
- successmessage = _("Race has been saved").encode('utf8')
- return render(request,
- TEMPLATEPREFIX+'races_list.html',
- {
- 'thisclub_admin':thisclub_admin(request.user),
- 'message':message,
- 'races':get_future_races(),
- 'successmessage':successmessage,
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,
- })
- else:
- return render(request,
- TEMPLATEPREFIX+'races_form.html',
- {'form':form,
- 'theboats':theboats,
- 'thisclub_admin':thisclub_admin(request.user),
- 'message':message,
- 'successmessage':successmessage,
- 'worked_hours':Member.objects.get(user=request.user).hoursworked, })
+ r.save()
+ successmessage = _("Race has been saved").encode('utf8')
+ return render(request,
+ TEMPLATEPREFIX+'races_list.html',
+ {
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'message':message,
+ 'races':get_future_races(),
+ 'successmessage':successmessage,
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,
+ })
+ else:
+ return render(request,
+ TEMPLATEPREFIX+'races_form.html',
+ {'form':form,
+ 'theboats':theboats,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'message':message,
+ 'successmessage':successmessage,
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked, })
else:
- form = RacesEditForm()
+ form = RacesEditForm()
+
+ return render(request,
+ TEMPLATEPREFIX+'races_form.html',
+ {'form':form,
+ 'theboats':theboats,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'message':message,
+ 'successmessage':successmessage,
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,
+ })
- return render(request,
- TEMPLATEPREFIX+'races_form.html',
- {'form':form,
- 'theboats':theboats,
- 'thisclub_admin':thisclub_admin(request.user),
- 'message':message,
- 'successmessage':successmessage,
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,
- })
-
@user_passes_test(thisclub_admin,login_url="cvkbrno/login")
def races_admin_delete_view(request,id):
# put in a try except block
try:
- therace = Races.objects.get(id=id)
- theoutings = Outing.objects.filter(race=therace)
+ therace = Races.objects.get(id=id)
+ theoutings = Outing.objects.filter(race=therace)
- for outing in theoutings:
- outing.delete()
+ for outing in theoutings:
+ outing.delete()
- therace.delete()
+ therace.delete()
except ObjectDoesNotExist:
- pass
-
+ pass
+
successmessage = _("Race deleted")
url = reverse(transport_view,
- kwargs={
- 'successmessage':successmessage,
- })
+ kwargs={
+ 'successmessage':successmessage,
+ })
return HttpResponseRedirect(url)
@@ -1328,27 +1328,27 @@ def members_work_complete_view(request,id=0):
thework.status = "executed"
thework.save()
for member in thework.worker.all():
- member.hoursworked+=thework.hours
- member.save()
+ member.hoursworked+=thework.hours
+ member.save()
theworks = MemberWork.objects.filter(status='planned')
return render(request,
- TEMPLATEPREFIX+'memberswork_admin.html',
- {'theworks':theworks,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
+ TEMPLATEPREFIX+'memberswork_admin.html',
+ {'theworks':theworks,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
@user_passes_test(thisclub_admin,login_url="/cvkbrno/login")
def members_work_delete_view(request,id=0):
thework = MemberWork.objects.get(id=id)
thework.delete()
-
+
theworks = MemberWork.objects.filter(status='planned')
return render(request,
- TEMPLATEPREFIX+'memberswork_admin.html',
- {'theworks':theworks,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
+ TEMPLATEPREFIX+'memberswork_admin.html',
+ {'theworks':theworks,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
@user_passes_test(thisclub_member,login_url="/cvkbrno/login")
def members_work_addme(request,id,message="",successmessage=""):
@@ -1377,78 +1377,78 @@ def makereservation_view(request,message="",successmessage=""):
theboats = get_availableboats_reservation(member,timezone.now())
# theboats = Boat.objects.filter(status__in = ["hangar", "water", "races"])
if (len(activeoutings)!=0):
- # we are still out
- url = reverse(closeouting_view)
- return HttpResponseRedirect(url)
+ # we are still out
+ url = reverse(closeouting_view)
+ return HttpResponseRedirect(url)
if request.method == 'POST':
- # Form was submitted
- form = OutingReserveForm(request.POST)
- if form.is_valid():
- # Get values from form
- dist = request.POST['distance']
- boat = Boat.objects.get(id=request.POST['boat'])
- stime = request.POST['starttime']
- sdate = request.POST['startdate']
- etime = request.POST['endtime']
-
- starttime = parser.parse(sdate+' '+stime)
- #starttime = timezone.make_aware(starttime)
- starttime = LOCALTIMEZONE.localize(starttime)
-
- endtime = parser.parse(sdate+' '+etime)
- #endtime = timezone.make_aware(endtime)
- endtime = LOCALTIMEZONE.localize(endtime)
-
- # check if conflicting reservations exist
- check,errormessg = conflicting_reservations(boat,starttime,endtime)
+ # Form was submitted
+ form = OutingReserveForm(request.POST)
+ if form.is_valid():
+ # Get values from form
+ dist = request.POST['distance']
+ boat = Boat.objects.get(id=request.POST['boat'])
+ stime = request.POST['starttime']
+ sdate = request.POST['startdate']
+ etime = request.POST['endtime']
- if check:
- url = reverse(makereservation_view,
- kwargs = {
- 'message':errormessg,
- })
+ starttime = parser.parse(sdate+' '+stime)
+ #starttime = timezone.make_aware(starttime)
+ starttime = LOCALTIMEZONE.localize(starttime)
- return HttpResponseRedirect(url)
- else:
- o = Outing(starttime=starttime,endtime=endtime,rower=member,
- boat=boat,distance=dist,
- status="reservation")
- o.save()
- # if not settings.DEBUG:
- # logout(request)
- url = reverse(base_view)
- return HttpResponseRedirect(url)
- else:
- return render(request,
- TEMPLATEPREFIX+'reservation_form.html',
- {'form':form,
- 'theboats':theboats,
- 'reservations':get_future_reservations(),
- 'message':message,
- 'successmessage':successmessage,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
-
+ endtime = parser.parse(sdate+' '+etime)
+ #endtime = timezone.make_aware(endtime)
+ endtime = LOCALTIMEZONE.localize(endtime)
+
+ # check if conflicting reservations exist
+ check,errormessg = conflicting_reservations(boat,starttime,endtime)
+
+ if check:
+ url = reverse(makereservation_view,
+ kwargs = {
+ 'message':errormessg,
+ })
+
+ return HttpResponseRedirect(url)
+ else:
+ o = Outing(starttime=starttime,endtime=endtime,rower=member,
+ boat=boat,distance=dist,
+ status="reservation")
+ o.save()
+ # if not settings.DEBUG:
+ # logout(request)
+ url = reverse(base_view)
+ return HttpResponseRedirect(url)
else:
- nownaive = timezone.now().replace(tzinfo=None)
- nowlocal = timezone.now().astimezone(LOCALTIMEZONE)
+ return render(request,
+ TEMPLATEPREFIX+'reservation_form.html',
+ {'form':form,
+ 'theboats':theboats,
+ 'reservations':get_future_reservations(),
+ 'message':message,
+ 'successmessage':successmessage,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
+
+ else:
+ nownaive = timezone.now().replace(tzinfo=None)
+ nowlocal = timezone.now().astimezone(LOCALTIMEZONE)
+
+ form = OutingReserveForm(
+ initial={'distance':11,
+ 'starttime': nowlocal,
+ 'startdate': nowlocal,
+ 'endtime': nowlocal+datetime.timedelta(hours=1.5)}
+ )
+ return render(request,
+ TEMPLATEPREFIX+'reservation_form.html',
+ {'form':form,
+ 'theboats':theboats,
+ 'reservations':get_future_reservations(),
+ 'message':message,
+ 'successmessage':successmessage,
+ 'thisclub_admin':thisclub_admin(request.user),
+ 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
- form = OutingReserveForm(
- initial={'distance':11,
- 'starttime': nowlocal,
- 'startdate': nowlocal,
- 'endtime': nowlocal+datetime.timedelta(hours=1.5)}
- )
- return render(request,
- TEMPLATEPREFIX+'reservation_form.html',
- {'form':form,
- 'theboats':theboats,
- 'reservations':get_future_reservations(),
- 'message':message,
- 'successmessage':successmessage,
- 'thisclub_admin':thisclub_admin(request.user),
- 'worked_hours':Member.objects.get(user=request.user).hoursworked,})
-
return HttpResponse(_("Make a reservation"))
@@ -1473,15 +1473,15 @@ def addmemberwork(formdict):
hours = int(formdict['hours'])
status = 'planned'
thework = MemberWork(date=date,
- hours=hours,
- name=name,status=status,comment=comment)
+ hours=hours,
+ name=name,status=status,comment=comment)
thework.save()
if len(worker) != 0:
- for index in worker:
- theworker = Member.objects.get(id=index)
- thework.worker.add(theworker)
- thework.save()
-
+ for index in worker:
+ theworker = Member.objects.get(id=index)
+ thework.worker.add(theworker)
+ thework.save()
+
id = thework.id
theview = members_work_admin_view
successmessage = _("Members Work Created")
@@ -1491,45 +1491,45 @@ def addmemberwork(formdict):
members = getclubmembers()
bcclist = []
for member in members:
- bcclist.append(member.user.email)
+ bcclist.append(member.user.email)
print bcclist
- if settings.DEBUG:
- res = handle_sendemailwork.delay(bcclist,thework.name,
- thework.date,thework.comment)
+ if settings.DEBUG:
+ res = handle_sendemailwork.delay(bcclist,thework.name,
+ thework.date,thework.comment)
else:
- res = queue.enqueue(handle_sendemailwork,bcclist,
- thework.name,thework.date,thework.comment)
+ res = queue.enqueue(handle_sendemailwork,bcclist,
+ thework.name,thework.date,thework.comment)
+
-
return [theview,message,successmessage,id]
def addbulkboat(xlsfile):
df = pd.read_excel(xlsfile)
for index,row in df.iterrows():
- boatcode = df.ix[index,'code']
- boatname = smart_text(df.ix[index,'name'])
- nrseats = df.ix[index,'nrseats']
- status = 'hangar'
- cats = df.ix[index,'categories']
- cats = str(cats).split()
- print boatcode
-
- theboat = Boat(boatcode=boatcode,boatname=boatname,
- nrseats=int(nrseats),
- status=status)
+ boatcode = df.ix[index,'code']
+ boatname = smart_text(df.ix[index,'name'])
+ nrseats = df.ix[index,'nrseats']
+ status = 'hangar'
+ cats = df.ix[index,'categories']
+ cats = str(cats).split()
+ print boatcode
- theboat.save()
- if (len(cats) !=0):
- for index in cats:
- print index
- thecategory = BoatCategory.objects.get(id=index)
- print unidecode.unidecode(thecategory.name)
- theboat.categories.add(thecategory)
+ theboat = Boat(boatcode=boatcode,boatname=boatname,
+ nrseats=int(nrseats),
+ status=status)
- theboat.save()
+ theboat.save()
+ if (len(cats) !=0):
+ for index in cats:
+ print index
+ thecategory = BoatCategory.objects.get(id=index)
+ print unidecode.unidecode(thecategory.name)
+ theboat.categories.add(thecategory)
+
+ theboat.save()
def addboat(formdict):
@@ -1543,25 +1543,25 @@ def addboat(formdict):
status = formdict['status']
comment = formdict['comment']
theboat = Boat(boatcode=boatcode,boatname=boatname,
- nrseats=int(nrseats),
- status=status,comment=comment)
+ nrseats=int(nrseats),
+ status=status,comment=comment)
# check if other boat exists with new code
if len(Boat.objects.filter(boatcode=boatcode)) != 0:
- message = _("There is already a boat with that code")
- theview = boats_admin_add_view
- return [theview,message,"",id]
+ message = _("There is already a boat with that code")
+ theview = boats_admin_add_view
+ return [theview,message,"",id]
else:
- theboat.save()
-
- if len(cats) !=0:
- for index in cats:
- thecategory = BoatCategory.objects.get(id=index)
- theboat.categories.add(thecategory)
+ theboat.save()
- theview = boats_admin_view
- successmessage = _('Boat created')
- message = ''
- return [theview,message,successmessage,id]
+ if len(cats) !=0:
+ for index in cats:
+ thecategory = BoatCategory.objects.get(id=index)
+ theboat.categories.add(thecategory)
+
+ theview = boats_admin_view
+ successmessage = _('Boat created')
+ message = ''
+ return [theview,message,successmessage,id]
def editboat(formdict,theboat):
# do something
@@ -1581,19 +1581,19 @@ def editboat(formdict,theboat):
theboat.categories.clear()
theboat.save()
if (len(cats) !=0):
- for index in cats:
- thecategory = BoatCategory.objects.get(id=index)
- theboat.categories.add(thecategory)
+ for index in cats:
+ thecategory = BoatCategory.objects.get(id=index)
+ theboat.categories.add(thecategory)
# check if other boat exists with new code
if boatcode != theboat.boatcode:
- if len(Boat.objects.filter(boatcode=boatcode)) != 0:
- message = _("There is already a boat with that code")
- theview = boats_admin_edit_view
- theid = theboat.id
- return [theview,message,"",theid]
- else:
- theboat.boatcode = boatcode
+ if len(Boat.objects.filter(boatcode=boatcode)) != 0:
+ message = _("There is already a boat with that code")
+ theview = boats_admin_edit_view
+ theid = theboat.id
+ return [theview,message,"",theid]
+ else:
+ theboat.boatcode = boatcode
theboat.save()
@@ -1604,36 +1604,36 @@ def editboat(formdict,theboat):
def addbulkmember(cats,xlsfile,sheetname):
df = pd.read_excel(xlsfile,sheetname=sheetname)
for index,row in df.iterrows():
- lastname,firstname = df.ix[index,'name'].split()
- email = df.ix[index,'e-mail']
- username = unidecode.unidecode(lastname)+unidecode.unidecode(firstname)[0]
- username = username.lower()
- password = 'cvkbrno'
- contributions = True
- hoursworked = 0
- status = 'member'
+ lastname,firstname = df.ix[index,'name'].split()
+ email = df.ix[index,'e-mail']
+ username = unidecode.unidecode(lastname)+unidecode.unidecode(firstname)[0]
+ username = username.lower()
+ password = 'cvkbrno'
+ contributions = True
+ hoursworked = 0
+ status = 'member'
- print username
-
- theuser = User.objects.create_user(username,password=password)
- theuser.first_name = firstname
- theuser.last_name = lastname
- theuser.email = email
- theuser.save()
+ print username
- themember = Member(user=theuser,status=status,
- contributions=contributions,
- hoursworked=hoursworked,
- club=THISCLUB)
+ theuser = User.objects.create_user(username,password=password)
+ theuser.first_name = firstname
+ theuser.last_name = lastname
+ theuser.email = email
+ theuser.save()
- themember.save()
+ themember = Member(user=theuser,status=status,
+ contributions=contributions,
+ hoursworked=hoursworked,
+ club=THISCLUB)
- if (len(cats) !=0):
- for index in cats:
- thecategory = BoatCategory.objects.get(id=index)
- themember.categories.add(thecategory)
+ themember.save()
- themember.save()
+ if (len(cats) !=0):
+ for index in cats:
+ thecategory = BoatCategory.objects.get(id=index)
+ themember.categories.add(thecategory)
+
+ themember.save()
def addmember(formdict):
message = ""
@@ -1648,50 +1648,50 @@ def addmember(formdict):
first_name = formdict['first_name']
last_name = formdict['last_name']
try:
- contributions = formdict['contributions']
+ contributions = formdict['contributions']
except:
- contributions = False
+ contributions = False
hoursworked = formdict['hoursworked']
cats = dict(formdict)["categories"]
#check if passwords are equal
if (password != password2):
- message = _("The two passwords are not equal")
- theview = members_admin_add_view
- theid = 0
- return [theview,message,"",theid]
-
+ message = _("The two passwords are not equal")
+ theview = members_admin_add_view
+ theid = 0
+ return [theview,message,"",theid]
+
#check if there isn't already a user with this username
if len(User.objects.filter(username=username)) != 0:
- message = _("There is already a user with that username")
- theview = members_admin_add_view
- theid = 0
- return [theview,message,"",theid]
+ message = _("There is already a user with that username")
+ theview = members_admin_add_view
+ theid = 0
+ return [theview,message,"",theid]
else:
- theuser = User.objects.create_user(username,password=password)
- theuser.first_name = first_name
- theuser.last_name = last_name
- theuser.email = email
- theuser.save()
+ theuser = User.objects.create_user(username,password=password)
+ theuser.first_name = first_name
+ theuser.last_name = last_name
+ theuser.email = email
+ theuser.save()
- themember = Member(user=theuser,status=status,
- contributions=contributions,
- hoursworked=hoursworked,
- club=THISCLUB)
+ themember = Member(user=theuser,status=status,
+ contributions=contributions,
+ hoursworked=hoursworked,
+ club=THISCLUB)
- themember.save()
+ themember.save()
- if (len(cats) !=0):
- for index in cats:
- thecategory = BoatCategory.objects.get(id=index)
- themember.categories.add(thecategory)
+ if (len(cats) !=0):
+ for index in cats:
+ thecategory = BoatCategory.objects.get(id=index)
+ themember.categories.add(thecategory)
- themember.save()
+ themember.save()
- successmessage = _("New Member Created")
-
- return [theview,"",successmessage,theid]
+ successmessage = _("New Member Created")
+
+ return [theview,"",successmessage,theid]
def editmemberwork(formdict,thework):
message = ""
@@ -1711,9 +1711,9 @@ def editmemberwork(formdict,thework):
thework.save()
if (len(workers) != 0):
- for index in workers:
- theworker = Member.objects.get(id=index)
- thework.worker.add(theworker)
+ for index in workers:
+ theworker = Member.objects.get(id=index)
+ thework.worker.add(theworker)
thework.save()
successmessage = _("Members Work Updated")
@@ -1729,9 +1729,9 @@ def editmember(formdict,themember):
first_name = formdict['first_name']
last_name = formdict['last_name']
try:
- contributions = formdict['contributions']
+ contributions = formdict['contributions']
except:
- contributions = False
+ contributions = False
hoursworked = formdict['hoursworked']
cats = dict(formdict)["categories"]
email = formdict['email']
@@ -1742,13 +1742,13 @@ def editmember(formdict,themember):
themember.categories.clear()
if (len(cats) !=0):
- for index in cats:
- thecategory = BoatCategory.objects.get(id=index)
- themember.categories.add(thecategory)
+ for index in cats:
+ thecategory = BoatCategory.objects.get(id=index)
+ themember.categories.add(thecategory)
themember.save()
-
+
theuser = themember.user
theuser.first_name = first_name
@@ -1759,5 +1759,3 @@ def editmember(formdict,themember):
successmessage = _("Changes saved")
return [theview,"",successmessage,0]
-
-
diff --git a/rowsandall_app/settings.py b/rowsandall_app/settings.py
index f3c29dcd..3ee00411 100644
--- a/rowsandall_app/settings.py
+++ b/rowsandall_app/settings.py
@@ -49,7 +49,6 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
INSTALLED_APPS = [
'rowers',
'survey',
- 'boatmovers',
# 'cvkbrno',
'django.contrib.admin',
'django.contrib.auth',
@@ -77,6 +76,7 @@ INSTALLED_APPS = [
'django_countries',
'rules',
'taggit',
+ 'boatmovers',
]
AUTHENTICATION_BACKENDS = (
@@ -138,10 +138,7 @@ TEMPLATES = [
],
'libraries': {
'staticfiles': 'django.templatetags.static',
- }
- # 'loaders': [
- # 'django.template.loaders.app_directories.Loader',
- # ],
+ },
},
},
]
diff --git a/rowsandall_app/urls.py b/rowsandall_app/urls.py
index e7fdbfba..7a9fceb3 100644
--- a/rowsandall_app/urls.py
+++ b/rowsandall_app/urls.py
@@ -79,7 +79,8 @@ urlpatterns += [
{'next_page': '/'},
name='logout',),
re_path(r'^rowers/', include('rowers.urls')),
- # re_path(r'^survey/',include('survey.urls')),
+ re_path(r'^boatmovers/',include('boatmovers.urls')),
+ #re_path(r'^survey/',include('survey.urls')),
# re_path(r'^cvkbrno/',include('cvkbrno.urls')),
# re_path(r'^admin/rq/',include('django_rq_dashboard.urls')),
re_path(r'^call\_back', rowersviews.rower_process_callback),
From a3f132b7b33f11e47836c7ba4d439990e2890bbb Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Wed, 22 Jun 2022 22:04:40 +0200
Subject: [PATCH 03/19] d
---
boatmovers/models.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/boatmovers/models.py b/boatmovers/models.py
index 10ffea51..7a7c4b0f 100644
--- a/boatmovers/models.py
+++ b/boatmovers/models.py
@@ -25,7 +25,7 @@ class Athlete(models.Model):
return u'{f} {l}'.format(f = self.first_name, l=self.last_name)
def get_absolute_url(self):
- return "/athlete/%i/" % self.id
+ return "/boatmovers/athlete/%i/" % self.id
class athleteForm(forms.ModelForm):
class Meta:
From 0caf031287841e1b3e804ddc155a54060b62dfdb Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Fri, 24 Jun 2022 10:01:36 +0200
Subject: [PATCH 04/19] generic work on athletes, crews, results
---
boatmovers/results.py | 111 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 111 insertions(+)
create mode 100644 boatmovers/results.py
diff --git a/boatmovers/results.py b/boatmovers/results.py
new file mode 100644
index 00000000..ebfdc0df
--- /dev/null
+++ b/boatmovers/results.py
@@ -0,0 +1,111 @@
+import trueskill
+from trueskill import Rating, rate
+
+class Athlete:
+ def __init__(self, first_name, last_name, club, birth_year, mu=25, sigma=25./3.):
+ self.first_name = first_name
+ self.last_name = last_name
+ self.club = club
+ self.birth_year = birth_year
+ self.rating = Rating(mu, sigma)
+
+ def expose(self):
+ return trueskill.expose(self.rating)
+
+ def setrating(self, rating):
+ self.rating = rating
+
+ def __str__(self):
+ return u'{f} {l} {c} - {s:.2f}'.format(
+ f=self.first_name,
+ l=self.last_name,
+ c=self.club,
+ s=self.expose()
+ )
+
+class Crew:
+ def __init__(self, athletes, name):
+ self.athletes = athletes
+ self.name = name
+
+ def size(self):
+ return len(self.athletes)
+
+ def __str__(self):
+ return u'{n}'.format(n=self.name)
+
+class Result:
+ def __init__(self, crews, name, validated=False, processed=False):
+ self.crews = crews
+ self.name = name
+ self.validated = validated
+ self.processed = processed
+
+ def validate(self):
+ # crews need to be more than 2
+ if len(self.crews) < 2:
+ self.validated = False
+ return False
+
+ # crews need to be all same length
+ l = self.crews[0].size()
+ for crew in self.crews:
+ if crew.size() != l:
+ self.validated = False
+ return False
+
+ # crew length need to be 1, 2, 4 or 8
+ if l not in [1,2,4,8]:
+ self.validated = False
+ return False
+
+ # cannot have same crew multiple times in same race
+ if len(self.crews) != len(set(self.crews)):
+ self.validated = False
+ return False
+
+ # cannot have same athletes in different crews in same race
+ allathletes = []
+ for crew in self.crews:
+ for athlete in crew.athletes:
+ allathletes.append(athlete)
+
+ if len(allathletes) != len(set(allathletes)):
+ self.validated = False
+ return False
+
+ self.validated = True
+ return self.validated
+
+ def process(self):
+ if not self.validated:
+ if not self.validate():
+ return False
+
+ if self.processed:
+ return True
+
+ # validate the race
+ ratings = list([athlete.rating for athlete in crew.athletes] for crew in self.crews)
+ result = rate(ratings, ranks = list(range(len(self.crews))))
+
+ i = 0
+ j = 0
+
+ for c in result:
+ for rating in c:
+ self.crews[i].athletes[j].setrating(rating)
+ j += 1
+ i += 1
+ j = 0
+
+ self.processed = True
+
+ return True
+
+ def __str__(self):
+ s = self.name + ': '
+ for crew in self.crews:
+ s = s + str(crew) + ', '
+
+ return s[:-2]
From f55e5a2fefa69f8c8477a44b845ecc1bd461c229 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Fri, 24 Jun 2022 13:35:34 +0200
Subject: [PATCH 05/19] add crew view
---
.../migrations/0006_auto_20220624_0811.py | 23 ++++++
.../migrations/0007_auto_20220624_0820.py | 24 ++++++
boatmovers/models.py | 78 ++++++++++++++++++-
.../templates/boatmovers/crew_form.html | 4 +
boatmovers/urls.py | 2 +
boatmovers/views.py | 16 +++-
6 files changed, 142 insertions(+), 5 deletions(-)
create mode 100644 boatmovers/migrations/0006_auto_20220624_0811.py
create mode 100644 boatmovers/migrations/0007_auto_20220624_0820.py
create mode 100644 boatmovers/templates/boatmovers/crew_form.html
diff --git a/boatmovers/migrations/0006_auto_20220624_0811.py b/boatmovers/migrations/0006_auto_20220624_0811.py
new file mode 100644
index 00000000..6b234db8
--- /dev/null
+++ b/boatmovers/migrations/0006_auto_20220624_0811.py
@@ -0,0 +1,23 @@
+# Generated by Django 3.2.12 on 2022-06-24 08:11
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('boatmovers', '0005_athlete_gender'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='athlete',
+ name='trueskill_exposed',
+ field=models.FloatField(default=0),
+ ),
+ migrations.AlterField(
+ model_name='athlete',
+ name='trueskill_sigma',
+ field=models.FloatField(default=8.333333333333334),
+ ),
+ ]
diff --git a/boatmovers/migrations/0007_auto_20220624_0820.py b/boatmovers/migrations/0007_auto_20220624_0820.py
new file mode 100644
index 00000000..4c4355fa
--- /dev/null
+++ b/boatmovers/migrations/0007_auto_20220624_0820.py
@@ -0,0 +1,24 @@
+# Generated by Django 3.2.12 on 2022-06-24 08:20
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('boatmovers', '0006_auto_20220624_0811'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='result',
+ name='crew',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='results', to='boatmovers.crew'),
+ ),
+ migrations.AlterField(
+ model_name='result',
+ name='race',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='results', to='boatmovers.race'),
+ ),
+ ]
diff --git a/boatmovers/models.py b/boatmovers/models.py
index 7a7c4b0f..8785c275 100644
--- a/boatmovers/models.py
+++ b/boatmovers/models.py
@@ -1,7 +1,10 @@
from django.db import models
from django import forms
+from django.core.exceptions import ValidationError
+
import datetime
from django.utils import timezone
+import trueskill
def current_day(ttz=None):
if ttz is None:
@@ -14,7 +17,8 @@ class Athlete(models.Model):
last_name = models.CharField(max_length=200)
club = models.CharField(max_length=200)
trueskill_mu = models.FloatField(default=25.)
- trueskill_sigma = models.FloatField(default=8.333)
+ trueskill_sigma = models.FloatField(default=25./3.)
+ trueskill_exposed = models.FloatField(default=0)
birth_year = models.IntegerField(default=1972)
gender = models.CharField(max_length=200, choices=(('m','M'),('f','F')))
@@ -24,6 +28,12 @@ class Athlete(models.Model):
def __str__(self):
return u'{f} {l}'.format(f = self.first_name, l=self.last_name)
+ def save(self, *args, **kwargs):
+ rating = trueskill.Rating(self.trueskill_mu, self.trueskill_sigma)
+ self.trueskill_exposed = trueskill.expose(rating)
+
+ super(Athlete, self).save(*args, **kwargs)
+
def get_absolute_url(self):
return "/boatmovers/athlete/%i/" % self.id
@@ -39,13 +49,22 @@ class Crew(models.Model):
def __str__(self):
return u'{n}'.format(n=self.name)
+ def save(self, *args, **kwargs):
+ super(Crew, self).save(*args, **kwargs)
+
+class crewForm(forms.ModelForm):
+ class Meta:
+ model = Crew
+ fields = ['name', 'athletes']
+
class Race(models.Model):
name = models.CharField(max_length=200)
resulturl = models.URLField(null=True)
date = models.DateField(default=current_day)
resultlist = models.ManyToManyField(Crew,through='Result')
- crew_size = models.IntegerField(default=1)
+ crew_size = models.IntegerField(default=1,verbose_name='Nr of rowers per crew (1, 2, 4, 8)')
verified = models.BooleanField(default=False)
+ processed = models.BooleanField(default=True)
class Meta:
unique_together = ('date','name')
@@ -53,10 +72,61 @@ class Race(models.Model):
def __str__(self):
return self.name
+ def save(self, *args, **kwargs):
+ results = self.results.all()
+ crews = []
+ athletes = []
+ for result in results:
+ crews.append(result.crew.id)
+ for athlete in result.crew.athletes.all():
+ athletes.append(athlete.id)
+
+ if len(crews) != len(set(crews)):
+ raise ValidationError(
+ "Cannot have the same crew more than one time in a race"
+ )
+
+ if len(athletes) != len(set(athletes)):
+ raise ValidationError(
+ "Cannot have the same athlete in different crews in a race"
+ )
+
+ super(Race, self).save(*args, **kwargs)
+
+class raceForm(forms.ModelForm):
+ class Meta:
+ model = Race
+ fields = ['name','date','resulturl','crew_size','resultlist']
+
+
class Result(models.Model):
- crew = models.ForeignKey(Crew, on_delete=models.CASCADE)
- race = models.ForeignKey(Race, on_delete=models.CASCADE)
+ crew = models.ForeignKey(Crew, on_delete=models.CASCADE,
+ related_name='results')
+ race = models.ForeignKey(Race, on_delete=models.CASCADE,
+ related_name='results')
order = models.PositiveIntegerField()
class Meta:
unique_together = ('crew','race','order')
+
+ def save(self, *args, **kwargs):
+ allresults = self.race.results.all()
+ athletes = []
+ for result in allresults:
+ for athlete in result.crew.athletes.all():
+ athletes.append(athlete.id)
+ if result.crew.id == self.crew.id:
+ raise ValidationError(
+ "Cannot have the same crew more than one time in a race"
+ )
+ if len(athletes) != len(set(athletes)):
+ raise ValidationError(
+ "Cannot have the same athlete in different crews in a race"
+ )
+
+ super(Result,self).save(*args, **kwargs)
+
+class resultForm(forms.ModelForm):
+ class Meta:
+ model = Result
+ fields = ['crew','race','order']
diff --git a/boatmovers/templates/boatmovers/crew_form.html b/boatmovers/templates/boatmovers/crew_form.html
new file mode 100644
index 00000000..a9b32c5f
--- /dev/null
+++ b/boatmovers/templates/boatmovers/crew_form.html
@@ -0,0 +1,4 @@
+
diff --git a/boatmovers/urls.py b/boatmovers/urls.py
index 46028e74..71b8da8e 100644
--- a/boatmovers/urls.py
+++ b/boatmovers/urls.py
@@ -6,4 +6,6 @@ import boatmovers.views as views
urlpatterns = [
url(r'athlete/add/$',views.AthleteCreateView.as_view(),name='athlete_add'),
+ url(r'crew/add/$',views.CrewCreateView.as_view(),name='crew_add'),
+ url(r'^$',views.boatmovers_view,name='boatmovers')
]
diff --git a/boatmovers/views.py b/boatmovers/views.py
index 3e98e380..04ab5de1 100644
--- a/boatmovers/views.py
+++ b/boatmovers/views.py
@@ -1,8 +1,9 @@
from django.shortcuts import render
+from django.http import HttpResponse
# Create your views here.
from django.views.generic.edit import CreateView
-from boatmovers.models import Athlete
+from boatmovers.models import Athlete, Crew
class AthleteCreateView(CreateView):
model = Athlete
@@ -13,3 +14,16 @@ class AthleteCreateView(CreateView):
'gender',
'club',
]
+ success_url = '/boatmovers/'
+
+class CrewCreateView(CreateView):
+ model = Crew
+ fields = [
+ 'name',
+ 'athletes'
+ ]
+
+ success_url = '/boatmovers/'
+
+def boatmovers_view(request):
+ return HttpResponse("1")
From f606a7aa0944c66762599475f7bced991f0bb4dd Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Fri, 24 Jun 2022 16:17:18 +0200
Subject: [PATCH 06/19] Basic functionality is there
---
.../migrations/0008_auto_20220624_1135.py | 23 ++++
.../migrations/0009_alter_race_crew_size.py | 18 ++++
.../migrations/0010_remove_race_resultlist.py | 17 +++
.../migrations/0011_alter_race_processed.py | 18 ++++
boatmovers/models.py | 102 ++++++++++++++++--
boatmovers/results.py | 18 ++--
boatmovers/templates/boatmovers.html | 69 ++++++++++++
.../templates/boatmovers/race_form.html | 4 +
.../templates/boatmovers/result_form.html | 4 +
boatmovers/templates/race.html | 45 ++++++++
boatmovers/urls.py | 5 +
boatmovers/views.py | 62 ++++++++++-
12 files changed, 366 insertions(+), 19 deletions(-)
create mode 100644 boatmovers/migrations/0008_auto_20220624_1135.py
create mode 100644 boatmovers/migrations/0009_alter_race_crew_size.py
create mode 100644 boatmovers/migrations/0010_remove_race_resultlist.py
create mode 100644 boatmovers/migrations/0011_alter_race_processed.py
create mode 100644 boatmovers/templates/boatmovers.html
create mode 100644 boatmovers/templates/boatmovers/race_form.html
create mode 100644 boatmovers/templates/boatmovers/result_form.html
create mode 100644 boatmovers/templates/race.html
diff --git a/boatmovers/migrations/0008_auto_20220624_1135.py b/boatmovers/migrations/0008_auto_20220624_1135.py
new file mode 100644
index 00000000..d5492e47
--- /dev/null
+++ b/boatmovers/migrations/0008_auto_20220624_1135.py
@@ -0,0 +1,23 @@
+# Generated by Django 3.2.12 on 2022-06-24 11:35
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('boatmovers', '0007_auto_20220624_0820'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='race',
+ name='processed',
+ field=models.BooleanField(default=True),
+ ),
+ migrations.AlterField(
+ model_name='race',
+ name='crew_size',
+ field=models.IntegerField(default=1, verbose_name='Nr of rowers per crew (1, 2, 4, 8)'),
+ ),
+ ]
diff --git a/boatmovers/migrations/0009_alter_race_crew_size.py b/boatmovers/migrations/0009_alter_race_crew_size.py
new file mode 100644
index 00000000..4207ae30
--- /dev/null
+++ b/boatmovers/migrations/0009_alter_race_crew_size.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.12 on 2022-06-24 12:48
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('boatmovers', '0008_auto_20220624_1135'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='race',
+ name='crew_size',
+ field=models.IntegerField(choices=[(1, 1), (2, 2), (4, 4), (8, 8)], default=1, verbose_name='Nr of rowers per crew (1, 2, 4, 8)'),
+ ),
+ ]
diff --git a/boatmovers/migrations/0010_remove_race_resultlist.py b/boatmovers/migrations/0010_remove_race_resultlist.py
new file mode 100644
index 00000000..e6d9403e
--- /dev/null
+++ b/boatmovers/migrations/0010_remove_race_resultlist.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.2.12 on 2022-06-24 12:50
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('boatmovers', '0009_alter_race_crew_size'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='race',
+ name='resultlist',
+ ),
+ ]
diff --git a/boatmovers/migrations/0011_alter_race_processed.py b/boatmovers/migrations/0011_alter_race_processed.py
new file mode 100644
index 00000000..f8b81cb7
--- /dev/null
+++ b/boatmovers/migrations/0011_alter_race_processed.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.12 on 2022-06-24 12:53
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('boatmovers', '0010_remove_race_resultlist'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='race',
+ name='processed',
+ field=models.BooleanField(default=False),
+ ),
+ ]
diff --git a/boatmovers/models.py b/boatmovers/models.py
index 8785c275..b2664c4b 100644
--- a/boatmovers/models.py
+++ b/boatmovers/models.py
@@ -52,6 +52,9 @@ class Crew(models.Model):
def save(self, *args, **kwargs):
super(Crew, self).save(*args, **kwargs)
+ def size(self):
+ return self.athletes.all().count()
+
class crewForm(forms.ModelForm):
class Meta:
model = Crew
@@ -59,12 +62,13 @@ class crewForm(forms.ModelForm):
class Race(models.Model):
name = models.CharField(max_length=200)
- resulturl = models.URLField(null=True)
- date = models.DateField(default=current_day)
- resultlist = models.ManyToManyField(Crew,through='Result')
- crew_size = models.IntegerField(default=1,verbose_name='Nr of rowers per crew (1, 2, 4, 8)')
+ resulturl = models.URLField(null=True, verbose_name='URL Link to results')
+ date = models.DateField(default=current_day, verbose_name='Race Date')
+ #resultlist = models.ManyToManyField(Result,through='Result')
+ crew_size = models.IntegerField(default=1,verbose_name='Nr of rowers per crew (1, 2, 4, 8)',
+ choices=((1,1),(2,2),(4,4),(8,8)))
verified = models.BooleanField(default=False)
- processed = models.BooleanField(default=True)
+ processed = models.BooleanField(default=False)
class Meta:
unique_together = ('date','name')
@@ -93,10 +97,87 @@ class Race(models.Model):
super(Race, self).save(*args, **kwargs)
+ def validate(self):
+ if len(self.results.all()) < 2:
+ self.verified = False
+ self.save()
+ return False
+
+ l = self.results.all()[0].crew.size()
+ for result in self.results.all():
+ if result.crew.size() != l:
+ self.verified = False
+ self.save()
+ return False
+
+ if l not in [1,2,4,8]:
+ self.verified = False
+ self.save()
+ return False
+
+ results = self.results.all()
+ crews = []
+ athletes = []
+ for result in results:
+ crews.append(result.crew.id)
+ for athlete in result.crew.athletes.all():
+ athletes.append(athlete.id)
+
+ if len(crews) != len(set(crews)):
+ self.verified = False
+ self.save()
+ return False
+
+ if len(athletes) != len(set(athletes)):
+ self.verified = False
+ self.save()
+ return False
+
+ self.verified = True
+ self.save()
+
+ def process(self):
+ if not self.verified:
+ if not self.validate():
+ return False
+
+ if self.processed:
+ return True
+
+ # validate the race
+ results = self.results.all().order_by('order')
+ crews = []
+ ranks = []
+
+ for result in results:
+ crew = result.crew
+ crewdict = {}
+ for athlete in crew.athletes.all():
+ crewdict[athlete.id] = trueskill.Rating(
+ athlete.trueskill_mu, athlete.trueskill_sigma)
+ crews.append(crewdict)
+ ranks.append(result.order)
+
+ rated_crews = trueskill.rate(crews, ranks)
+
+ for crew in rated_crews:
+
+ for id, rating in crew.items():
+ athlete = Athlete.objects.get(id=id)
+ athlete.trueskill_mu = rating.mu
+ athlete.trueskill_sigma = rating.sigma
+ athlete.save()
+
+ self.processed = True
+ self.save()
+
+ return True
+
+
class raceForm(forms.ModelForm):
class Meta:
model = Race
- fields = ['name','date','resulturl','crew_size','resultlist']
+ fields = ['name','date','resulturl','crew_size']
class Result(models.Model):
@@ -107,7 +188,14 @@ class Result(models.Model):
order = models.PositiveIntegerField()
class Meta:
- unique_together = ('crew','race','order')
+ unique_together = ('crew','order')
+
+ def __str__(self):
+ return u'{r}: {o} - {c}'.format(
+ r=self.race,
+ o=self.order,
+ c=self.crew,
+ )
def save(self, *args, **kwargs):
allresults = self.race.results.all()
diff --git a/boatmovers/results.py b/boatmovers/results.py
index ebfdc0df..168a51a6 100644
--- a/boatmovers/results.py
+++ b/boatmovers/results.py
@@ -38,30 +38,30 @@ class Result:
def __init__(self, crews, name, validated=False, processed=False):
self.crews = crews
self.name = name
- self.validated = validated
+ self.verified = validated
self.processed = processed
def validate(self):
# crews need to be more than 2
if len(self.crews) < 2:
- self.validated = False
+ self.verified = False
return False
# crews need to be all same length
l = self.crews[0].size()
for crew in self.crews:
if crew.size() != l:
- self.validated = False
+ self.verified = False
return False
# crew length need to be 1, 2, 4 or 8
if l not in [1,2,4,8]:
- self.validated = False
+ self.verified = False
return False
# cannot have same crew multiple times in same race
if len(self.crews) != len(set(self.crews)):
- self.validated = False
+ self.verified = False
return False
# cannot have same athletes in different crews in same race
@@ -71,14 +71,14 @@ class Result:
allathletes.append(athlete)
if len(allathletes) != len(set(allathletes)):
- self.validated = False
+ self.verified = False
return False
- self.validated = True
- return self.validated
+ self.verified = True
+ return self.verified
def process(self):
- if not self.validated:
+ if not self.verified:
if not self.validate():
return False
diff --git a/boatmovers/templates/boatmovers.html b/boatmovers/templates/boatmovers.html
new file mode 100644
index 00000000..8337956e
--- /dev/null
+++ b/boatmovers/templates/boatmovers.html
@@ -0,0 +1,69 @@
+
+
+
+ | Rank |
+ Score |
+ Name | |
+ Club |
+ Gender |
+ Year of Birth |
+
+ {% for athlete in athletes %}
+
+ | {{ forloop.counter }} |
+ {{ athlete.trueskill_exposed|floatformat:2 }} |
+ {{ athlete.first_name }} |
+ {{ athlete.last_name }} |
+ {{ athlete.club }} |
+ {{ athlete.gender }} |
+ {{ athlete.birth_year }} |
+
+ {% endfor %}
+
+
+
+ This ranking was based on results from following races:
+
+
+
+ {% for race in races %}
+
+ | {{ race.date }} | {{ race.name }} |
+
+ View Race
+ |
+
+ {% endfor %}
+
+
+{% if user.is_authenticated and user.is_staff %}
+
+ Unprocessed races
+
+
+
+ {% for race in new_races %}
+
+ | {{ race.date }} | {{ race.name }} |
+
+ Manage Race
+ |
+
+ {% endfor %}
+
+
+
+ Add Athlete
+
+
+ Add Crew
+
+{% endif %}
+
+ Add Race
+
+{% if user.is_authenticated and user.is_staff %}
+
+ Add Result
+
+{% endif %}
diff --git a/boatmovers/templates/boatmovers/race_form.html b/boatmovers/templates/boatmovers/race_form.html
new file mode 100644
index 00000000..a9b32c5f
--- /dev/null
+++ b/boatmovers/templates/boatmovers/race_form.html
@@ -0,0 +1,4 @@
+
diff --git a/boatmovers/templates/boatmovers/result_form.html b/boatmovers/templates/boatmovers/result_form.html
new file mode 100644
index 00000000..a9b32c5f
--- /dev/null
+++ b/boatmovers/templates/boatmovers/result_form.html
@@ -0,0 +1,4 @@
+
diff --git a/boatmovers/templates/race.html b/boatmovers/templates/race.html
new file mode 100644
index 00000000..c26bcbff
--- /dev/null
+++ b/boatmovers/templates/race.html
@@ -0,0 +1,45 @@
+
+ {{ race.name }}
+
+
+ {{ race.date }}
+
+
+
+
+ | Order |
+ Crew | |
+
+ {% for result in results %}
+
+ | {{ result.order }} |
+ {{ result.crew.name }} |
+
+ {% endfor %}
+
+
+{% if user.is_authenticated and user.is_staff %}
+{% if race.verified %}
+
+ Race has been verified
+
+{% if race.processed %}
+
+ Race has been processed
+
+{% else %}
+
+ Race is not processed. Process Race
+
+{% endif %}
+{% else %}
+
+ Race is not verified. Verify Race
+
+{% endif %}
+{% if not race.verified and not race.processed %}
+
+ Add Result
+
+{% endif %}
+{% endif %}
diff --git a/boatmovers/urls.py b/boatmovers/urls.py
index 71b8da8e..0a849670 100644
--- a/boatmovers/urls.py
+++ b/boatmovers/urls.py
@@ -7,5 +7,10 @@ import boatmovers.views as views
urlpatterns = [
url(r'athlete/add/$',views.AthleteCreateView.as_view(),name='athlete_add'),
url(r'crew/add/$',views.CrewCreateView.as_view(),name='crew_add'),
+ url(r'race/add/$',views.RaceCreateView.as_view(),name='race_add'),
+ url(r'result/add/$',views.ResultCreateView.as_view(),name='result_add'),
+ url(r'race/(?P\d+)/$',views.race_view,name='race_view'),
+ url(r'race/(?P\d+)/verify/$',views.race_verify,name='race_verify'),
+ url(r'race/(?P\d+)/process/$',views.race_process,name='race_process'),
url(r'^$',views.boatmovers_view,name='boatmovers')
]
diff --git a/boatmovers/views.py b/boatmovers/views.py
index 04ab5de1..65ed0bea 100644
--- a/boatmovers/views.py
+++ b/boatmovers/views.py
@@ -1,9 +1,11 @@
from django.shortcuts import render
-from django.http import HttpResponse
+from django.http import HttpResponse, HttpResponseRedirect
+from django.shortcuts import get_object_or_404
+from django.urls import reverse
# Create your views here.
from django.views.generic.edit import CreateView
-from boatmovers.models import Athlete, Crew
+from boatmovers.models import Athlete, Crew, Race, Result
class AthleteCreateView(CreateView):
model = Athlete
@@ -25,5 +27,59 @@ class CrewCreateView(CreateView):
success_url = '/boatmovers/'
+class RaceCreateView(CreateView):
+ model = Race
+ fields = [
+ 'name',
+ 'resulturl',
+ 'date',
+ 'crew_size',
+ #'resultlist',
+ ]
+
+ success_url = '/boatmovers/'
+
+class ResultCreateView(CreateView):
+ model = Result
+ fields = [
+ 'crew',
+ 'race',
+ 'order'
+ ]
+
+ success_url = '/boatmovers/'
+
def boatmovers_view(request):
- return HttpResponse("1")
+ athletes = Athlete.objects.all().order_by('-trueskill_exposed','-birth_year','last_name','first_name')
+
+ races = Race.objects.filter(verified=True,processed=True).order_by('-date')
+ new_races = Race.objects.filter(processed=False).order_by('date')
+
+ return render(request,
+ 'boatmovers.html',
+ {'athletes':athletes,
+ 'races': races,
+ 'new_races': new_races}
+ )
+
+def race_view(request,id=0):
+ race = get_object_or_404(Race, pk=id)
+ results = race.results.all().order_by('order')
+
+ return render(request,
+ 'race.html',
+ {'race':race,
+ 'results':results}
+ )
+
+def race_verify(request, id=0):
+ race = get_object_or_404(Race, pk=id)
+ outcome = race.validate()
+
+ return HttpResponseRedirect(reverse('race_view',kwargs={'id':race.id}))
+
+def race_process(request, id=0):
+ race = get_object_or_404(Race, pk=id)
+ outcome = race.process()
+
+ return HttpResponseRedirect(reverse('race_view',kwargs={'id':race.id}))
From 13925f6e7f025a27fe79abe6a001b3334eedea26 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Fri, 24 Jun 2022 17:31:45 +0200
Subject: [PATCH 07/19] it is working
---
boatmovers/templates/boatmovers.html | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/boatmovers/templates/boatmovers.html b/boatmovers/templates/boatmovers.html
index 8337956e..aa3f539b 100644
--- a/boatmovers/templates/boatmovers.html
+++ b/boatmovers/templates/boatmovers.html
@@ -1,3 +1,6 @@
+
+ Boat Movers Ranking
+
@@ -6,7 +9,6 @@
| Name | |
Club |
Gender |
- Year of Birth |
{% for athlete in athletes %}
@@ -16,11 +18,15 @@
| {{ athlete.last_name }} |
{{ athlete.club }} |
{{ athlete.gender }} |
- {{ athlete.birth_year }} |
{% endfor %}
+
+ This page is an experimental ranking based on public race results, mainly from Dutch Masters
+ rowing events. If your name shows up and you do not agree with that, contact us at info@rowsandall.com
+ and we'll remove your name.
+
This ranking was based on results from following races:
From 0b88f3c8613bed1e1c7cc5f0682a88e7b4321cbc Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Sat, 25 Jun 2022 14:16:17 +0200
Subject: [PATCH 08/19] small improvements
---
boatmovers/templates/boatmovers.html | 21 ++++++++++++++++++---
boatmovers/templates/crew.html | 19 +++++++++++++++++++
boatmovers/templates/race.html | 2 +-
boatmovers/urls.py | 1 +
boatmovers/views.py | 11 +++++++++++
5 files changed, 50 insertions(+), 4 deletions(-)
create mode 100644 boatmovers/templates/crew.html
diff --git a/boatmovers/templates/boatmovers.html b/boatmovers/templates/boatmovers.html
index aa3f539b..5b133e25 100644
--- a/boatmovers/templates/boatmovers.html
+++ b/boatmovers/templates/boatmovers.html
@@ -6,7 +6,7 @@
| Rank |
Score |
- Name | |
+ Name | |
Club |
Gender |
@@ -23,10 +23,25 @@
- This page is an experimental ranking based on public race results, mainly from Dutch Masters
- rowing events. If your name shows up and you do not agree with that, contact us at info@rowsandall.com
+ This page is an experimental ranking based on public race results,
+ mainly from Dutch Masters
+ rowing events. It is inspired by Rowing Stats.
+
+
+ The best way to climb the ranking is to win races against crews with people who are higher
+ in the ranking (unexpected win).
+
+
+ If your name shows up and you do not agree with that, contact us at info@rowsandall.com
and we'll remove your name.
+
+ If you'd like us to include a recent race result, use the "Add Race" link below. A race
+ is a single start (during a regatta).
+
+
+ You can also contact us at info@rowsandall.com.
+
This ranking was based on results from following races:
diff --git a/boatmovers/templates/crew.html b/boatmovers/templates/crew.html
new file mode 100644
index 00000000..56d33232
--- /dev/null
+++ b/boatmovers/templates/crew.html
@@ -0,0 +1,19 @@
+
+ {{ crew.name }}
+
+
+
+
+ | Athlete |
+ |
+ Score |
+
+ {% for athlete in athletes %}
+
+ | {{ athlete.first_name }} |
+ {{ athlete.last_name }} |
+ {{ athlete.trueskill_exposed|floatformat:2 }} |
+
+ {% endfor %}
+
+
diff --git a/boatmovers/templates/race.html b/boatmovers/templates/race.html
index c26bcbff..347aed79 100644
--- a/boatmovers/templates/race.html
+++ b/boatmovers/templates/race.html
@@ -13,7 +13,7 @@
{% for result in results %}
| {{ result.order }} |
- {{ result.crew.name }} |
+ {{ result.crew.name }} |
{% endfor %}
diff --git a/boatmovers/urls.py b/boatmovers/urls.py
index 0a849670..1ce9ca38 100644
--- a/boatmovers/urls.py
+++ b/boatmovers/urls.py
@@ -12,5 +12,6 @@ urlpatterns = [
url(r'race/(?P\d+)/$',views.race_view,name='race_view'),
url(r'race/(?P\d+)/verify/$',views.race_verify,name='race_verify'),
url(r'race/(?P\d+)/process/$',views.race_process,name='race_process'),
+ url(r'crew/(?P\d+)/$',views.crew_view,name='crew_view'),
url(r'^$',views.boatmovers_view,name='boatmovers')
]
diff --git a/boatmovers/views.py b/boatmovers/views.py
index 65ed0bea..16d1960a 100644
--- a/boatmovers/views.py
+++ b/boatmovers/views.py
@@ -83,3 +83,14 @@ def race_process(request, id=0):
outcome = race.process()
return HttpResponseRedirect(reverse('race_view',kwargs={'id':race.id}))
+
+def crew_view(request, id=0):
+ crew = get_object_or_404(Crew, pk=id)
+ athletes = crew.athletes.all().order_by("-trueskill_exposed")
+
+ return render(request,
+ 'crew.html',
+ {
+ 'crew':crew,
+ 'athletes':athletes
+ })
From 44d3dfc919646e2313cc595f306d9c79da2b3900 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Sat, 25 Jun 2022 16:07:11 +0200
Subject: [PATCH 09/19] time team scraping works
---
.../migrations/0012_auto_20220625_1328.py | 33 ++++++++
.../migrations/0013_alter_crew_athletes.py | 18 +++++
boatmovers/models.py | 13 +--
boatmovers/scrapers.py | 76 ++++++++++++++++++
boatmovers/templates/boatmovers.html | 3 +
boatmovers/templates/race.html | 5 ++
boatmovers/views.py | 32 +++++++-
db.sqlite3-journal | Bin 0 -> 12824 bytes
8 files changed, 172 insertions(+), 8 deletions(-)
create mode 100644 boatmovers/migrations/0012_auto_20220625_1328.py
create mode 100644 boatmovers/migrations/0013_alter_crew_athletes.py
create mode 100644 boatmovers/scrapers.py
create mode 100644 db.sqlite3-journal
diff --git a/boatmovers/migrations/0012_auto_20220625_1328.py b/boatmovers/migrations/0012_auto_20220625_1328.py
new file mode 100644
index 00000000..9a0b5552
--- /dev/null
+++ b/boatmovers/migrations/0012_auto_20220625_1328.py
@@ -0,0 +1,33 @@
+# Generated by Django 3.2.12 on 2022-06-25 13:28
+
+import boatmovers.models
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('boatmovers', '0011_alter_race_processed'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='crew',
+ name='athletes',
+ field=models.ManyToManyField(related_name='crews', to='boatmovers.Athlete'),
+ ),
+ migrations.AlterField(
+ model_name='race',
+ name='date',
+ field=models.DateField(default=boatmovers.models.current_day, verbose_name='Race Date'),
+ ),
+ migrations.AlterField(
+ model_name='race',
+ name='resulturl',
+ field=models.URLField(null=True, verbose_name='URL Link to results'),
+ ),
+ migrations.AlterUniqueTogether(
+ name='result',
+ unique_together={('crew', 'order')},
+ ),
+ ]
diff --git a/boatmovers/migrations/0013_alter_crew_athletes.py b/boatmovers/migrations/0013_alter_crew_athletes.py
new file mode 100644
index 00000000..8f9634c4
--- /dev/null
+++ b/boatmovers/migrations/0013_alter_crew_athletes.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.12 on 2022-06-25 13:31
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('boatmovers', '0012_auto_20220625_1328'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='crew',
+ name='athletes',
+ field=models.ManyToManyField(related_name='athlete_crews', to='boatmovers.Athlete'),
+ ),
+ ]
diff --git a/boatmovers/models.py b/boatmovers/models.py
index b2664c4b..d930eab3 100644
--- a/boatmovers/models.py
+++ b/boatmovers/models.py
@@ -2,6 +2,8 @@ from django.db import models
from django import forms
from django.core.exceptions import ValidationError
+import collections
+
import datetime
from django.utils import timezone
import trueskill
@@ -43,7 +45,7 @@ class athleteForm(forms.ModelForm):
fields = ['first_name','last_name','club','birth_year']
class Crew(models.Model):
- athletes = models.ManyToManyField(Athlete)
+ athletes = models.ManyToManyField(Athlete, related_name='athlete_crews')
name = models.CharField(max_length=200)
def __str__(self):
@@ -90,10 +92,10 @@ class Race(models.Model):
"Cannot have the same crew more than one time in a race"
)
- if len(athletes) != len(set(athletes)):
- raise ValidationError(
- "Cannot have the same athlete in different crews in a race"
- )
+ #if len(athletes) != len(set(athletes)):
+ # raise ValidationError(
+ # "Cannot have the same athlete in different crews in a race"
+ # )
super(Race, self).save(*args, **kwargs)
@@ -208,6 +210,7 @@ class Result(models.Model):
"Cannot have the same crew more than one time in a race"
)
if len(athletes) != len(set(athletes)):
+ print([item for item, count in collections.Counter(athletes).items() if count>1])
raise ValidationError(
"Cannot have the same athlete in different crews in a race"
)
diff --git a/boatmovers/scrapers.py b/boatmovers/scrapers.py
new file mode 100644
index 00000000..f4f9c658
--- /dev/null
+++ b/boatmovers/scrapers.py
@@ -0,0 +1,76 @@
+import re
+from bs4 import BeautifulSoup
+import requests
+from boatmovers.models import *
+import pandas as pd
+
+url_heineken = ''
+
+def time_team_scraper(url,raceid):
+ race = Race.objects.get(id=raceid)
+ nr = race.crew_size
+ r = requests.get(url)
+ soup = BeautifulSoup(r.content,features='lxml')
+ tbl = soup.find('table')
+ order = 1
+
+ str = re.search('(.*)results(.*)',url)
+ base = str.groups()[0]
+
+ for tr in tbl.findAll("tr"):
+ trs = tr.findAll("td")
+ for each in trs:
+ try:
+ link = each.find('a')['href']
+ name = each.find('a').contents[0]
+ except (TypeError, IndexError):
+ link = ''
+ name =''
+
+ if 'entry' in link:
+ print(order, name)
+
+ dfs = pd.read_html(base+link[3:])
+ df = dfs[0]
+ namen = df['naam']
+
+ crew = Crew(name=name)
+ crew.save()
+ for i in range(nr):
+ try:
+ names = df['naam'][i].split(' ')
+ first_name = ' '.join(names[:-1])
+ last_name = names[-1]
+ except AttributeError:
+ try:
+ first_name = str(df['naam'][i])
+ last_name = ''
+ except TypeError:
+ first_name = 'Unknown'
+ last_name = 'Athlete'
+ athletes = Athlete.objects.filter(first_name = first_name,
+ last_name = last_name)
+ if len(athletes) >= 1:
+ athlete = athletes[0]
+ else:
+ athlete = Athlete(first_name=first_name,
+ last_name=last_name,
+ club = name)
+ athlete.save()
+ print(athlete)
+
+ crew.athletes.add(athlete)
+
+ result = Result(
+ crew = crew,
+ race = race,
+ order = order
+ )
+ try:
+ result.save()
+ except ValidationError as e:
+ print(e)
+
+ order += 1
+
+ print('')
diff --git a/boatmovers/templates/boatmovers.html b/boatmovers/templates/boatmovers.html
index 5b133e25..87db2bb2 100644
--- a/boatmovers/templates/boatmovers.html
+++ b/boatmovers/templates/boatmovers.html
@@ -18,6 +18,9 @@
{{ athlete.last_name }} |
{{ athlete.club }} |
{{ athlete.gender }} |
+ {% if user.is_authenticated and user.is_staff %}
+ edit |
+ {% endif %}
{% endfor %}
diff --git a/boatmovers/templates/race.html b/boatmovers/templates/race.html
index 347aed79..8f602c69 100644
--- a/boatmovers/templates/race.html
+++ b/boatmovers/templates/race.html
@@ -14,6 +14,11 @@
| {{ result.order }} |
{{ result.crew.name }} |
+ {% if result.crew.id in duplicate_crews %}
+ ! |
+ {% elif result.crew.id in duplicate_athletes_crews %}
+ ! |
+ {% endif %}
{% endfor %}
diff --git a/boatmovers/views.py b/boatmovers/views.py
index 16d1960a..94f3cb0b 100644
--- a/boatmovers/views.py
+++ b/boatmovers/views.py
@@ -3,6 +3,8 @@ from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.urls import reverse
+import collections
+
# Create your views here.
from django.views.generic.edit import CreateView
from boatmovers.models import Athlete, Crew, Race, Result
@@ -50,7 +52,7 @@ class ResultCreateView(CreateView):
success_url = '/boatmovers/'
def boatmovers_view(request):
- athletes = Athlete.objects.all().order_by('-trueskill_exposed','-birth_year','last_name','first_name')
+ athletes = Athlete.objects.filter(trueskill_exposed__gt=0).order_by('-trueskill_exposed','-birth_year','last_name','first_name')
races = Race.objects.filter(verified=True,processed=True).order_by('-date')
new_races = Race.objects.filter(processed=False).order_by('date')
@@ -66,10 +68,34 @@ def race_view(request,id=0):
race = get_object_or_404(Race, pk=id)
results = race.results.all().order_by('order')
+ crews = []
+ athletes = []
+
+ for result in results:
+ crews.append(result.crew.id)
+ for athlete in result.crew.athletes.all():
+ athletes.append(athlete.id)
+
+ # duplicates
+ duplicate_athletes = [item for item, count in collections.Counter(athletes).items() if count>1]
+ duplicate_crews = [item for item, count in collections.Counter(crews).items() if count>1]
+ duplicate_athletes_crews = []
+ for athlete_id in duplicate_athletes:
+ athlete = Athlete.objects.get(id=athlete_id)
+ crews = [crew.id for crew in athlete.athlete_crews.all()]
+ for crew in crews:
+ duplicate_athletes_crews.append(crew)
+
+
return render(request,
'race.html',
- {'race':race,
- 'results':results}
+ {
+ 'race':race,
+ 'results':results,
+ 'duplicate_athletes':duplicate_athletes,
+ 'duplicate_crews':duplicate_crews,
+ 'duplicate_athletes_crews':duplicate_athletes_crews
+ }
)
def race_verify(request, id=0):
diff --git a/db.sqlite3-journal b/db.sqlite3-journal
new file mode 100644
index 0000000000000000000000000000000000000000..18977d1d7cf8f4540a475472617c8437cc685ebb
GIT binary patch
literal 12824
zcmeHOdvILUdB6KO+P5yYv|g<@i&nUbW57+ZVQeKBODox0R=bvvgba2PINCkdUg_?=
z^4+_Zt+oUk+7PZoJ)wD!Fo}n03$YV7nY!df2pK1C>xS^iOrT6d>6C<&hLq64(3C)b
z=bXEe1#+?fY-cs&)%x7?edqgr-}8LCQk2D?y=PuA6vg+ZqIj`*(c**VyZ^@sc*!+~p~6Vao=H={p`L|QYEqro2szZ*Oj{FHxRupHbG
z+!&1euJQiX_gnwrzypC#1m*%C_I@X@DR4<3((-c44_i*Qe75DFZ^HM5@P~p*%Lm9j
zd5gS6o+hWsUy{%G-}GuEM}E)qglArTQGHtduKMSy3t&b
zi_kjXzl2u!Rt8`2{NQ4;HtqH1O=@I{)Y8}#t7Yr8y>({S0w+Cpb&&2h@wimcs+r+h
zsj`n6fs^Fvb`no{y+d`w%$b!cHTYsYLE6@My+yje-=fty%_z+<9qa9@NW7D;TlTPR
zGo!+^DwZ!=2@0`Xx{(?T=aJS9(wPKXORL!$rN#)eHJjnVr74o`;(KkoqS0EPQMQ;l
zSDQJ2XYWmt?zq=mV5X6QbeS@<3ZTW4i&v2p*cEBr(n>66)+ZTXeoum=vAjbonVeuJ
z)h)&kNhV2(%c((GrspZOYWtX8#*>yd66bQ6%ou`d%)*-QA`%BSoJ-c^!h7Q+4LOQT
zGa!OJq%*GNO^ULLB!F>IvrCmhW>Hq=*pgAnGjCesTyq&&)8cmdeTfK1bW~%;
z4Bx#sNjl+ZKt!+c?PE4$hQ^;%<0OG6Li{09pMeu%wUQ)h4z_TV>DmP3XT}u8lc_jK
z33n6L9WrMHvSq0eoM#Ulc0#L3Hj^o`R&2H_Y%T*+Y6csr8^RZFjFY&CnToNC=@rwe
zahQM6MiQV9;*8B|Tvh+`?vc`=M)W%Od;d=Z4=XK-vVz39*P3OmNCk(>J4izKxHV&D
z+5DtM%UX#`ez)sD)M7IuX4#@8;rDl~Cfzu3NT;-xF=yfT2GlKcPyU#sDAY@|mbG9I
zTAju6?FrJ!Db5ZrZ1?=8ldOYALvSTwl2JGbe9E$QYQX(H-koRCN-?28*COnGuO_uArj#GW7(&RF1baR5Msg;vP_kFwJ
z;s}*2c*{iS?@o~}?jdzu%ZyN+*0<}X#f*8b#vKWg6wjzprF}Xm%H}*!7+ym*io#th)`*aoX5xvC=Nb;;=OngyX~AuJ+2p41A8aRW!dKx2
zCbMb+nU_|OHt2-CePt%F{oI1)Tv3D?G(VCgUE(my(rm7Hff)va8~I*o1b}4>nDx1u
zZE>U?SWP;`QSdIY9XY9D)_H7fXoM;r4e4fe_SBc4&G$lEm6c1|lLSct1Fkkq26vnl
z(dh4$nMx#q0hB0XM)8
zi=e+BuEk4Z-mDm7bU)K4QKS4fEG`x(vZlph+1aQ76=Tq%6^i8G`P0RQ$IGhk(Ul}26or=8=J)Ku&YL8FJ4}loG0H1|$lJdo4Ilu_qg2S%W1%|~
zqFhS)Vdf$Q0Yei2FPUK$Dt7}ptH|oeq2QjC35w_E8j6r*FxPwzsngnxX5B!9`aK;a1!od9lUF<>ec=keTUL=|!$pj7
zX6Yyt$ZRKMF)V86IQlHBZfjsN;Wijp95-znPU;Uzc=^6Tkv6cFm+s8hwwo3z7&orJ
zRW<|pQx9Ru$m-Odcl(yF%fOJ4!VQAV1-Kx^mr^9f8z7nQhf$cBRiPk}3KjDFv)irc@mfK3KUG(}sQUAGBb}2I1piL~WDl#_@g)3dV0F?nY
z0|&&~-ENVQ>br4l6{&Q_Pc1F57SPAy2rm
zTEx~YvYajQz$c}f3n;UQccfY2d!Ek&iPa?84SkVX*qm$&GHzeczLF%-5Ax)7z!*1?
zC_M`u7K}2$GTbPc4UpwWZW|@@+@Og@4=&>Wqeh2a9+>r3vCZNY!uNsVKmQc(oZ>KrbCl`y2-fzKHfT`v@JWWCVud6NZ;4ULt3Zk2X6(({F`8&iM`k5k{
zcOXADi#8{4@~VbyVXK9XgFMz)6&6QZ!~0;r-l!{L6+t_P#j9jKD%6FoxlwDf&-Oe4
zrI(C6mU!2gRz+(Mv;MSETqRcvY()qBlq`D%wttlJc0dMSqJyN7XB(F)I0qHC1JC1)
zn5M>r*|;+N6^D8a@;LUpfokxEgJ<|}CP~{`@#K1*8;nVF3O6g>4<2uvVHmvnnAYxIUEc9MtNV$t-fHNdPcoFNYveG
zruFB6zi+*-b$9E^z#qpRjeRWE8+{|tAAKZxD7ro1jYcD9B6miLEvF+Z!#@t+-EwPq
zINTOG6Z(8e5A}tj!KX1V_=C5(Q}e$~1eypm5ojXNL|_R5{mzYHWldLCz#9t$Mlmc}
zzf;5DsXC~m<3>$2YP)t#WJb}TF{5{L@8e(HJ%tQD%#^*
zA662{2A68d+(FBj!kkSz*fVp_bA6zF?&|4-zy9RSp#9s<(&{bOI3r;txu#P{Fot;n
zvxep<@1zY%?VXhB?=NCb)Vuj;$MKWpA{hMJ{bzP<3}$*ePwd}!+qb^m>lDJu`ZmcR
zi-{DUzc!lg5n4MB7FlNyGNj%wWEiiY!K;n)7Kj<66Pa<`7BxN^7)R@3^=|&ji517L
z^g)hakKF$j2_EU~{PHu2`)O~pKK?HFzi|2yqw=W0OTDQWv~Tp1k?
z?)kVYFCoQn$~|_raqMMIDXg@0c6q$9U|`&=4zDfJifOO|qv(@)yP4UL44mxE9OFO7
zFLNewP)hE`cpD=ebnO`4F1z~*hr+Mi-Fesp!tlGnm`*XyvX-UU;M^Qmx?FksD~(wn
z_U@T6(X}s2^gib%h!vM&ZDTq*ZaPz2cI)NNN5V>{yETv7GA0FOmO}@3j_n@~E2*U9
zj9!^fc4SYw?DqA}hhYA++&+LAj$R(Y}>>MpR-FqD14B^E~7bzt9+UF=w}C{2dYJ6%eRmz|xs&ht^yyOCby^g{5sTUG1YB!Za_h2D+sO6M9J
z>C#PTCELUxnZ0W@-RNxLg-9NUkD%(caeTJ72T$DuNB|>YaG?hSdL7
zUsGRJpHxq)kKmgCC)E4YXVo9#TLBNKT{3?^RE#pH`2kcdECmx15u2^Fb4VCIU?a
zng}!zXd=)=pou^efhGb?1eypm5%|A`0KU(sKFhz|ip%&thbws9co^S+_H-V8FJ9A!
z!+3DX$3KYoN#|y~zw6L2-iHpy@w(FCcjOxmb>a2;Ln>AhP7d!kALQ%yp^bR`qSJ%*
bl!L$a@N_sgV5R$D0k4TXUg8(?zXSOnyG0?u
literal 0
HcmV?d00001
From 53679a1ba3beeaca84df6eecd41314a65a5277db Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Mon, 27 Jun 2022 21:28:49 +0200
Subject: [PATCH 10/19] first attempt to read csv - needs improvement
---
boatmovers/models.py | 12 +++++++
boatmovers/scrapers.py | 51 +++++++++++++++++++++++++++
boatmovers/templates/boatmovers.html | 17 +++++++++
db.sqlite3-journal | Bin 12824 -> 0 bytes
4 files changed, 80 insertions(+)
delete mode 100644 db.sqlite3-journal
diff --git a/boatmovers/models.py b/boatmovers/models.py
index d930eab3..616ee1ef 100644
--- a/boatmovers/models.py
+++ b/boatmovers/models.py
@@ -8,6 +8,8 @@ import datetime
from django.utils import timezone
import trueskill
+from rowers.utils import dologging
+
def current_day(ttz=None):
if ttz is None:
return (datetime.datetime.now(tz=timezone.utc)).date()
@@ -169,6 +171,16 @@ class Race(models.Model):
athlete.trueskill_mu = rating.mu
athlete.trueskill_sigma = rating.sigma
athlete.save()
+ u = 'Rating athlete {id} {f} {l} mu = {mu} sigma = {sigma} race {rid} {rname}'.format(
+ id = id,
+ f = athlete.first_name,
+ l = athlete.last_name,
+ mu = rating.mu,
+ sigma = rating.sigma,
+ rid = self.id,
+ rname = self.name,
+ )
+ dologging('ratings.log',u)
self.processed = True
self.save()
diff --git a/boatmovers/scrapers.py b/boatmovers/scrapers.py
index f4f9c658..cea9dc53 100644
--- a/boatmovers/scrapers.py
+++ b/boatmovers/scrapers.py
@@ -6,6 +6,57 @@ import pandas as pd
url_heineken = ''
+
+def csv_reader(filename,raceid,clubcol='Ploeg',bankjes=['Slag'],uitslag='Pos'):
+ race = Race.objects.get(id=raceid)
+ nr = race.crew_size
+
+ df = pd.read_csv(filename)
+ # replace column names if different
+
+ for row in df.itertuples():
+ order = row.Pos
+ crewname = row.Ploeg
+ crew = Crew(name=crewname)
+ crew.save()
+
+ for i in range(nr):
+ # need to improve for multiple rowers
+ try:
+ naam = row.Slag.split(' ')
+ first_name = ' '.join(naam[:-1])
+ last_name = naam[-1]
+ except AttributeError:
+ try:
+ first_name = str(row.Slag)
+ last_name = ''
+ except TypeError:
+ first_name = 'Unknown'
+ last_name = 'Athlete'
+ athletes = Athlete.objects.filter(first_name = first_name,
+ last_name = last_name)
+ if len(athletes) >= 1:
+ athlete = athletes[0]
+ else:
+ athlete = Athlete(first_name=first_name,
+ last_name=last_name,
+ club = crewname)
+ athlete.save()
+ print(athlete)
+
+ crew.athletes.add(athlete)
+
+ result = Result(
+ crew = crew,
+ race = race,
+ order = order
+ )
+ try:
+ result.save()
+ except ValidationError as e:
+ print(e)
+
+
def time_team_scraper(url,raceid):
race = Race.objects.get(id=raceid)
nr = race.crew_size
diff --git a/boatmovers/templates/boatmovers.html b/boatmovers/templates/boatmovers.html
index 87db2bb2..f8ab7d67 100644
--- a/boatmovers/templates/boatmovers.html
+++ b/boatmovers/templates/boatmovers.html
@@ -1,6 +1,20 @@
+
Boat Movers Ranking
+
+
@@ -25,6 +39,8 @@
{% endfor %}
+
+
This page is an experimental ranking based on public race results,
mainly from Dutch Masters
@@ -91,3 +107,4 @@
Add Result
{% endif %}
+
diff --git a/db.sqlite3-journal b/db.sqlite3-journal
deleted file mode 100644
index 18977d1d7cf8f4540a475472617c8437cc685ebb..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 12824
zcmeHOdvILUdB6KO+P5yYv|g<@i&nUbW57+ZVQeKBODox0R=bvvgba2PINCkdUg_?=
z^4+_Zt+oUk+7PZoJ)wD!Fo}n03$YV7nY!df2pK1C>xS^iOrT6d>6C<&hLq64(3C)b
z=bXEe1#+?fY-cs&)%x7?edqgr-}8LCQk2D?y=PuA6vg+ZqIj`*(c**VyZ^@sc*
!+~p~6Vao=H={p`L|QYEqro2szZ*Oj{FHxRupHbG
z+!&1euJQiX_gnwrzypC#1m*%C_I@X@DR4<3((-c44_i*Qe75DFZ^HM5@P~p*%Lm9j
zd5gS6o+hWsUy{%G-}GuEM}E)qglArTQGHtduKMSy3t&b
zi_kjXzl2u!Rt8`2{NQ4;HtqH1O=@I{)Y8}#t7Yr8y>({S0w+Cpb&&2h@wimcs+r+h
zsj`n6fs^Fvb`no{y+d`w%$b!cHTYsYLE6@My+yje-=fty%_z+<9qa9@NW7D;TlTPR
zGo!+^DwZ!=2@0`Xx{(?T=aJS9(wPKXORL!$rN#)eHJjnVr74o`;(KkoqS0EPQMQ;l
zSDQJ2XYWmt?zq=mV5X6QbeS@<3ZTW4i&v2p*cEBr(n>66)+ZTXeoum=vAjbonVeuJ
z)h)&kNhV2(%c((GrspZOYWtX8#*>yd66bQ6%ou`d%)*-QA`%BSoJ-c^!h7Q+4LOQT
zGa!OJq%*GNO^ULLB!F>IvrCmhW>Hq=*pgAnGjCesTyq&&)8cmdeTfK1bW~%;
z4Bx#sNjl+ZKt!+c?PE4$hQ^;%<0OG6Li{09pMeu%wUQ)h4z_TV>DmP3XT}u8lc_jK
z33n6L9WrMHvSq0eoM#Ulc0#L3Hj^o`R&2H_Y%T*+Y6csr8^RZFjFY&CnToNC=@rwe
zahQM6MiQV9;*8B|Tvh+`?vc`=M)W%Od;d=Z4=XK-vVz39*P3OmNCk(>J4izKxHV&D
z+5DtM%UX#`ez)sD)M7IuX4#@8;rDl~Cfzu3NT;-xF=yfT2GlKcPyU#sDAY@|mbG9I
zTAju6?FrJ!Db5ZrZ1?=8ldOYALvSTwl2JGbe9E$QYQX(H-koRCN-?28*COnGuO_uArj#GW7(&RF1baR5Msg;vP_kFwJ
z;s}*2c*{iS?@o~}?jdzu%ZyN+*0<}X#f*8b#vKWg6wjzprF}Xm%H}*!7+ym*io#th)`*aoX5xvC=Nb;;=OngyX~AuJ+2p41A8aRW!dKx2
zCbMb+nU_|OHt2-CePt%F{oI1)Tv3D?G(VCgUE(my(rm7Hff)va8~I*o1b}4>nDx1u
zZE>U?SWP;`QSdIY9XY9D)_H7fXoM;r4e4fe_SBc4&G$lEm6c1|lLSct1Fkkq26vnl
z(dh4$nMx#q0hB0XM)8
zi=e+BuEk4Z-mDm7bU)K4QKS4fEG`x(vZlph+1aQ76=Tq%6^i8G`P0RQ$IGhk(Ul}26or=8=J)Ku&YL8FJ4}loG0H1|$lJdo4Ilu_qg2S%W1%|~
zqFhS)Vdf$Q0Yei2FPUK$Dt7}ptH|oeq2QjC35w_E8j6r*FxPwzsngnxX5B!9`aK;a1!od9lUF<>ec=keTUL=|!$pj7
zX6Yyt$ZRKMF)V86IQlHBZfjsN;Wijp95-znPU;Uzc=^6Tkv6cFm+s8hwwo3z7&orJ
zRW<|pQx9Ru$m-Odcl(yF%fOJ4!VQAV1-Kx^mr^9f8z7nQhf$cBRiPk}3KjDFv)irc@mfK3KUG(}sQUAGBb}2I1piL~WDl#_@g)3dV0F?nY
z0|&&~-ENVQ>br4l6{&Q_Pc1F57SPAy2rm
zTEx~YvYajQz$c}f3n;UQccfY2d!Ek&iPa?84SkVX*qm$&GHzeczLF%-5Ax)7z!*1?
zC_M`u7K}2$GTbPc4UpwWZW|@@+@Og@4=&>Wqeh2a9+>r3vCZNY!uNsVKmQc(oZ>KrbCl`y2-fzKHfT`v@JWWCVud6NZ;4ULt3Zk2X6(({F`8&iM`k5k{
zcOXADi#8{4@~VbyVXK9XgFMz)6&6QZ!~0;r-l!{L6+t_P#j9jKD%6FoxlwDf&-Oe4
zrI(C6mU!2gRz+(Mv;MSETqRcvY()qBlq`D%wttlJc0dMSqJyN7XB(F)I0qHC1JC1)
zn5M>r*|;+N6^D8a@;LUpfokxEgJ<|}CP~{`@#K1*8;nVF3O6g>4<2uvVHmvnnAYxIUEc9MtNV$t-fHNdPcoFNYveG
zruFB6zi+*-b$9E^z#qpRjeRWE8+{|tAAKZxD7ro1jYcD9B6miLEvF+Z!#@t+-EwPq
zINTOG6Z(8e5A}tj!KX1V_=C5(Q}e$~1eypm5ojXNL|_R5{mzYHWldLCz#9t$Mlmc}
zzf;5DsXC~m<3>$2YP)t#WJb}TF{5{L@8e(HJ%tQD%#^*
zA662{2A68d+(FBj!kkSz*fVp_bA6zF?&|4-zy9RSp#9s<(&{bOI3r;txu#P{Fot;n
zvxep<@1zY%?VXhB?=NCb)Vuj;$MKWpA{hMJ{bzP<3}$*ePwd}!+qb^m>lDJu`ZmcR
zi-{DUzc!lg5n4MB7FlNyGNj%wWEiiY!K;n)7Kj<66Pa<`7BxN^7)R@3^=|&ji517L
z^g)hakKF$j2_EU~{PHu2`)O~pKK?HFzi|2yqw=W0OTDQWv~Tp1k?
z?)kVYFCoQn$~|_raqMMIDXg@0c6q$9U|`&=4zDfJifOO|qv(@)yP4UL44mxE9OFO7
zFLNewP)hE`cpD=ebnO`4F1z~*hr+Mi-Fesp!tlGnm`*XyvX-UU;M^Qmx?FksD~(wn
z_U@T6(X}s2^gib%h!vM&ZDTq*ZaPz2cI)NNN5V>{yETv7GA0FOmO}@3j_n@~E2*U9
zj9!^fc4SYw?DqA}hhYA++&+LAj$R(Y}>>MpR-FqD14B^E~7bzt9+UF=w}C{2dYJ6%eRmz|xs&ht^yyOCby^g{5sTUG1YB!Za_h2D+sO6M9J
z>C#PTCELUxnZ0W@-RNxLg-9NUkD%(caeTJ72T$DuNB|>YaG?hSdL7
zUsGRJpHxq)kKmgCC)E4YXVo9#TLBNKT{3?^RE#pH`2kcdECmx15u2^Fb4VCIU?a
zng}!zXd=)=pou^efhGb?1eypm5%|A`0KU(sKFhz|ip%&thbws9co^S+_H-V8FJ9A!
z!+3DX$3KYoN#|y~zw6L2-iHpy@w(FCcjOxmb>a2;Ln>AhP7d!kALQ%yp^bR`qSJ%*
bl!L$a@N_sgV5R$D0k4TXUg8(?zXSOnyG0?u
From 22f3708120a4e2207f2d3aff6a88f9d5fa56fcce Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Wed, 29 Jun 2022 14:00:57 +0200
Subject: [PATCH 11/19] updating scrapers
---
boatmovers/scrapers.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/boatmovers/scrapers.py b/boatmovers/scrapers.py
index cea9dc53..9033d1cb 100644
--- a/boatmovers/scrapers.py
+++ b/boatmovers/scrapers.py
@@ -23,7 +23,10 @@ def csv_reader(filename,raceid,clubcol='Ploeg',bankjes=['Slag'],uitslag='Pos'):
for i in range(nr):
# need to improve for multiple rowers
try:
- naam = row.Slag.split(' ')
+ print(row)
+ naam = row[df.columns.get_loc('Slag')+1].split(' ')
+ #print(naam)
+ #naam = row.Slag.split(' ')
first_name = ' '.join(naam[:-1])
last_name = naam[-1]
except AttributeError:
From a47ae2bc5b8d547b20236e5a7811c130c6cd76a0 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Wed, 29 Jun 2022 16:17:37 +0200
Subject: [PATCH 12/19] adding link to Home, delayed tasks working
---
boatmovers/scrapers.py | 10 ++----
boatmovers/tasks.py | 23 +++++++++++++
boatmovers/templates/boatmovers.html | 5 +++
.../templates/boatmovers/athlete_form.html | 3 ++
.../templates/boatmovers/race_form.html | 3 ++
.../templates/boatmovers/result_form.html | 3 ++
boatmovers/templates/boatmovers_base.html | 33 +++++++++++++++++++
boatmovers/templates/crew.html | 3 ++
boatmovers/templates/race.html | 4 +++
boatmovers/views.py | 8 ++++-
10 files changed, 87 insertions(+), 8 deletions(-)
create mode 100644 boatmovers/tasks.py
create mode 100644 boatmovers/templates/boatmovers_base.html
diff --git a/boatmovers/scrapers.py b/boatmovers/scrapers.py
index 9033d1cb..8e00011c 100644
--- a/boatmovers/scrapers.py
+++ b/boatmovers/scrapers.py
@@ -15,18 +15,14 @@ def csv_reader(filename,raceid,clubcol='Ploeg',bankjes=['Slag'],uitslag='Pos'):
# replace column names if different
for row in df.itertuples():
- order = row.Pos
- crewname = row.Ploeg
+ order = row[df.columns.get_loc(uitslag)+1]
+ crewname = row[df.columns.get_loc(clubcol)+1]
crew = Crew(name=crewname)
crew.save()
for i in range(nr):
- # need to improve for multiple rowers
try:
- print(row)
- naam = row[df.columns.get_loc('Slag')+1].split(' ')
- #print(naam)
- #naam = row.Slag.split(' ')
+ naam = row[df.columns.get_loc(bankjes[i])+1].split(' ')
first_name = ' '.join(naam[:-1])
last_name = naam[-1]
except AttributeError:
diff --git a/boatmovers/tasks.py b/boatmovers/tasks.py
new file mode 100644
index 00000000..d45d7d4d
--- /dev/null
+++ b/boatmovers/tasks.py
@@ -0,0 +1,23 @@
+import os
+os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"
+from YamJam import yamjam
+CFG = yamjam()['rowsandallapp']
+
+try:
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE",CFG['settings_name'])
+except KeyError:
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE","rowsandall_app.settings")
+
+from django.core.wsgi import get_wsgi_application
+application = get_wsgi_application()
+
+from boatmovers.models import Race
+from rq import get_current_job
+from django_rq import job
+
+@job
+def race_process(id):
+ job = get_current_job()
+
+ race = Race.objects.get(id=id)
+ return race.process()
diff --git a/boatmovers/templates/boatmovers.html b/boatmovers/templates/boatmovers.html
index f8ab7d67..0a08e1db 100644
--- a/boatmovers/templates/boatmovers.html
+++ b/boatmovers/templates/boatmovers.html
@@ -1,3 +1,5 @@
+{% extends "boatmovers_base.html" %}
+{% block main %}
+
+
Boat Movers Ranking
@@ -108,3 +112,4 @@
{% endif %}
+{% endblock %}
diff --git a/boatmovers/templates/boatmovers/athlete_form.html b/boatmovers/templates/boatmovers/athlete_form.html
index a9b32c5f..da989c98 100644
--- a/boatmovers/templates/boatmovers/athlete_form.html
+++ b/boatmovers/templates/boatmovers/athlete_form.html
@@ -1,4 +1,7 @@
+{% extends "boatmovers_base.html" %}
+{% block main %}
+{% endblock %}
diff --git a/boatmovers/templates/boatmovers/race_form.html b/boatmovers/templates/boatmovers/race_form.html
index a9b32c5f..da989c98 100644
--- a/boatmovers/templates/boatmovers/race_form.html
+++ b/boatmovers/templates/boatmovers/race_form.html
@@ -1,4 +1,7 @@
+{% extends "boatmovers_base.html" %}
+{% block main %}
+{% endblock %}
diff --git a/boatmovers/templates/boatmovers/result_form.html b/boatmovers/templates/boatmovers/result_form.html
index a9b32c5f..da989c98 100644
--- a/boatmovers/templates/boatmovers/result_form.html
+++ b/boatmovers/templates/boatmovers/result_form.html
@@ -1,4 +1,7 @@
+{% extends "boatmovers_base.html" %}
+{% block main %}
+{% endblock %}
diff --git a/boatmovers/templates/boatmovers_base.html b/boatmovers/templates/boatmovers_base.html
new file mode 100644
index 00000000..af81b876
--- /dev/null
+++ b/boatmovers/templates/boatmovers_base.html
@@ -0,0 +1,33 @@
+{% load leaflet_tags %}
+{% load cookielaw_tags %}
+
+{% block filters %}
+{% endblock %}
+
+
+
+ {% block title %}Rowsandall Boatmovers{% endblock %}
+
+
+
+
+ {% if WARNING_MESSAGE != '' %}
+ {{ WARNING_MESSAGE }}
+ {% endif %}
+ {% if messages %}
+ {% for message in messages %}
+
+ {{ message|safe }}
+
+ {% endfor %}
+ {% endif %}
+
+ {% block main %}
+
+ {% endblock %}
+
+
+
+ {% block scripts %} {% endblock %}
diff --git a/boatmovers/templates/crew.html b/boatmovers/templates/crew.html
index 56d33232..074882fb 100644
--- a/boatmovers/templates/crew.html
+++ b/boatmovers/templates/crew.html
@@ -1,3 +1,5 @@
+{% extends "boatmovers_base.html" %}
+{% block main %}
{{ crew.name }}
@@ -17,3 +19,4 @@
{% endfor %}
+{% endblock %}
diff --git a/boatmovers/templates/race.html b/boatmovers/templates/race.html
index 8f602c69..3e92de8a 100644
--- a/boatmovers/templates/race.html
+++ b/boatmovers/templates/race.html
@@ -1,3 +1,6 @@
+{% extends "boatmovers_base.html" %}
+
+{% block main %}
{{ race.name }}
@@ -48,3 +51,4 @@
{% endif %}
{% endif %}
+{% endblock %}
diff --git a/boatmovers/views.py b/boatmovers/views.py
index 94f3cb0b..97c937f7 100644
--- a/boatmovers/views.py
+++ b/boatmovers/views.py
@@ -2,12 +2,16 @@ from django.shortcuts import render
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.urls import reverse
+from django.contrib import messages
import collections
# Create your views here.
from django.views.generic.edit import CreateView
from boatmovers.models import Athlete, Crew, Race, Result
+import boatmovers.tasks as tasks
+import django_rq
+queue = django_rq.get_queue('high')
class AthleteCreateView(CreateView):
model = Athlete
@@ -106,7 +110,9 @@ def race_verify(request, id=0):
def race_process(request, id=0):
race = get_object_or_404(Race, pk=id)
- outcome = race.process()
+ job = queue.enqueue(tasks.race_process,race.id)
+ #outcome = race.process()
+ messages.info(request,"Your race is being processed. Reload to get the new status.")
return HttpResponseRedirect(reverse('race_view',kwargs={'id':race.id}))
From a4926ccc72e988583a792d42b0634a1b4021b532 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Wed, 29 Jun 2022 16:35:47 +0200
Subject: [PATCH 13/19] better check for duplicate athletes
---
boatmovers/models.py | 5 +++++
boatmovers/scrapers.py | 28 +++++++++++++++++++++-------
2 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/boatmovers/models.py b/boatmovers/models.py
index 616ee1ef..fa119fad 100644
--- a/boatmovers/models.py
+++ b/boatmovers/models.py
@@ -33,6 +33,11 @@ class Athlete(models.Model):
return u'{f} {l}'.format(f = self.first_name, l=self.last_name)
def save(self, *args, **kwargs):
+ name = '{f} {l}'.format(f = self.first_name, l = self.last_name)
+ for a in Athlete.objects.filter(gender=self.gender):
+ aname = '{f} {l}'.format(f = a.first_name, l = a.last_name)
+ if name == aname:
+ raise ValidationError("Duplicate:{id}".format(id=a.id))
rating = trueskill.Rating(self.trueskill_mu, self.trueskill_sigma)
self.trueskill_exposed = trueskill.expose(rating)
diff --git a/boatmovers/scrapers.py b/boatmovers/scrapers.py
index 8e00011c..44f469c1 100644
--- a/boatmovers/scrapers.py
+++ b/boatmovers/scrapers.py
@@ -3,11 +3,12 @@ from bs4 import BeautifulSoup
import requests
from boatmovers.models import *
import pandas as pd
+from django.core.exceptions import ValidationError
url_heineken = ''
-def csv_reader(filename,raceid,clubcol='Ploeg',bankjes=['Slag'],uitslag='Pos'):
+def csv_reader(filename,raceid,clubcol='Ploeg',bankjes=['Slag'],uitslag='Pos',gender='m'):
race = Race.objects.get(id=raceid)
nr = race.crew_size
@@ -33,14 +34,21 @@ def csv_reader(filename,raceid,clubcol='Ploeg',bankjes=['Slag'],uitslag='Pos'):
first_name = 'Unknown'
last_name = 'Athlete'
athletes = Athlete.objects.filter(first_name = first_name,
- last_name = last_name)
+ last_name = last_name,
+ gender=gender)
if len(athletes) >= 1:
athlete = athletes[0]
else:
athlete = Athlete(first_name=first_name,
last_name=last_name,
- club = crewname)
- athlete.save()
+ club = crewname,
+ gender=gender)
+ try:
+ athlete.save()
+ except ValidationError as e:
+ text, id = e.message.split(':')
+ athlete = Athlete.objects.get(id=id)
+
print(athlete)
crew.athletes.add(athlete)
@@ -56,7 +64,7 @@ def csv_reader(filename,raceid,clubcol='Ploeg',bankjes=['Slag'],uitslag='Pos'):
print(e)
-def time_team_scraper(url,raceid):
+def time_team_scraper(url,raceid,gender='m'):
race = Race.objects.get(id=raceid)
nr = race.crew_size
r = requests.get(url)
@@ -105,8 +113,14 @@ def time_team_scraper(url,raceid):
else:
athlete = Athlete(first_name=first_name,
last_name=last_name,
- club = name)
- athlete.save()
+ club = name,
+ gender=gender)
+ try:
+ athlete.save()
+ except ValidationError as e:
+ text, id = e.message.split(':')
+ athlete = Athlete.objects.get(id=id)
+
print(athlete)
crew.athletes.add(athlete)
From 76dec8d3acdbe9ce4254b2efd10e544810002f30 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Wed, 29 Jun 2022 20:24:18 +0200
Subject: [PATCH 14/19] add
---
boatmovers/migrations/0014_athlete_dummy.py | 18 +++++++++++
.../0015_alter_athlete_unique_together.py | 17 ++++++++++
boatmovers/migrations/0016_race_gender.py | 18 +++++++++++
boatmovers/models.py | 26 +++++++++++++---
boatmovers/scrapers.py | 31 +++++++++++++------
boatmovers/templates/boatmovers.html | 5 +++
boatmovers/urls.py | 3 +-
boatmovers/views.py | 10 +++++-
8 files changed, 112 insertions(+), 16 deletions(-)
create mode 100644 boatmovers/migrations/0014_athlete_dummy.py
create mode 100644 boatmovers/migrations/0015_alter_athlete_unique_together.py
create mode 100644 boatmovers/migrations/0016_race_gender.py
diff --git a/boatmovers/migrations/0014_athlete_dummy.py b/boatmovers/migrations/0014_athlete_dummy.py
new file mode 100644
index 00000000..f3aec5e7
--- /dev/null
+++ b/boatmovers/migrations/0014_athlete_dummy.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.12 on 2022-06-29 15:45
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('boatmovers', '0013_alter_crew_athletes'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='athlete',
+ name='dummy',
+ field=models.BooleanField(default=False),
+ ),
+ ]
diff --git a/boatmovers/migrations/0015_alter_athlete_unique_together.py b/boatmovers/migrations/0015_alter_athlete_unique_together.py
new file mode 100644
index 00000000..ee5e6ac1
--- /dev/null
+++ b/boatmovers/migrations/0015_alter_athlete_unique_together.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.2.12 on 2022-06-29 17:44
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('boatmovers', '0014_athlete_dummy'),
+ ]
+
+ operations = [
+ migrations.AlterUniqueTogether(
+ name='athlete',
+ unique_together={('first_name', 'last_name', 'birth_year', 'gender')},
+ ),
+ ]
diff --git a/boatmovers/migrations/0016_race_gender.py b/boatmovers/migrations/0016_race_gender.py
new file mode 100644
index 00000000..ffedd044
--- /dev/null
+++ b/boatmovers/migrations/0016_race_gender.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.12 on 2022-06-29 18:23
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('boatmovers', '0015_alter_athlete_unique_together'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='race',
+ name='gender',
+ field=models.CharField(choices=[('m', 'M'), ('f', 'F')], default='m', max_length=200),
+ ),
+ ]
diff --git a/boatmovers/models.py b/boatmovers/models.py
index fa119fad..34fd7a6c 100644
--- a/boatmovers/models.py
+++ b/boatmovers/models.py
@@ -25,16 +25,20 @@ class Athlete(models.Model):
trueskill_exposed = models.FloatField(default=0)
birth_year = models.IntegerField(default=1972)
gender = models.CharField(max_length=200, choices=(('m','M'),('f','F')))
+ dummy = models.BooleanField(default=False)
class Meta:
- unique_together = ('first_name','last_name','birth_year')
+ unique_together = ('first_name','last_name','birth_year','gender')
def __str__(self):
return u'{f} {l}'.format(f = self.first_name, l=self.last_name)
def save(self, *args, **kwargs):
name = '{f} {l}'.format(f = self.first_name, l = self.last_name)
- for a in Athlete.objects.filter(gender=self.gender):
+ athletes = Athlete.objects.filter(gender=self.gender)
+ if self.pk is not None:
+ athletes = athletes.exclude(pk=self.pk)
+ for a in athletes:
aname = '{f} {l}'.format(f = a.first_name, l = a.last_name)
if name == aname:
raise ValidationError("Duplicate:{id}".format(id=a.id))
@@ -78,6 +82,7 @@ class Race(models.Model):
choices=((1,1),(2,2),(4,4),(8,8)))
verified = models.BooleanField(default=False)
processed = models.BooleanField(default=False)
+ gender = models.CharField(max_length=200,choices=(('m','M'),('f','F')),default='m')
class Meta:
unique_together = ('date','name')
@@ -106,8 +111,10 @@ class Race(models.Model):
super(Race, self).save(*args, **kwargs)
- def validate(self):
+ def validate(self, verbose=False):
if len(self.results.all()) < 2:
+ if verbose:
+ print('False: Less than 2 results')
self.verified = False
self.save()
return False
@@ -115,11 +122,15 @@ class Race(models.Model):
l = self.results.all()[0].crew.size()
for result in self.results.all():
if result.crew.size() != l:
+ if verbose:
+ print('False: crew {c} has different crew size'.format(c=result.crew))
self.verified = False
self.save()
return False
if l not in [1,2,4,8]:
+ if verbose:
+ print('False: Crew size not in 1, 2, 4, or 8')
self.verified = False
self.save()
return False
@@ -130,14 +141,19 @@ class Race(models.Model):
for result in results:
crews.append(result.crew.id)
for athlete in result.crew.athletes.all():
- athletes.append(athlete.id)
+ if not athlete.dummy:
+ athletes.append(athlete.id)
if len(crews) != len(set(crews)):
+ if verbose:
+ print('False: Same crew competing twice')
self.verified = False
self.save()
return False
if len(athletes) != len(set(athletes)):
+ if verbose:
+ print('False: Duplicate athletes')
self.verified = False
self.save()
return False
@@ -196,7 +212,7 @@ class Race(models.Model):
class raceForm(forms.ModelForm):
class Meta:
model = Race
- fields = ['name','date','resulturl','crew_size']
+ fields = ['name','date','resulturl','crew_size','gender']
class Result(models.Model):
diff --git a/boatmovers/scrapers.py b/boatmovers/scrapers.py
index 44f469c1..d67e2fea 100644
--- a/boatmovers/scrapers.py
+++ b/boatmovers/scrapers.py
@@ -8,7 +8,8 @@ from django.core.exceptions import ValidationError
url_heineken = ''
-def csv_reader(filename,raceid,clubcol='Ploeg',bankjes=['Slag'],uitslag='Pos',gender='m'):
+def csv_reader(filename,raceid,clubcol='Ploeg',bankjes=['Slag'],uitslag='Pos',gender='m',
+ startorder=1):
race = Race.objects.get(id=raceid)
nr = race.crew_size
@@ -26,13 +27,16 @@ def csv_reader(filename,raceid,clubcol='Ploeg',bankjes=['Slag'],uitslag='Pos',ge
naam = row[df.columns.get_loc(bankjes[i])+1].split(' ')
first_name = ' '.join(naam[:-1])
last_name = naam[-1]
+ dummy = False
except AttributeError:
try:
first_name = str(row.Slag)
last_name = ''
+ dummy=False
except TypeError:
first_name = 'Unknown'
last_name = 'Athlete'
+ dummy=True
athletes = Athlete.objects.filter(first_name = first_name,
last_name = last_name,
gender=gender)
@@ -42,7 +46,8 @@ def csv_reader(filename,raceid,clubcol='Ploeg',bankjes=['Slag'],uitslag='Pos',ge
athlete = Athlete(first_name=first_name,
last_name=last_name,
club = crewname,
- gender=gender)
+ gender=gender,
+ dummy=dummy)
try:
athlete.save()
except ValidationError as e:
@@ -59,12 +64,15 @@ def csv_reader(filename,raceid,clubcol='Ploeg',bankjes=['Slag'],uitslag='Pos',ge
order = order
)
try:
- result.save()
+ if order>=startorder:
+ result.save()
except ValidationError as e:
print(e)
+ print(' ')
-def time_team_scraper(url,raceid,gender='m'):
+
+def time_team_scraper(url,raceid,gender='m',startorder=1):
race = Race.objects.get(id=raceid)
nr = race.crew_size
r = requests.get(url)
@@ -99,13 +107,16 @@ def time_team_scraper(url,raceid,gender='m'):
names = df['naam'][i].split(' ')
first_name = ' '.join(names[:-1])
last_name = names[-1]
+ dummy=False
except AttributeError:
try:
first_name = str(df['naam'][i])
last_name = ''
+ dummy=False
except TypeError:
first_name = 'Unknown'
last_name = 'Athlete'
+ dummy=True
athletes = Athlete.objects.filter(first_name = first_name,
last_name = last_name)
if len(athletes) >= 1:
@@ -114,7 +125,8 @@ def time_team_scraper(url,raceid,gender='m'):
athlete = Athlete(first_name=first_name,
last_name=last_name,
club = name,
- gender=gender)
+ gender=gender,
+ dummy=dummy)
try:
athlete.save()
except ValidationError as e:
@@ -130,10 +142,11 @@ def time_team_scraper(url,raceid,gender='m'):
race = race,
order = order
)
- try:
- result.save()
- except ValidationError as e:
- print(e)
+ if order >= startorder:
+ try:
+ result.save()
+ except ValidationError as e:
+ print(e)
order += 1
diff --git a/boatmovers/templates/boatmovers.html b/boatmovers/templates/boatmovers.html
index 0a08e1db..b33d4823 100644
--- a/boatmovers/templates/boatmovers.html
+++ b/boatmovers/templates/boatmovers.html
@@ -17,6 +17,11 @@
Boat Movers Ranking
+
diff --git a/boatmovers/urls.py b/boatmovers/urls.py
index 1ce9ca38..a2933262 100644
--- a/boatmovers/urls.py
+++ b/boatmovers/urls.py
@@ -13,5 +13,6 @@ urlpatterns = [
url(r'race/(?P\d+)/verify/$',views.race_verify,name='race_verify'),
url(r'race/(?P\d+)/process/$',views.race_process,name='race_process'),
url(r'crew/(?P\d+)/$',views.crew_view,name='crew_view'),
- url(r'^$',views.boatmovers_view,name='boatmovers')
+ url(r'^$',views.boatmovers_view,name='boatmovers'),
+ #url(r'(?P\b[0-9A-Fa-f]+\b)/$',views.boatmovers_view,name='boatmovers')
]
diff --git a/boatmovers/views.py b/boatmovers/views.py
index 97c937f7..5ff1700c 100644
--- a/boatmovers/views.py
+++ b/boatmovers/views.py
@@ -56,7 +56,15 @@ class ResultCreateView(CreateView):
success_url = '/boatmovers/'
def boatmovers_view(request):
- athletes = Athlete.objects.filter(trueskill_exposed__gt=0).order_by('-trueskill_exposed','-birth_year','last_name','first_name')
+ athletes = Athlete.objects.filter(trueskill_exposed__gt=0,
+ dummy=False).order_by('-trueskill_exposed','-birth_year','last_name','first_name')
+
+ filter = request.GET.get('filter','all')
+
+ if filter == 'm':
+ athletes = athletes.exclude(gender='f')
+ elif filter == 'f':
+ athletes = athletes.exclude(gender='m')
races = Race.objects.filter(verified=True,processed=True).order_by('-date')
new_races = Race.objects.filter(processed=False).order_by('date')
From 966b5454d3a1da358985016adfbf3e5819dde391 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Wed, 29 Jun 2022 21:36:40 +0200
Subject: [PATCH 15/19] fix
---
boatmovers/forms.py | 5 +++
boatmovers/templates/athlete.html | 16 ++++++++
boatmovers/templates/csvform.html | 14 +++++++
boatmovers/templates/race.html | 3 ++
boatmovers/urls.py | 2 +
boatmovers/views.py | 63 +++++++++++++++++++++++++++++++
6 files changed, 103 insertions(+)
create mode 100644 boatmovers/forms.py
create mode 100644 boatmovers/templates/athlete.html
create mode 100644 boatmovers/templates/csvform.html
diff --git a/boatmovers/forms.py b/boatmovers/forms.py
new file mode 100644
index 00000000..ca5efb59
--- /dev/null
+++ b/boatmovers/forms.py
@@ -0,0 +1,5 @@
+from django import forms
+
+class CsvForm(forms.Form):
+ file = forms.FileField(label='CSV File')
+ # comment = forms.CharField(required=False)
diff --git a/boatmovers/templates/athlete.html b/boatmovers/templates/athlete.html
new file mode 100644
index 00000000..ad92e6ce
--- /dev/null
+++ b/boatmovers/templates/athlete.html
@@ -0,0 +1,16 @@
+{% extends "boatmovers_base.html" %}
+
+{% block main %}
+
+ {{ athlete.first_name }} {{ athlete.last_name }}
+
+
+
+ {% for result in results %}
+
+ | {{ result.order }} | {{ result.race.name }} |
+
+ {% endfor %}
+
+
+{% endblock %}
diff --git a/boatmovers/templates/csvform.html b/boatmovers/templates/csvform.html
new file mode 100644
index 00000000..fe1e592a
--- /dev/null
+++ b/boatmovers/templates/csvform.html
@@ -0,0 +1,14 @@
+{% extends "boatmovers_base.html" %}
+
+{% block main %}
+
+ {{ athlete.first_name }} {{ athlete.last_name }}
+
+
+
+
+{% endblock %}
diff --git a/boatmovers/templates/race.html b/boatmovers/templates/race.html
index 3e92de8a..ba1a7def 100644
--- a/boatmovers/templates/race.html
+++ b/boatmovers/templates/race.html
@@ -7,6 +7,9 @@
{{ race.date }}
+
+ Results
+
diff --git a/boatmovers/urls.py b/boatmovers/urls.py
index a2933262..56483293 100644
--- a/boatmovers/urls.py
+++ b/boatmovers/urls.py
@@ -6,10 +6,12 @@ import boatmovers.views as views
urlpatterns = [
url(r'athlete/add/$',views.AthleteCreateView.as_view(),name='athlete_add'),
+ url(r'athlete/(?P\d+)/$',views.athlete_view,name='athlete_view'),
url(r'crew/add/$',views.CrewCreateView.as_view(),name='crew_add'),
url(r'race/add/$',views.RaceCreateView.as_view(),name='race_add'),
url(r'result/add/$',views.ResultCreateView.as_view(),name='result_add'),
url(r'race/(?P\d+)/$',views.race_view,name='race_view'),
+ url(r'race/(?P\d+)/csv/$',views.race_add_csv,name='race_add_csv'),
url(r'race/(?P\d+)/verify/$',views.race_verify,name='race_verify'),
url(r'race/(?P\d+)/process/$',views.race_process,name='race_process'),
url(r'crew/(?P\d+)/$',views.crew_view,name='crew_view'),
diff --git a/boatmovers/views.py b/boatmovers/views.py
index 5ff1700c..3b048a8c 100644
--- a/boatmovers/views.py
+++ b/boatmovers/views.py
@@ -10,6 +10,9 @@ import collections
from django.views.generic.edit import CreateView
from boatmovers.models import Athlete, Crew, Race, Result
import boatmovers.tasks as tasks
+from boatmovers.forms import CsvForm
+from boatmovers.scrapers import *
+#from rowers.rows import handle_uploaded_file
import django_rq
queue = django_rq.get_queue('high')
@@ -55,6 +58,24 @@ class ResultCreateView(CreateView):
success_url = '/boatmovers/'
+def athlete_view(request,id=0):
+ athlete = get_object_or_404(Athlete, pk=id)
+ crews = athlete.athlete_crews
+ resultslist = []
+
+ for crew in crews.values():
+ c = Crew.objects.get(id=crew['id'])
+ results = Result.objects.filter(crew=c)
+ for result in results:
+ resultslist.append(result)
+
+ return render(request,
+ 'athlete.html',
+ {
+ 'athlete':athlete,
+ 'results':resultslist,
+ })
+
def boatmovers_view(request):
athletes = Athlete.objects.filter(trueskill_exposed__gt=0,
dummy=False).order_by('-trueskill_exposed','-birth_year','last_name','first_name')
@@ -116,6 +137,48 @@ def race_verify(request, id=0):
return HttpResponseRedirect(reverse('race_view',kwargs={'id':race.id}))
+def handle_uploaded_file(f):
+ with open('media/results.csv', 'wb+') as destination:
+ for chunk in f.chunks():
+ destination.write(chunk)
+
+def race_add_csv(request, id=0):
+ race = get_object_or_404(Race, pk=id)
+ if race.verified or race.processed:
+ messages.error(request,"Cannot upload CSV file for processed or verified race")
+ url = reverse("race_view",kwargs={'id':id})
+ return HttpResponseRedirect(url)
+
+ form = CsvForm()
+ if request.method == 'POST':
+
+ form = CsvForm(request.POST, request.FILES)
+
+ if form.is_valid():
+ handle_uploaded_file(request.FILES['file'])
+ if race.crew_size == 1:
+ bankjes = ['Slag']
+ elif race.crew_size == 2:
+ bankjes = ['Slag','Boeg']
+ elif race.crew_size == 4:
+ bankjes = ['Slag','2','3','Boeg']
+ elif race.crew_size == 8:
+ bankjes = ['Slag','2','3','4','5','6','7','Boeg']
+
+ csv_reader('media/results.csv',race.id,bankjes=bankjes,gender=race.gender)
+
+ url = reverse('race_view',kwargs={'id':race.id})
+
+ return HttpResponseRedirect(url)
+
+
+ return render(request,
+ 'csvform.html',
+ {
+ 'race':race,
+ 'form':form,
+ })
+
def race_process(request, id=0):
race = get_object_or_404(Race, pk=id)
job = queue.enqueue(tasks.race_process,race.id)
From 7fff546dbdf0da1855576571d6923ffd0a819884 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Wed, 29 Jun 2022 21:43:08 +0200
Subject: [PATCH 16/19] fix
---
boatmovers/templates/boatmovers.html | 1 +
boatmovers/templates/csvform.html | 4 ++--
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/boatmovers/templates/boatmovers.html b/boatmovers/templates/boatmovers.html
index b33d4823..0fef3c78 100644
--- a/boatmovers/templates/boatmovers.html
+++ b/boatmovers/templates/boatmovers.html
@@ -41,6 +41,7 @@
| {{ athlete.last_name }} |
{{ athlete.club }} |
{{ athlete.gender }} |
+ results |
{% if user.is_authenticated and user.is_staff %}
edit |
{% endif %}
diff --git a/boatmovers/templates/csvform.html b/boatmovers/templates/csvform.html
index fe1e592a..483c4a0e 100644
--- a/boatmovers/templates/csvform.html
+++ b/boatmovers/templates/csvform.html
@@ -2,10 +2,10 @@
{% block main %}
- {{ athlete.first_name }} {{ athlete.last_name }}
+ {{ race.name }}
-