Private
Public Access
1
0
Files
rowsandall/boatmovers/models.py
Sander Roosendaal 194140f627 adding full_name
2022-07-08 14:46:04 +02:00

259 lines
8.3 KiB
Python

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
from rowers.utils import dologging
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)
full_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')))
dummy = models.BooleanField(default=False)
class Meta:
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)
self.full_name = name
athletes = Athlete.objects.filter(gender=self.gender, full_name=self.full_name)
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))
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, related_name='athlete_crews')
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)
gender = models.CharField(max_length=200,choices=(('m','M'),('f','F')),default='m')
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, verbose=False):
if len(self.results.all()) < 2:
if verbose:
print('False: Less than 2 results')
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:
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
results = self.results.all()
crews = []
athletes = []
for result in results:
crews.append(result.crew.id)
for athlete in result.crew.athletes.all():
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
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()
u = '{id},{f},{l},{mu},{sigma},{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.csv',u)
self.processed = True
self.save()
return True
class raceForm(forms.ModelForm):
class Meta:
model = Race
fields = ['name','date','resulturl','crew_size','gender']
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)):
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"
)
super(Result,self).save(*args, **kwargs)
class resultForm(forms.ModelForm):
class Meta:
model = Result
fields = ['crew','race','order']