263 lines
8.1 KiB
Python
263 lines
8.1 KiB
Python
import os
|
|
import re
|
|
|
|
from django import forms
|
|
from django.db.models import Q
|
|
from django.template.defaultfilters import filesizeformat
|
|
from django.utils import timezone
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
from member.models import TFJMUser, Solution, Synthesis
|
|
from tfjm.inputs import DatePickerInput, DateTimePickerInput, AmountInput
|
|
from tournament.models import Tournament, Team, Pool
|
|
|
|
|
|
class TournamentForm(forms.ModelForm):
|
|
"""
|
|
Create and update tournaments.
|
|
"""
|
|
|
|
# Only organizers can organize tournaments. Well, that's pretty normal...
|
|
organizers = forms.ModelMultipleChoiceField(
|
|
TFJMUser.objects.filter(Q(role="0admin") | Q(role="1volunteer")).order_by('role'),
|
|
label=_("Organizers"),
|
|
)
|
|
|
|
def clean(self):
|
|
cleaned_data = super().clean()
|
|
|
|
if not self.instance.pk:
|
|
if Tournament.objects.filter(name=cleaned_data["data"], year=os.getenv("TFJM_YEAR")):
|
|
self.add_error("name", _("This tournament already exists."))
|
|
if cleaned_data["final"] and Tournament.objects.filter(final=True, year=os.getenv("TFJM_YEAR")):
|
|
self.add_error("name", _("The final tournament was already defined."))
|
|
|
|
return cleaned_data
|
|
|
|
class Meta:
|
|
model = Tournament
|
|
exclude = ('year',)
|
|
widgets = {
|
|
"price": AmountInput(),
|
|
"date_start": DatePickerInput(),
|
|
"date_end": DatePickerInput(),
|
|
"date_inscription": DateTimePickerInput(),
|
|
"date_solutions": DateTimePickerInput(),
|
|
"date_syntheses": DateTimePickerInput(),
|
|
"date_solutions_2": DateTimePickerInput(),
|
|
"date_syntheses_2": DateTimePickerInput(),
|
|
}
|
|
|
|
|
|
class OrganizerForm(forms.ModelForm):
|
|
"""
|
|
Register an organizer in the website.
|
|
"""
|
|
|
|
class Meta:
|
|
model = TFJMUser
|
|
fields = ('last_name', 'first_name', 'email', 'is_superuser',)
|
|
|
|
def clean(self):
|
|
cleaned_data = super().clean()
|
|
|
|
if TFJMUser.objects.filter(email=cleaned_data["email"], year=os.getenv("TFJM_YEAR")).exists():
|
|
self.add_error("email", _("This organizer already exist."))
|
|
|
|
return cleaned_data
|
|
|
|
def save(self, commit=True):
|
|
user = self.instance
|
|
user.role = '0admin' if user.is_superuser else '1volunteer'
|
|
user.save()
|
|
super().save(commit)
|
|
|
|
|
|
class TeamForm(forms.ModelForm):
|
|
"""
|
|
Add and update a team.
|
|
"""
|
|
tournament = forms.ModelChoiceField(
|
|
Tournament.objects.filter(date_inscription__gte=timezone.now(), final=False),
|
|
)
|
|
|
|
class Meta:
|
|
model = Team
|
|
fields = ('name', 'trigram', 'tournament',)
|
|
|
|
def clean(self):
|
|
cleaned_data = super().clean()
|
|
|
|
cleaned_data["trigram"] = cleaned_data["trigram"].upper()
|
|
|
|
if not re.match("[A-Z]{3}", cleaned_data["trigram"]):
|
|
self.add_error("trigram", _("The trigram must be composed of three upcase letters."))
|
|
|
|
if not self.instance.pk:
|
|
if Team.objects.filter(trigram=cleaned_data["trigram"], year=os.getenv("TFJM_YEAR")).exists():
|
|
self.add_error("trigram", _("This trigram is already used."))
|
|
|
|
if Team.objects.filter(name=cleaned_data["name"], year=os.getenv("TFJM_YEAR")).exists():
|
|
self.add_error("name", _("This name is already used."))
|
|
|
|
if cleaned_data["tournament"].date_inscription < timezone.now:
|
|
self.add_error("tournament", _("This tournament is already closed."))
|
|
|
|
return cleaned_data
|
|
|
|
|
|
class JoinTeam(forms.Form):
|
|
"""
|
|
Form to join a team with an access code.
|
|
"""
|
|
|
|
access_code = forms.CharField(
|
|
label=_("Access code"),
|
|
max_length=6,
|
|
)
|
|
|
|
def clean(self):
|
|
cleaned_data = super().clean()
|
|
|
|
if not re.match("[a-z0-9]{6}", cleaned_data["access_code"]):
|
|
self.add_error('access_code', _("The access code must be composed of 6 alphanumeric characters."))
|
|
|
|
team = Team.objects.filter(access_code=cleaned_data["access_code"])
|
|
if not team.exists():
|
|
self.add_error('access_code', _("This access code is invalid."))
|
|
team = team.get()
|
|
if not team.invalid:
|
|
self.add_error('access_code', _("The team is already validated."))
|
|
cleaned_data["team"] = team
|
|
|
|
return cleaned_data
|
|
|
|
|
|
class SolutionForm(forms.ModelForm):
|
|
"""
|
|
Form to upload a solution.
|
|
"""
|
|
|
|
problem = forms.ChoiceField(
|
|
label=_("Problem"),
|
|
choices=[(str(i), _("Problem #%(problem)d") % {"problem": i}) for i in range(1, 9)],
|
|
)
|
|
|
|
def clean_file(self):
|
|
content = self.cleaned_data['file']
|
|
content_type = content.content_type
|
|
if content_type in ["application/pdf"]:
|
|
if content.size > 5 * 2 ** 20:
|
|
raise forms.ValidationError(
|
|
_('Please keep filesize under %(max_size)s. Current filesize %(current_size)s') % {
|
|
"max_size": filesizeformat(2 * 2 ** 20),
|
|
"current_size": filesizeformat(content.size)
|
|
})
|
|
else:
|
|
raise forms.ValidationError(_('The file should be a PDF file.'))
|
|
return content
|
|
|
|
class Meta:
|
|
model = Solution
|
|
fields = ('file', 'problem',)
|
|
|
|
|
|
class SynthesisForm(forms.ModelForm):
|
|
"""
|
|
Form to upload a synthesis.
|
|
"""
|
|
|
|
def clean_file(self):
|
|
content = self.cleaned_data['file']
|
|
content_type = content.content_type
|
|
if content_type in ["application/pdf"]:
|
|
if content.size > 5 * 2 ** 20:
|
|
raise forms.ValidationError(
|
|
_('Please keep filesize under %(max_size)s. Current filesize %(current_size)s') % {
|
|
"max_size": filesizeformat(2 * 2 ** 20),
|
|
"current_size": filesizeformat(content.size)
|
|
})
|
|
else:
|
|
raise forms.ValidationError(_('The file should be a PDF file.'))
|
|
return content
|
|
|
|
class Meta:
|
|
model = Synthesis
|
|
fields = ('file', 'source', 'round',)
|
|
|
|
|
|
class PoolForm(forms.ModelForm):
|
|
"""
|
|
Form to add a pool.
|
|
Should not be used: prefer to pass by API and auto-add pools with the results of the draw.
|
|
"""
|
|
|
|
team1 = forms.ModelChoiceField(
|
|
Team.objects.filter(validation_status="2valid").all(),
|
|
empty_label=_("Choose a team..."),
|
|
label=_("Team 1"),
|
|
)
|
|
|
|
problem1 = forms.IntegerField(
|
|
min_value=1,
|
|
max_value=8,
|
|
initial=1,
|
|
label=_("Problem defended by team 1"),
|
|
)
|
|
|
|
team2 = forms.ModelChoiceField(
|
|
Team.objects.filter(validation_status="2valid").all(),
|
|
empty_label=_("Choose a team..."),
|
|
label=_("Team 2"),
|
|
)
|
|
|
|
problem2 = forms.IntegerField(
|
|
min_value=1,
|
|
max_value=8,
|
|
initial=2,
|
|
label=_("Problem defended by team 2"),
|
|
)
|
|
|
|
team3 = forms.ModelChoiceField(
|
|
Team.objects.filter(validation_status="2valid").all(),
|
|
empty_label=_("Choose a team..."),
|
|
label=_("Team 3"),
|
|
)
|
|
|
|
problem3 = forms.IntegerField(
|
|
min_value=1,
|
|
max_value=8,
|
|
initial=3,
|
|
label=_("Problem defended by team 3"),
|
|
)
|
|
|
|
def clean(self):
|
|
cleaned_data = super().clean()
|
|
|
|
team1, pb1 = cleaned_data["team1"], cleaned_data["problem1"]
|
|
team2, pb2 = cleaned_data["team2"], cleaned_data["problem2"]
|
|
team3, pb3 = cleaned_data["team3"], cleaned_data["problem3"]
|
|
|
|
sol1 = Solution.objects.get(team=team1, problem=pb1, final=team1.selected_for_final)
|
|
sol2 = Solution.objects.get(team=team2, problem=pb2, final=team2.selected_for_final)
|
|
sol3 = Solution.objects.get(team=team3, problem=pb3, final=team3.selected_for_final)
|
|
|
|
cleaned_data["teams"] = [team1, team2, team3]
|
|
cleaned_data["solutions"] = [sol1, sol2, sol3]
|
|
|
|
return cleaned_data
|
|
|
|
def save(self, commit=True):
|
|
pool = super().save(commit)
|
|
|
|
pool.refresh_from_db()
|
|
pool.teams.set(self.cleaned_data["teams"])
|
|
pool.solutions.set(self.cleaned_data["solutions"])
|
|
pool.save()
|
|
|
|
return pool
|
|
|
|
class Meta:
|
|
model = Pool
|
|
fields = ('round', 'juries',)
|