1
0
mirror of https://gitlab.com/animath/si/plateforme.git synced 2025-06-21 07:58:26 +02:00

Validate teams

This commit is contained in:
Yohann D'ANELLO
2020-05-05 02:20:45 +02:00
parent 4534a278d7
commit 4d9b6ad2c5
5 changed files with 202 additions and 13 deletions

View File

@ -1,3 +1,7 @@
import os
import re
from datetime import datetime
from django import forms
from django.utils.translation import gettext_lazy as _
@ -7,6 +11,17 @@ from tournament.models import Tournament, Team
class TournamentForm(forms.ModelForm):
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
fields = '__all__'
@ -25,6 +40,14 @@ class OrganizerForm(forms.ModelForm):
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("trigram", _("This organizer already exist."))
return cleaned_data
def save(self, commit=True):
user = self.instance
user.role = '0admin' if user.is_superuser else '1organizer'
@ -32,10 +55,34 @@ class OrganizerForm(forms.ModelForm):
class TeamForm(forms.ModelForm):
tournament = forms.ModelChoiceField(
Tournament.objects.filter(date_inscription__gte=datetime.today(), 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 < datetime.today():
self.add_error("tournament", _("This tournament is already closed."))
return cleaned_data
class JoinTeam(forms.Form):
access_code = forms.CharField(
@ -46,10 +93,16 @@ class JoinTeam(forms.Form):
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."))
cleaned_data["team"] = team.get()
team = team.get()
if not team.invalid:
self.add_error('access_code', _("The team is already validated."))
cleaned_data["team"] = team
return cleaned_data

View File

@ -1,5 +1,5 @@
import os
from datetime import date
from datetime import date, datetime
from django.db import models
from django.urls import reverse_lazy
@ -36,23 +36,38 @@ class Tournament(models.Model):
)
date_start = models.DateField(
default=datetime.today,
verbose_name=_("date start"),
)
date_end = models.DateField(
default=datetime.today,
verbose_name=_("date end"),
)
date_inscription = models.DateTimeField(
default=datetime.now,
verbose_name=_("date of registration closing"),
)
date_solutions = models.DateTimeField(
default=datetime.now,
verbose_name=_("date of maximal solution submission"),
)
date_syntheses = models.DateTimeField(
verbose_name=_("date of maximal syntheses submission"),
default=datetime.now,
verbose_name=_("date of maximal syntheses submission for the first round"),
)
date_solutions_2 = models.DateTimeField(
default=datetime.now,
verbose_name=_("date when solutions of round 2 are available"),
)
date_syntheses_2 = models.DateTimeField(
default=datetime.now,
verbose_name=_("date of maximal syntheses submission for the second round"),
)
final = models.BooleanField(
@ -172,6 +187,11 @@ class Team(models.Model):
return ['<a href="{url}">'.format(url=reverse_lazy("member:information", args=(user.pk,))) + str(user) + '</a>'
for user in self.participants]
@property
def can_validate(self):
# TODO In a normal time, team needs a motivation letter and authorizations.
return self.encadrants.exists() and self.participants.count() >= 4
class Meta:
verbose_name = _("team")
verbose_name_plural = _("teams")

View File

@ -1,5 +1,6 @@
import random
import zipfile
from datetime import datetime
from io import BytesIO
from django.contrib.auth.mixins import LoginRequiredMixin
@ -21,21 +22,21 @@ from .tables import TournamentTable, TeamTable, SolutionTable, SynthesisTable
class AdminMixin(LoginRequiredMixin):
def dispatch(self, request, *args, **kwargs):
if not request.user.admin:
if not request.user.is_authenticated or not request.user.admin:
raise PermissionDenied
return super().dispatch(request, *args, **kwargs)
class OrgaMixin(LoginRequiredMixin):
def dispatch(self, request, *args, **kwargs):
if not request.user.organizes:
if not request.user.is_authenticated or not request.user.organizes:
raise PermissionDenied
return super().dispatch(request, *args, **kwargs)
class TeamMixin(LoginRequiredMixin):
def dispatch(self, request, *args, **kwargs):
if not request.user.team:
if not request.user.is_authenticated or not request.user.team:
raise PermissionDenied
return super().dispatch(request, *args, **kwargs)
@ -105,12 +106,14 @@ class TeamDetailView(LoginRequiredMixin, DetailView):
model = Team
def dispatch(self, request, *args, **kwargs):
if not request.user.admin and self.request.user not in self.get_object().tournament.organizers.all()\
and self.get_object() != request.user.team:
if not request.user.is_authenticated or \
(not request.user.admin and self.request.user not in self.get_object().tournament.organizers.all()
and self.get_object() != request.user.team):
raise PermissionDenied
return super().dispatch(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
print(request.POST)
team = self.get_object()
if "zip" in request.POST:
solutions = team.solutions.all()
@ -128,13 +131,28 @@ class TeamDetailView(LoginRequiredMixin, DetailView):
.format(_("Solutions for team {team}.zip")
.format(team=str(team)).replace(" ", "%20"))
return resp
elif "leave" in request.POST:
elif "leave" in request.POST and request.user.participates:
request.user.team = None
request.user.save()
if not team.users.exists():
team.delete()
return redirect('tournament:detail', pk=team.tournament.pk)
elif "delete" in request.POST:
elif "request_validation" in request.POST and request.user.participates:
team.validation_status = "1waiting"
team.save()
# TODO Send mail
return redirect('tournament:team_detail', pk=team.pk)
elif "validate" in request.POST and request.user.organizes:
team.validation_status = "2valid"
team.save()
# TODO Send mail
return redirect('tournament:team_detail', pk=team.pk)
elif "invalidate" in request.POST and request.user.organizes:
team.validation_status = "0invalid"
team.save()
# TODO Send mail
return redirect('tournament:team_detail', pk=team.pk)
elif "delete" in request.POST and request.user.organizes:
team.delete()
return redirect('tournament:detail', pk=team.tournament.pk)
@ -204,12 +222,18 @@ class SolutionsView(TeamMixin, BaseFormView, SingleTableView):
solution = form.instance
solution.team = self.request.user.team
solution.final = solution.team.selected_for_final
if datetime.now() > solution.tournament.date_solutions:
form.add_error('file', _("You can't publish your solution anymore. Deadline: {date:%m-%d-%Y %h:%M}.")
.format(date=solution.tournament.date_solutions))
return super().form_invalid(form)
prev_sol = Solution.objects.filter(problem=solution.problem, team=solution.team, final=solution.final)
for sol in prev_sol.all():
sol.delete()
alphabet = "0123456789abcdefghijklmnopqrstuvwxyz0123456789"
id = ""
for _ in range(64):
for i in range(64):
id += random.choice(alphabet)
solution.file.name = id
solution.save()
@ -302,13 +326,26 @@ class SynthesesView(TeamMixin, BaseFormView, SingleTableView):
synthesis = form.instance
synthesis.team = self.request.user.team
synthesis.final = synthesis.team.selected_for_final
if synthesis.round == '1' and datetime.now() > synthesis.tournament.date_syntheses:
form.add_error('file', _("You can't publish your synthesis anymore for the first round."
" Deadline: {date:%m-%d-%Y %h:%M}.")
.format(date=synthesis.tournament.date_syntheses))
return super().form_invalid(form)
if synthesis.round == '2' and datetime.now() > synthesis.tournament.date_syntheses_2:
form.add_error('file', _("You can't publish your synthesis anymore for the second round."
" Deadline: {date:%m-%d-%Y %h:%M}.")
.format(date=synthesis.tournament.date_syntheses_2))
return super().form_invalid(form)
prev_syn = Synthesis.objects.filter(team=synthesis.team, round=synthesis.round, source=synthesis.source,
final=synthesis.final)
for syn in prev_syn.all():
syn.delete()
alphabet = "0123456789abcdefghijklmnopqrstuvwxyz0123456789"
id = ""
for _ in range(64):
for i in range(64):
id += random.choice(alphabet)
synthesis.file.name = id
synthesis.save()