Private
Public Access
1
0
Files
rowsandall/boatmovers/models.py
2022-06-24 16:17:18 +02:00

221 lines
6.6 KiB
Python

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:
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=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')))
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)
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
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)
def __str__(self):
return u'{n}'.format(n=self.name)
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
fields = ['name', 'athletes']
class Race(models.Model):
name = models.CharField(max_length=200)
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=False)
class Meta:
unique_together = ('date','name')
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)
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']
class Result(models.Model):
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','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()
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']