# Copyright (C) 2020 by Animath # SPDX-License-Identifier: GPL-3.0-or-later import re from bootstrap_datepicker_plus import DatePickerInput, DateTimePickerInput from django import forms from django.core.exceptions import ValidationError from django.utils import formats from django.utils.translation import gettext_lazy as _ from PyPDF3 import PdfFileReader from .models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament class TeamForm(forms.ModelForm): """ Form to create a team, with the name and the trigram,... """ def clean_trigram(self): trigram = self.cleaned_data["trigram"].upper() if not re.match("[A-Z]{3}", trigram): raise ValidationError(_("The trigram must be composed of three uppercase letters.")) return trigram class Meta: model = Team fields = ('name', 'trigram',) class JoinTeamForm(forms.ModelForm): """ Form to join a team by the access code. """ def clean_access_code(self): access_code = self.cleaned_data["access_code"] if not Team.objects.filter(access_code=access_code).exists(): raise ValidationError(_("No team was found with this access code.")) return access_code def clean(self): cleaned_data = super().clean() if "access_code" in cleaned_data: team = Team.objects.get(access_code=cleaned_data["access_code"]) self.instance = team return cleaned_data class Meta: model = Team fields = ('access_code',) class ParticipationForm(forms.ModelForm): """ Form to update the problem of a team participation. """ class Meta: model = Participation fields = ('tournament',) class RequestValidationForm(forms.Form): """ Form to ask about validation. """ _form_type = forms.CharField( initial="RequestValidationForm", widget=forms.HiddenInput(), ) engagement = forms.BooleanField( label=_("I engage myself to participate to the whole TFJM²."), required=True, ) class ValidateParticipationForm(forms.Form): """ Form to let administrators to accept or refuse a team. """ _form_type = forms.CharField( initial="ValidateParticipationForm", widget=forms.HiddenInput(), ) message = forms.CharField( label=_("Message to address to the team:"), widget=forms.Textarea(), ) class TournamentForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields["date_start"].widget = DatePickerInput( format=formats.get_format_lazy(format_type="DATE_INPUT_FORMATS", use_l10n=True)[0]) self.fields["date_end"].widget = DatePickerInput( format=formats.get_format_lazy(format_type="DATE_INPUT_FORMATS", use_l10n=True)[0]) self.fields["inscription_limit"].widget = DateTimePickerInput( format=formats.get_format_lazy(format_type="DATETIME_INPUT_FORMATS", use_l10n=True)[0]) self.fields["solution_limit"].widget = DateTimePickerInput( format=formats.get_format_lazy(format_type="DATETIME_INPUT_FORMATS", use_l10n=True)[0]) self.fields["solutions_draw"].widget = DateTimePickerInput( format=formats.get_format_lazy(format_type="DATETIME_INPUT_FORMATS", use_l10n=True)[0]) self.fields["syntheses_first_phase_limit"].widget = DateTimePickerInput( format=formats.get_format_lazy(format_type="DATETIME_INPUT_FORMATS", use_l10n=True)[0]) self.fields["solutions_available_second_phase"].widget = DateTimePickerInput( format=formats.get_format_lazy(format_type="DATETIME_INPUT_FORMATS", use_l10n=True)[0]) self.fields["syntheses_second_phase_limit"].widget = DateTimePickerInput( format=formats.get_format_lazy(format_type="DATETIME_INPUT_FORMATS", use_l10n=True)[0]) self.fields["organizers"].widget = forms.CheckboxSelectMultiple() class Meta: model = Tournament fields = '__all__' class SolutionForm(forms.ModelForm): def clean_file(self): if "file" in self.files: file = self.files["file"] if file.size > 5e6: raise ValidationError(_("The uploaded file size must be under 5 Mo.")) if file.content_type != "application/pdf": raise ValidationError(_("The uploaded file must be a PDF file.")) pdf_reader = PdfFileReader(file) pages = len(pdf_reader.pages) if pages > 30: raise ValidationError(_("The PDF file must not have more than 30 pages.")) return self.cleaned_data["photo_authorization"] def save(self, commit=True): """ Don't save a solution with this way. Use a view instead """ class Meta: model = Solution fields = ('problem', 'file',) class PoolForm(forms.ModelForm): class Meta: model = Pool fields = ('tournament', 'round', 'bbb_code', 'juries',) widgets = { "juries": forms.CheckboxSelectMultiple, } class PoolTeamsForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields["participations"].queryset = self.instance.tournament.participations.all() class Meta: model = Pool fields = ('participations',) widgets = { "participations": forms.CheckboxSelectMultiple, } class PassageForm(forms.ModelForm): def clean(self): cleaned_data = super().clean() if "defender" in cleaned_data and "opponent" in cleaned_data and "reporter" in cleaned_data \ and len({cleaned_data["defender"], cleaned_data["opponent"], cleaned_data["reporter"]}) < 3: self.add_error(None, _("The defender, the opponent and the reporter must be different.")) if "defender" in self.cleaned_data and "solution_number" in self.cleaned_data \ and not Solution.objects.filter(participation=cleaned_data["defender"], problem=cleaned_data["solution_number"]).exists(): self.add_error("solution_number", _("This defender did not work on this problem.")) return cleaned_data class Meta: model = Passage fields = ('solution_number', 'place', 'defender', 'opponent', 'reporter',) class SynthesisForm(forms.ModelForm): def clean_file(self): if "file" in self.files: file = self.files["file"] if file.size > 2e6: raise ValidationError(_("The uploaded file size must be under 2 Mo.")) if file.content_type != "application/pdf": raise ValidationError(_("The uploaded file must be a PDF file.")) return self.cleaned_data["photo_authorization"] def save(self, commit=True): """ Don't save a synthesis with this way. Use a view instead """ class Meta: model = Synthesis fields = ('type', 'file',) class NoteForm(forms.ModelForm): class Meta: model = Note fields = ('defender_writing', 'defender_oral', 'opponent_writing', 'opponent_oral', 'reporter_writing', 'reporter_oral', )