From 38ceef7a549b159bdbc533bed26db0b6553ce39f Mon Sep 17 00:00:00 2001 From: Emmy D'Anello Date: Fri, 7 Jun 2024 15:48:52 +0200 Subject: [PATCH] Adapt platform to have 3 rounds (untested) Signed-off-by: Emmy D'Anello --- draw/consumers.py | 86 +-- draw/static/tfjm/js/draw.js | 12 +- locale/fr/LC_MESSAGES/django.po | 522 +++++++++--------- participation/api/serializers.py | 1 + participation/api/views.py | 1 + participation/forms.py | 11 +- ...olutions_available_third_phase_and_more.py | 42 ++ participation/models.py | 59 +- .../participation/tournament_detail.html | 8 +- 9 files changed, 440 insertions(+), 302 deletions(-) create mode 100644 participation/migrations/0015_tournament_solutions_available_third_phase_and_more.py diff --git a/draw/consumers.py b/draw/consumers.py index f5b82cc..a62f164 100644 --- a/draw/consumers.py +++ b/draw/consumers.py @@ -183,7 +183,7 @@ class DrawConsumer(AsyncJsonWebsocketConsumer): # Create the draw draw = await Draw.objects.acreate(tournament=self.tournament) r1 = None - for i in [1, 2]: + for i in range(1, settings.NB_ROUNDS + 1): # Create the round r = await Round.objects.acreate(draw=draw, number=i) if i == 1: @@ -532,17 +532,17 @@ class DrawConsumer(AsyncJsonWebsocketConsumer): 'visible': True}) # First send the second pool to have the good team order - r2 = await self.tournament.draw.round_set.filter(number=2).aget() - await self.channel_layer.group_send(f"tournament-{self.tournament.id}", - {'tid': self.tournament_id, 'type': 'draw.send_poules', - 'round': r2.number, - 'poules': [ - { - 'letter': pool.get_letter_display(), - 'teams': await pool.atrigrams(), - } - async for pool in r2.pool_set.order_by('letter').all() - ]}) + for r in self.tournament.draw.round_set.filter(number__gte=2).all(): + await self.channel_layer.group_send(f"tournament-{self.tournament.id}", + {'tid': self.tournament_id, 'type': 'draw.send_poules', + 'round': r.number, + 'poules': [ + { + 'letter': pool.get_letter_display(), + 'teams': await pool.atrigrams(), + } + async for pool in r.pool_set.order_by('letter').all() + ]}) await self.channel_layer.group_send(f"tournament-{self.tournament.id}", {'tid': self.tournament_id, 'type': 'draw.send_poules', 'round': r.number, @@ -843,11 +843,11 @@ class DrawConsumer(AsyncJsonWebsocketConsumer): """ msg = self.tournament.draw.last_message - if r.number == 1 and not self.tournament.final: + if r.number < settings.NB_ROUNDS and not self.tournament.final: # Next round - r2 = await self.tournament.draw.round_set.filter(number=2).aget() - self.tournament.draw.current_round = r2 - msg += "

Le tirage au sort du tour 1 est terminé." + next_round = await self.tournament.draw.round_set.filter(number=r.number + 1).aget() + self.tournament.draw.current_round = next_round + msg += f"

Le tirage au sort du tour {r.number} est terminé." self.tournament.draw.last_message = msg await self.tournament.draw.asave() @@ -866,20 +866,20 @@ class DrawConsumer(AsyncJsonWebsocketConsumer): # Reorder dices await self.channel_layer.group_send(f"tournament-{self.tournament.id}", {'tid': self.tournament_id, 'type': 'draw.send_poules', - 'round': r2.number, + 'round': next_round.number, 'poules': [ { 'letter': pool.get_letter_display(), 'teams': await pool.atrigrams(), } - async for pool in r2.pool_set.order_by('letter').all() + async for pool in next_round.pool_set.order_by('letter').all() ]}) # The passage order for the second round is already determined by the first round # Start the first pool of the second round - p1: Pool = await r2.pool_set.filter(letter=1).aget() - r2.current_pool = p1 - await r2.asave() + p1: Pool = await next_round.pool_set.filter(letter=1).aget() + next_round.current_pool = p1 + await next_round.asave() async for td in p1.teamdraw_set.prefetch_related('participation__team').all(): await self.channel_layer.group_send(f"team-{td.participation.team.trigram}", @@ -1372,32 +1372,36 @@ class DrawConsumer(AsyncJsonWebsocketConsumer): 'round': r.number, 'team': td.participation.team.trigram, 'problem': td.accepted}) - elif r.number == 2: + elif r.number >= 2: if not self.tournament.final: # Go to the previous round - r1 = await self.tournament.draw.round_set \ - .prefetch_related('current_pool__current_team__participation__team').aget(number=1) - self.tournament.draw.current_round = r1 + previous_round = await self.tournament.draw.round_set \ + .prefetch_related('current_pool__current_team__participation__team').aget(number=r.number - 1) + self.tournament.draw.current_round = previous_round await self.tournament.draw.asave() - async for td in r1.team_draws.prefetch_related('participation__team').all(): + async for td in previous_round.team_draws.prefetch_related('participation__team').all(): await self.channel_layer.group_send( f"tournament-{self.tournament.id}", {'tid': self.tournament_id, 'type': 'draw.dice', 'team': td.participation.team.trigram, 'result': td.choice_dice}) - await self.channel_layer.group_send(f"tournament-{self.tournament.id}", - {'tid': self.tournament_id, 'type': 'draw.send_poules', - 'round': r1.number, - 'poules': [ - { - 'letter': pool.get_letter_display(), - 'teams': await pool.atrigrams(), - } - async for pool in r1.pool_set.order_by('letter').all() - ]}) + await self.channel_layer.group_send( + f"tournament-{self.tournament.id}", + { + 'tid': self.tournament_id, + 'type': 'draw.send_poules', + 'round': previous_round.number, + 'poules': [ + { + 'letter': pool.get_letter_display(), + 'teams': await pool.atrigrams(), + } + async for pool in previous_round.pool_set.order_by('letter').all() + ] + }) - previous_pool = r1.current_pool + previous_pool = previous_round.current_pool td = previous_pool.current_team td.purposed = td.accepted @@ -1417,14 +1421,14 @@ class DrawConsumer(AsyncJsonWebsocketConsumer): await self.channel_layer.group_send(f"tournament-{self.tournament.id}", {'tid': self.tournament_id, 'type': 'draw.set_problem', - 'round': r1.number, + 'round': previous_round.number, 'team': td.participation.team.trigram, 'problem': td.accepted}) else: # Don't continue the final tournament - r1 = await self.tournament.draw.round_set \ + previous_round = await self.tournament.draw.round_set \ .prefetch_related('current_pool__current_team__participation__team').aget(number=1) - self.tournament.draw.current_round = r1 + self.tournament.draw.current_round = previous_round await self.tournament.draw.asave() async for td in r.teamdraw_set.all(): @@ -1446,7 +1450,7 @@ class DrawConsumer(AsyncJsonWebsocketConsumer): ] }) - async for td in r1.team_draws.prefetch_related('participation__team').all(): + async for td in previous_round.team_draws.prefetch_related('participation__team').all(): await self.channel_layer.group_send( f"tournament-{self.tournament.id}", {'tid': self.tournament_id, 'type': 'draw.dice', 'team': td.participation.team.trigram, diff --git a/draw/static/tfjm/js/draw.js b/draw/static/tfjm/js/draw.js index ea0075d..34310ae 100644 --- a/draw/static/tfjm/js/draw.js +++ b/draw/static/tfjm/js/draw.js @@ -311,7 +311,7 @@ document.addEventListener('DOMContentLoaded', () => { /** * Set the different pools for the given round, and update the interface. * @param tid The tournament id - * @param round The round number, as integer (1 or 2) + * @param round The round number, as integer (1 or 2, or 3 for ETEAM) * @param poules The list of poules, which are represented with their letters and trigrams, * [{'letter': 'A', 'teams': ['ABC', 'DEF', 'GHI']}] */ @@ -433,7 +433,7 @@ document.addEventListener('DOMContentLoaded', () => { /** * Update the table for the given round and the given pool, where there will be the chosen problems. * @param tid The tournament id - * @param round The round number, as integer (1 or 2) + * @param round The round number, as integer (1 or 2, or 3 for ETEAM) * @param poule The current pool, which id represented with its letter and trigrams, * {'letter': 'A', 'teams': ['ABC', 'DEF', 'GHI']} */ @@ -590,7 +590,7 @@ document.addEventListener('DOMContentLoaded', () => { /** * Highlight the team that is currently choosing its problem. * @param tid The tournament id - * @param round The current round number, as integer (1 or 2) + * @param round The current round number, as integer (1 or 2, or 3 for ETEAM) * @param pool The current pool letter (A, B, C or D) (null if non-relevant) * @param team The current team trigram (null if non-relevant) */ @@ -627,7 +627,7 @@ document.addEventListener('DOMContentLoaded', () => { /** * Update the recap and the table when a team accepts a problem. * @param tid The tournament id - * @param round The current round, as integer (1 or 2) + * @param round The current round, as integer (1 or 2, or 3 for ETEAM) * @param team The current team trigram * @param problem The accepted problem, as integer */ @@ -651,7 +651,7 @@ document.addEventListener('DOMContentLoaded', () => { /** * Update the recap when a team rejects a problem. * @param tid The tournament id - * @param round The current round, as integer (1 or 2) + * @param round The current round, as integer (1 or 2, or 3 for ETEAM) * @param team The current team trigram * @param rejected The full list of rejected problems */ @@ -682,7 +682,7 @@ document.addEventListener('DOMContentLoaded', () => { * For a 5-teams pool, we may reorder the pool if two teams select the same problem. * Then, we redraw the table and set the accepted problems. * @param tid The tournament id - * @param round The current round, as integer (1 or 2) + * @param round The current round, as integer (1 or 2, or 3 for ETEAM) * @param poule The pool represented by its letter * @param teams The teams list represented by their trigrams, ["ABC", "DEF", "GHI", "JKL", "MNO"] * @param problems The accepted problems in the same order than the teams, [1, 1, 2, 2, 3] diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 2f08fb6..6712a7b 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: TFJM\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-06-07 14:45+0200\n" +"POT-Creation-Date: 2024-06-07 15:49+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Emmy D'Anello \n" "Language-Team: LANGUAGE \n" @@ -78,8 +78,8 @@ msgstr "Type de permission nécessaire pour écrire un message dans un canal." #: chat/models.py:62 draw/admin.py:53 draw/admin.py:71 draw/admin.py:88 #: draw/models.py:26 participation/admin.py:79 participation/admin.py:140 -#: participation/admin.py:171 participation/models.py:694 -#: participation/models.py:718 participation/models.py:936 +#: participation/admin.py:171 participation/models.py:704 +#: participation/models.py:728 participation/models.py:989 #: registration/models.py:762 #: registration/templates/registration/payment_form.html:53 msgid "tournament" @@ -95,7 +95,7 @@ msgstr "" #: chat/models.py:73 draw/models.py:429 draw/models.py:456 #: participation/admin.py:136 participation/admin.py:155 -#: participation/models.py:1439 participation/models.py:1448 +#: participation/models.py:1492 participation/models.py:1501 #: participation/tables.py:84 msgid "pool" msgstr "poule" @@ -109,7 +109,7 @@ msgstr "" #: chat/models.py:84 draw/templates/draw/tournament_content.html:277 #: participation/admin.py:167 participation/models.py:253 -#: participation/models.py:709 +#: participation/models.py:719 #: participation/templates/participation/tournament_harmonize.html:15 #: registration/models.py:157 registration/models.py:753 #: registration/tables.py:39 @@ -217,7 +217,7 @@ msgstr "" msgid "Toggle fullscreen mode" msgstr "Inverse le mode plein écran" -#: chat/templates/chat/content.html:76 tfjm/templates/navbar.html:119 +#: chat/templates/chat/content.html:76 tfjm/templates/navbar.html:125 msgid "Log out" msgstr "Déconnexion" @@ -241,15 +241,15 @@ msgstr "Chat du TFJM²" #: chat/templates/chat/login.html:10 chat/templates/chat/login.html:29 #: registration/templates/registration/password_reset_complete.html:10 -#: tfjm/templates/base.html:81 tfjm/templates/base.html:82 -#: tfjm/templates/navbar.html:100 +#: tfjm/templates/base.html:82 tfjm/templates/base.html:83 +#: tfjm/templates/navbar.html:106 #: tfjm/templates/registration/includes/login.html:22 #: tfjm/templates/registration/login.html:7 #: tfjm/templates/registration/login.html:8 msgid "Log in" msgstr "Connexion" -#: chat/urls.py:13 tfjm/templates/navbar.html:68 +#: chat/urls.py:13 tfjm/templates/navbar.html:74 msgid "Chat" msgstr "Chat" @@ -260,11 +260,11 @@ msgid "teams" msgstr "équipes" #: draw/admin.py:92 draw/models.py:234 draw/models.py:448 -#: participation/models.py:940 +#: participation/models.py:993 msgid "round" msgstr "tour" -#: draw/apps.py:10 tfjm/templates/navbar.html:62 +#: draw/apps.py:10 tfjm/templates/navbar.html:68 msgid "Draw" msgstr "Tirage au sort" @@ -402,7 +402,7 @@ msgstr "La poule en cours, où les équipes choisissent leurs problèmes" msgid "rounds" msgstr "tours" -#: draw/models.py:257 participation/models.py:948 +#: draw/models.py:257 participation/models.py:1001 msgid "letter" msgstr "lettre" @@ -440,12 +440,12 @@ msgstr "L'instance complète de la poule." msgid "Pool {letter}{number}" msgstr "Poule {letter}{number}" -#: draw/models.py:430 participation/models.py:1440 +#: draw/models.py:430 participation/models.py:1493 msgid "pools" msgstr "poules" -#: draw/models.py:442 participation/models.py:926 participation/models.py:1589 -#: participation/models.py:1619 participation/models.py:1661 +#: draw/models.py:442 participation/models.py:979 participation/models.py:1642 +#: participation/models.py:1672 participation/models.py:1714 msgid "participation" msgstr "participation" @@ -469,8 +469,8 @@ msgid "" msgstr "" "L'ordre de choix dans la poule, entre 0 et la taille de la poule moins 1." -#: draw/models.py:479 draw/models.py:502 participation/models.py:1462 -#: participation/models.py:1626 +#: draw/models.py:479 draw/models.py:502 participation/models.py:1515 +#: participation/models.py:1679 #, python-brace-format msgid "Problem #{problem}" msgstr "Problème n°{problem}" @@ -681,98 +681,98 @@ msgstr "Changelog de type \"{action}\" pour le modèle {model} le {timestamp}" msgid "valid" msgstr "valide" -#: participation/admin.py:87 participation/models.py:730 +#: participation/admin.py:87 participation/models.py:740 msgid "selected for final" msgstr "sélectionnée pour la finale" #: participation/admin.py:124 participation/admin.py:183 -#: participation/models.py:1469 participation/tables.py:112 +#: participation/models.py:1522 participation/tables.py:112 msgid "defender" msgstr "défenseur⋅se" -#: participation/admin.py:128 participation/models.py:1476 -#: participation/models.py:1673 +#: participation/admin.py:128 participation/models.py:1529 +#: participation/models.py:1726 msgid "opponent" msgstr "opposant⋅e" -#: participation/admin.py:132 participation/models.py:1483 -#: participation/models.py:1674 +#: participation/admin.py:132 participation/models.py:1536 +#: participation/models.py:1727 msgid "reporter" msgstr "rapporteur⋅rice" -#: participation/admin.py:187 participation/models.py:1624 +#: participation/admin.py:187 participation/models.py:1677 msgid "problem" msgstr "numéro de problème" -#: participation/forms.py:29 +#: participation/forms.py:30 msgid "This name is already used." msgstr "Ce nom est déjà utilisé." -#: participation/forms.py:36 +#: participation/forms.py:37 msgid "The trigram must be composed of three uppercase letters." msgstr "Le trigramme doit être composé de trois lettres majuscules." -#: participation/forms.py:39 +#: participation/forms.py:40 msgid "This trigram is already used." msgstr "Ce trigramme est déjà utilisé." -#: participation/forms.py:54 +#: participation/forms.py:55 msgid "No team was found with this access code." msgstr "Aucune équipe n'a été trouvée avec ce code d'accès." -#: participation/forms.py:58 participation/views.py:506 +#: participation/forms.py:59 participation/views.py:506 msgid "The team is already validated or the validation is pending." msgstr "La validation de l'équipe est déjà faite ou en cours." -#: participation/forms.py:87 participation/forms.py:347 -#: registration/forms.py:122 registration/forms.py:144 -#: registration/forms.py:166 registration/forms.py:188 -#: registration/forms.py:210 registration/forms.py:232 -#: registration/forms.py:281 registration/forms.py:314 +#: participation/forms.py:88 participation/forms.py:354 +#: registration/forms.py:123 registration/forms.py:145 +#: registration/forms.py:167 registration/forms.py:189 +#: registration/forms.py:211 registration/forms.py:233 +#: registration/forms.py:282 registration/forms.py:315 msgid "The uploaded file size must be under 2 Mo." msgstr "Le fichier envoyé doit peser moins de 2 Mo." -#: participation/forms.py:89 registration/forms.py:124 -#: registration/forms.py:146 registration/forms.py:168 -#: registration/forms.py:190 registration/forms.py:212 -#: registration/forms.py:234 registration/forms.py:283 -#: registration/forms.py:316 +#: participation/forms.py:90 registration/forms.py:125 +#: registration/forms.py:147 registration/forms.py:169 +#: registration/forms.py:191 registration/forms.py:213 +#: registration/forms.py:235 registration/forms.py:284 +#: registration/forms.py:317 msgid "The uploaded file must be a PDF, PNG of JPEG file." msgstr "Le fichier envoyé doit être au format PDF, PNG ou JPEG." -#: participation/forms.py:107 +#: participation/forms.py:108 msgid "I engage myself to participate to the whole TFJM²." msgstr "Je m'engage à participer à l'intégralité du TFJM²." -#: participation/forms.py:122 +#: participation/forms.py:123 msgid "Message to address to the team:" msgstr "Message à adresser à l'équipe :" -#: participation/forms.py:157 +#: participation/forms.py:164 msgid "The uploaded file size must be under 5 Mo." msgstr "Le fichier envoyé doit peser moins de 5 Mo." -#: participation/forms.py:159 participation/forms.py:349 +#: participation/forms.py:166 participation/forms.py:356 msgid "The uploaded file must be a PDF file." msgstr "Le fichier envoyé doit être au format PDF." -#: participation/forms.py:163 +#: participation/forms.py:170 msgid "The PDF file must not have more than 30 pages." msgstr "Le fichier PDF ne doit pas avoir plus de 30 pages." -#: participation/forms.py:217 +#: participation/forms.py:224 msgid "Add" msgstr "Ajouter" -#: participation/forms.py:232 +#: participation/forms.py:239 msgid "This user already exists, but is a participant." msgstr "Cet⋅te utilisateur⋅rice existe déjà, mais en tant que participant⋅e." -#: participation/forms.py:243 +#: participation/forms.py:250 msgid "Spreadsheet file:" msgstr "Fichier tableur :" -#: participation/forms.py:269 +#: participation/forms.py:276 msgid "" "This file contains non-UTF-8 and non-ISO-8859-1 content. Please send your " "sheet as a CSV file." @@ -780,24 +780,24 @@ msgstr "" "Ce fichier contient des éléments non-UTF-8 et non-ISO-8859-1. Merci " "d'envoyer votre tableur au format CSV." -#: participation/forms.py:308 +#: participation/forms.py:315 msgid "The following note is higher of the maximum expected value:" msgstr "La note suivante est supérieure au maximum attendu :" -#: participation/forms.py:314 +#: participation/forms.py:321 msgid "The following user was not found:" msgstr "L'utilisateur⋅rice suivant n'a pas été trouvé :" -#: participation/forms.py:330 +#: participation/forms.py:337 msgid "The defender, the opponent and the reporter must be different." msgstr "" "Les équipes défenseuse, opposante et rapportrice doivent être différent⋅es." -#: participation/forms.py:334 +#: participation/forms.py:341 msgid "This defender did not work on this problem." msgstr "Ce⋅tte défenseur⋅se ne travaille pas sur ce problème." -#: participation/forms.py:353 +#: participation/forms.py:360 msgid "The PDF file must not have more than 2 pages." msgstr "Le fichier PDF ne doit pas avoir plus de 2 pages." @@ -996,62 +996,70 @@ msgid "limit date to upload the syntheses for the first phase" msgstr "date limite pour envoyer les notes de synthèses pour la première phase" #: participation/models.py:319 -msgid "date when the solutions for the second round become available" -msgstr "date à laquelle les solutions pour le second tour sont accessibles" +msgid "check this case when solutions for the second round become available" +msgstr "cocher la case lorsque les solutions pour le second tour sont accessibles" #: participation/models.py:324 msgid "limit date to upload the syntheses for the second phase" msgstr "date limite d'envoi des notes de synthèse pour la seconde phase" #: participation/models.py:329 -#: participation/templates/participation/tournament_detail.html:48 +msgid "check this case when solutions for the third round become available" +msgstr "cocher la case lorsque les solutions pour le second tour sont accessibles" + +#: participation/models.py:334 +msgid "limit date to upload the syntheses for the third phase" +msgstr "date limite pour envoyer les notes de synthèses pour la troisième phase" + +#: participation/models.py:339 +#: participation/templates/participation/tournament_detail.html:50 msgid "description" msgstr "description" -#: participation/models.py:335 +#: participation/models.py:345 #: participation/templates/participation/tournament_detail.html:12 msgid "organizers" msgstr "organisateur⋅rices" -#: participation/models.py:340 +#: participation/models.py:350 #: participation/templates/participation/team_detail.html:161 msgid "final" msgstr "finale" -#: participation/models.py:348 +#: participation/models.py:358 msgid "Google Sheet ID" msgstr "ID de la feuille Google Sheets" -#: participation/models.py:695 registration/admin.py:125 +#: participation/models.py:705 registration/admin.py:125 msgid "tournaments" msgstr "tournois" -#: participation/models.py:724 +#: participation/models.py:734 msgid "valid team" msgstr "équipe valide" -#: participation/models.py:725 +#: participation/models.py:735 msgid "The participation got the validation of the organizers." msgstr "La participation a été validée par les organisateur⋅rices." -#: participation/models.py:731 +#: participation/models.py:741 msgid "The team is selected for the final tournament." msgstr "L'équipe est sélectionnée pour la finale." -#: participation/models.py:735 +#: participation/models.py:745 msgid "mention" msgstr "mention" -#: participation/models.py:742 +#: participation/models.py:752 msgid "mention (final)" msgstr "Mention (pour la finale) :" -#: participation/models.py:752 +#: participation/models.py:762 #, python-brace-format msgid "Participation of the team {name} ({trigram})" msgstr "Participation de l'équipe {name} ({trigram})" -#: participation/models.py:759 +#: participation/models.py:769 #, python-brace-format msgid "" "

The team {trigram} has {nb_missing_payments} missing payments. Each " @@ -1064,11 +1072,11 @@ msgstr "" "notification de bourse) pour participer au tournoi.

Les participant⋅es " "qui n'ont pas encore payé sont : {participants}.

" -#: participation/models.py:767 +#: participation/models.py:777 msgid "Missing payments" msgstr "Paiements manquants" -#: participation/models.py:784 +#: participation/models.py:794 msgid "" "

The solutions for the tournament of {tournament} are due on the {date:%Y-" "%m-%d %H:%M}.

You have currently sent {nb_solutions} " @@ -1083,11 +1091,11 @@ msgstr "" "pouvez envoyer vos solutions sur votre page de " "participation.

" -#: participation/models.py:794 participation/models.py:808 +#: participation/models.py:804 participation/models.py:818 msgid "Solutions due" msgstr "Rendu des solutions" -#: participation/models.py:800 +#: participation/models.py:810 msgid "" "

The solutions for the tournament of {tournament} are due on the {date:%Y-" "%m-%d %H:%M}.

Remember that you can only fix minor changes to your " @@ -1100,7 +1108,7 @@ msgstr "" "parties.

Vous pouvez envoyer vos solutions sur votre " "page de participation.

" -#: participation/models.py:814 registration/models.py:606 +#: participation/models.py:824 registration/models.py:606 msgid "" "

The draw of the solutions for the tournament {tournament} is planned on " "the {date:%Y-%m-%d %H:%M}. You can join it on this link." @@ -1110,11 +1118,11 @@ msgstr "" "{date:%d/%m/%Y %H:%M}. Vous pouvez y participer sur ce lien.

" -#: participation/models.py:820 registration/models.py:613 +#: participation/models.py:830 registration/models.py:613 msgid "Draw of solutions" msgstr "Tirage au sort des solutions" -#: participation/models.py:830 +#: participation/models.py:840 #, python-brace-format msgid "" "

The solutions draw is ended. You can check the result on votre solution du problème " "{problem}.

" -#: participation/models.py:839 participation/models.py:881 +#: participation/models.py:849 participation/models.py:891 +#: participation/models.py:934 #, python-brace-format msgid "" "

You will oppose the solution of the team {opponent} on the problème {problem}. Vous pouvez envoyer votre note " "de synthèse sur cette page.

" -#: participation/models.py:848 participation/models.py:890 +#: participation/models.py:858 participation/models.py:900 +#: participation/models.py:943 #, python-brace-format msgid "" "

You will report the solution of the team {reporter} on the problème {problem}. Vous pouvez envoyer votre note " "de synthèse sur cette page.

" -#: participation/models.py:864 registration/models.py:628 +#: participation/models.py:874 registration/models.py:628 msgid "First round" msgstr "Premier tour" -#: participation/models.py:874 +#: participation/models.py:884 #, python-brace-format msgid "" "

For the second round, you will defend your " @@ -1161,11 +1171,21 @@ msgstr "" "

Pour le second tour, vous défendrez votre " "solution du problème {problem}.

" -#: participation/models.py:906 registration/models.py:639 +#: participation/models.py:916 participation/models.py:959 +#: registration/models.py:639 msgid "Second round" msgstr "Second tour" -#: participation/models.py:912 +#: participation/models.py:927 +#, python-brace-format +msgid "" +"

For the third round, you will defend your " +"solution of the problem {problem}.

" +msgstr "" +"

Pour le troisième tour, vous défendrez votre " +"solution du problème {problem}.

" + +#: participation/models.py:965 #, python-brace-format msgid "" "

The tournament {tournament} is ended. You can check the results on the Le tournoi {tournament} est terminé. Vous pouvez consulter les résultats " "sur la page du tournoi.

" -#: participation/models.py:917 +#: participation/models.py:970 msgid "Tournament ended" msgstr "Tournoi terminé" -#: participation/models.py:927 participation/models.py:970 +#: participation/models.py:980 participation/models.py:1023 msgid "participations" msgstr "participations" -#: participation/models.py:942 participation/models.py:943 -#: participation/models.py:944 +#: participation/models.py:995 participation/models.py:996 +#: participation/models.py:997 #, python-brace-format msgid "Round {round}" msgstr "Tour {round}" -#: participation/models.py:958 +#: participation/models.py:1011 msgid "room" msgstr "salle" -#: participation/models.py:960 +#: participation/models.py:1013 msgid "Room 1" msgstr "Salle 1" -#: participation/models.py:961 +#: participation/models.py:1014 msgid "Room 2" msgstr "Salle 2" -#: participation/models.py:964 +#: participation/models.py:1017 msgid "For 5-teams pools only" msgstr "Pour les poules de 5 équipe uniquement" -#: participation/models.py:976 +#: participation/models.py:1029 msgid "juries" msgstr "jurys" -#: participation/models.py:985 +#: participation/models.py:1038 msgid "president of the jury" msgstr "président⋅e du jury" -#: participation/models.py:992 +#: participation/models.py:1045 msgid "BigBlueButton URL" msgstr "Lien BigBlueButton" -#: participation/models.py:993 +#: participation/models.py:1046 msgid "The link of the BBB visio for this pool." msgstr "Le lien du salon BBB pour cette poule." -#: participation/models.py:998 +#: participation/models.py:1051 msgid "results available" msgstr "résultats disponibles" -#: participation/models.py:999 +#: participation/models.py:1052 msgid "" "Check this case when results become accessible to teams. They stay " "accessible to you. Only averages are given." @@ -1233,33 +1253,33 @@ msgstr "" "Ils restent toujours accessibles pour vous. Seules les moyennes sont " "communiquées." -#: participation/models.py:1031 +#: participation/models.py:1084 msgid "The president of the jury must be part of the jury." msgstr "Læ président⋅e du jury doit faire partie du jury." -#: participation/models.py:1420 +#: participation/models.py:1473 #, python-brace-format msgid "The jury {jury} is not part of the jury for this pool." msgstr "{jury} ne fait pas partie du jury pour cette poule." -#: participation/models.py:1433 +#: participation/models.py:1486 #, python-brace-format msgid "Pool {code} for tournament {tournament} with teams {teams}" msgstr "Poule {code} du tournoi {tournament} avec les équipes {teams}" -#: participation/models.py:1453 +#: participation/models.py:1506 msgid "position" msgstr "position" -#: participation/models.py:1460 +#: participation/models.py:1513 msgid "defended solution" msgstr "solution défendue" -#: participation/models.py:1488 +#: participation/models.py:1541 msgid "penalties" msgstr "pénalités" -#: participation/models.py:1490 +#: participation/models.py:1543 msgid "" "Number of penalties for the defender. The defender will loose a 0.5 " "coefficient per penalty." @@ -1267,120 +1287,120 @@ msgstr "" "Nombre de pénalités pour l'équipe défenseuse. Elle perd un coefficient 0.5 " "sur sa présentation orale par pénalité." -#: participation/models.py:1559 participation/models.py:1562 -#: participation/models.py:1565 +#: participation/models.py:1612 participation/models.py:1615 +#: participation/models.py:1618 #, python-brace-format msgid "Team {trigram} is not registered in the pool." msgstr "L'équipe {trigram} n'est pas inscrite dans la poule." -#: participation/models.py:1570 +#: participation/models.py:1623 #, python-brace-format msgid "Passage of {defender} for problem {problem}" msgstr "Passage de {defender} pour le problème {problem}" -#: participation/models.py:1574 participation/models.py:1583 -#: participation/models.py:1668 participation/models.py:1710 +#: participation/models.py:1627 participation/models.py:1636 +#: participation/models.py:1721 participation/models.py:1763 msgid "passage" msgstr "passage" -#: participation/models.py:1575 +#: participation/models.py:1628 msgid "passages" msgstr "passages" -#: participation/models.py:1594 +#: participation/models.py:1647 msgid "difference" msgstr "différence" -#: participation/models.py:1595 +#: participation/models.py:1648 msgid "Score to add/remove on the final score" msgstr "Score à ajouter/retrancher au score final" -#: participation/models.py:1602 +#: participation/models.py:1655 msgid "tweak" msgstr "harmonisation" -#: participation/models.py:1603 +#: participation/models.py:1656 msgid "tweaks" msgstr "harmonisations" -#: participation/models.py:1631 +#: participation/models.py:1684 msgid "solution for the final tournament" msgstr "solution pour la finale" -#: participation/models.py:1636 participation/models.py:1679 +#: participation/models.py:1689 participation/models.py:1732 msgid "file" msgstr "fichier" -#: participation/models.py:1646 +#: participation/models.py:1699 #, python-brace-format msgid "Solution of team {team} for problem {problem}" msgstr "Solution de l'équipe {team} pour le problème {problem}" -#: participation/models.py:1648 +#: participation/models.py:1701 msgid "for final" msgstr "pour la finale" -#: participation/models.py:1651 +#: participation/models.py:1704 msgid "solution" msgstr "solution" -#: participation/models.py:1652 +#: participation/models.py:1705 msgid "solutions" msgstr "solutions" -#: participation/models.py:1685 +#: participation/models.py:1738 #, python-brace-format msgid "Synthesis of {team} as {type} for problem {problem} of {defender}" msgstr "" "Note de synthèse de l'équipe {team} en tant que {type} pour le problème " "{problem} de {defender}" -#: participation/models.py:1693 +#: participation/models.py:1746 msgid "synthesis" msgstr "note de synthèse" -#: participation/models.py:1694 +#: participation/models.py:1747 msgid "syntheses" msgstr "notes de synthèse" -#: participation/models.py:1703 +#: participation/models.py:1756 msgid "jury" msgstr "jury" -#: participation/models.py:1715 +#: participation/models.py:1768 msgid "defender writing note" msgstr "note d'écrit défenseur⋅se" -#: participation/models.py:1721 +#: participation/models.py:1774 msgid "defender oral note" msgstr "note d'oral défenseur⋅se" -#: participation/models.py:1727 +#: participation/models.py:1780 msgid "opponent writing note" msgstr "note d'écrit opposant⋅e" -#: participation/models.py:1733 +#: participation/models.py:1786 msgid "opponent oral note" msgstr "note d'oral opposant⋅e" -#: participation/models.py:1739 +#: participation/models.py:1792 msgid "reporter writing note" msgstr "note d'écrit rapporteur⋅rice" -#: participation/models.py:1745 +#: participation/models.py:1798 msgid "reporter oral note" msgstr "note d'oral du rapporteur⋅rice" -#: participation/models.py:1805 +#: participation/models.py:1858 #, python-brace-format msgid "Notes of {jury} for {passage}" msgstr "Notes de {jury} pour le {passage}" -#: participation/models.py:1808 +#: participation/models.py:1861 msgid "note" msgstr "note" -#: participation/models.py:1809 +#: participation/models.py:1862 msgid "notes" msgstr "notes" @@ -1432,18 +1452,18 @@ msgstr "Pas d'équipe définie" #: registration/tables.py:46 #: registration/templates/registration/payment_form.html:210 #: registration/templates/registration/update_user.html:16 -#: registration/templates/registration/user_detail.html:211 +#: registration/templates/registration/user_detail.html:214 msgid "Update" msgstr "Modifier" #: participation/templates/participation/create_team.html:11 #: participation/templates/participation/tournament_form.html:14 -#: tfjm/templates/base.html:77 +#: tfjm/templates/base.html:78 msgid "Create" msgstr "Créer" #: participation/templates/participation/join_team.html:11 -#: tfjm/templates/base.html:72 +#: tfjm/templates/base.html:73 msgid "Join" msgstr "Rejoindre" @@ -1521,12 +1541,12 @@ msgstr "Envoyer une solution" #: registration/templates/registration/upload_parental_authorization.html:17 #: registration/templates/registration/upload_photo_authorization.html:18 #: registration/templates/registration/upload_vaccine_sheet.html:13 -#: registration/templates/registration/user_detail.html:221 -#: registration/templates/registration/user_detail.html:227 -#: registration/templates/registration/user_detail.html:232 -#: registration/templates/registration/user_detail.html:237 -#: registration/templates/registration/user_detail.html:245 -#: registration/templates/registration/user_detail.html:251 +#: registration/templates/registration/user_detail.html:224 +#: registration/templates/registration/user_detail.html:230 +#: registration/templates/registration/user_detail.html:235 +#: registration/templates/registration/user_detail.html:240 +#: registration/templates/registration/user_detail.html:248 +#: registration/templates/registration/user_detail.html:254 msgid "Upload" msgstr "Téléverser" @@ -1685,7 +1705,7 @@ msgid "Go to the Google Sheets page of the pool" msgstr "Aller à la page Google Sheets de la poule" #: participation/templates/participation/pool_detail.html:116 -#: participation/templates/participation/tournament_detail.html:101 +#: participation/templates/participation/tournament_detail.html:103 #: participation/templates/participation/tournament_harmonize.html:8 msgid "Ranking" msgstr "Classement" @@ -1817,22 +1837,22 @@ msgstr "Lettre de motivation :" #: registration/templates/registration/payment_form.html:269 #: registration/templates/registration/upload_health_sheet.html:12 #: registration/templates/registration/upload_parental_authorization.html:12 -#: registration/templates/registration/user_detail.html:69 -#: registration/templates/registration/user_detail.html:80 -#: registration/templates/registration/user_detail.html:92 -#: registration/templates/registration/user_detail.html:102 -#: registration/templates/registration/user_detail.html:112 -#: registration/templates/registration/user_detail.html:123 +#: registration/templates/registration/user_detail.html:72 +#: registration/templates/registration/user_detail.html:83 +#: registration/templates/registration/user_detail.html:95 +#: registration/templates/registration/user_detail.html:105 +#: registration/templates/registration/user_detail.html:115 +#: registration/templates/registration/user_detail.html:126 msgid "Download" msgstr "Télécharger" #: participation/templates/participation/team_detail.html:140 -#: registration/templates/registration/user_detail.html:72 -#: registration/templates/registration/user_detail.html:82 -#: registration/templates/registration/user_detail.html:95 -#: registration/templates/registration/user_detail.html:105 -#: registration/templates/registration/user_detail.html:115 -#: registration/templates/registration/user_detail.html:125 +#: registration/templates/registration/user_detail.html:75 +#: registration/templates/registration/user_detail.html:85 +#: registration/templates/registration/user_detail.html:98 +#: registration/templates/registration/user_detail.html:108 +#: registration/templates/registration/user_detail.html:118 +#: registration/templates/registration/user_detail.html:128 msgid "Replace" msgstr "Remplacer" @@ -1850,7 +1870,7 @@ msgid "grouped" msgstr "groupé" #: participation/templates/participation/team_detail.html:168 -#: registration/templates/registration/user_detail.html:188 +#: registration/templates/registration/user_detail.html:191 #: registration/views.py:490 msgid "Update payment" msgstr "Mettre à jour le paiement" @@ -1968,78 +1988,77 @@ msgid "date of maximal syntheses submission for the first round" msgstr "date limite de soumission des notes de synthèse pour le premier tour" #: participation/templates/participation/tournament_detail.html:42 -msgid "date when solutions of round 2 are available" -msgstr "" -"date à partir de laquelle les solutions pour le second tour sont disponibles" - -#: participation/templates/participation/tournament_detail.html:45 msgid "date of maximal syntheses submission for the second round" msgstr "date limite de soumission des notes de synthèse pour le second tour" -#: participation/templates/participation/tournament_detail.html:51 +#: participation/templates/participation/tournament_detail.html:46 +msgid "date of maximal syntheses submission for the third round" +msgstr "date limite de soumission des notes de synthèse pour le troisième tour" + +#: participation/templates/participation/tournament_detail.html:53 msgid "To contact organizers" msgstr "Pour contacter les organisateur⋅rices" -#: participation/templates/participation/tournament_detail.html:54 +#: participation/templates/participation/tournament_detail.html:56 msgid "To contact juries" msgstr "Pour contacter les juré⋅es" -#: participation/templates/participation/tournament_detail.html:57 +#: participation/templates/participation/tournament_detail.html:59 msgid "To contact valid teams" msgstr "Pour contacter les équipes valides" -#: participation/templates/participation/tournament_detail.html:66 +#: participation/templates/participation/tournament_detail.html:68 msgid "Edit tournament" msgstr "Modifier le tournoi" -#: participation/templates/participation/tournament_detail.html:74 -#: tfjm/templates/navbar.html:31 +#: participation/templates/participation/tournament_detail.html:76 +#: tfjm/templates/navbar.html:37 msgid "Teams" msgstr "Équipes" -#: participation/templates/participation/tournament_detail.html:82 +#: participation/templates/participation/tournament_detail.html:84 msgid "Access to payments list" msgstr "Accéder à la liste des paiements" -#: participation/templates/participation/tournament_detail.html:90 +#: participation/templates/participation/tournament_detail.html:92 msgid "Pools" msgstr "Poules" -#: participation/templates/participation/tournament_detail.html:119 +#: participation/templates/participation/tournament_detail.html:121 msgid "Selected for final tournament" msgstr "Sélectionnée pour la finale" -#: participation/templates/participation/tournament_detail.html:127 +#: participation/templates/participation/tournament_detail.html:129 msgid "Select for final tournament" msgstr "Sélectionner pour la finale" -#: participation/templates/participation/tournament_detail.html:140 -#: participation/templates/participation/tournament_detail.html:144 +#: participation/templates/participation/tournament_detail.html:142 +#: participation/templates/participation/tournament_detail.html:146 msgid "Harmonize" msgstr "Harmoniser" -#: participation/templates/participation/tournament_detail.html:140 -#: participation/templates/participation/tournament_detail.html:144 +#: participation/templates/participation/tournament_detail.html:142 +#: participation/templates/participation/tournament_detail.html:146 msgid "Day" msgstr "Jour" -#: participation/templates/participation/tournament_detail.html:153 +#: participation/templates/participation/tournament_detail.html:155 msgid "Publish notes for first round" msgstr "Publier les notes pour le premier tour" -#: participation/templates/participation/tournament_detail.html:158 +#: participation/templates/participation/tournament_detail.html:160 msgid "Unpublish notes for first round" msgstr "Dépublier les notes pour le premier tour" -#: participation/templates/participation/tournament_detail.html:164 +#: participation/templates/participation/tournament_detail.html:166 msgid "Publish notes for second round" msgstr "Publier les notes pour le second tour" -#: participation/templates/participation/tournament_detail.html:169 +#: participation/templates/participation/tournament_detail.html:171 msgid "Unpublish notes for second round" msgstr "Dépublier les notes pour le second tour" -#: participation/templates/participation/tournament_detail.html:181 +#: participation/templates/participation/tournament_detail.html:183 msgid "Files available for download" msgstr "Fichiers disponibles au téléchargement" @@ -2066,7 +2085,7 @@ msgid "Back to tournament page" msgstr "Retour à la page du tournoi" #: participation/templates/participation/tournament_list.html:6 -#: tfjm/templates/base.html:64 +#: tfjm/templates/base.html:65 msgid "All tournaments" msgstr "Tous les tournois" @@ -2097,8 +2116,8 @@ msgstr "Modèles :" msgid "Warning: non-free format" msgstr "Attention : format non libre" -#: participation/views.py:62 tfjm/templates/base.html:76 -#: tfjm/templates/navbar.html:37 +#: participation/views.py:62 tfjm/templates/base.html:77 +#: tfjm/templates/navbar.html:43 msgid "Create team" msgstr "Créer une équipe" @@ -2110,8 +2129,8 @@ msgstr "Vous ne participez pas, vous ne pouvez pas créer d'équipe." msgid "You are already in a team." msgstr "Vous êtes déjà dans une équipe." -#: participation/views.py:103 tfjm/templates/base.html:71 -#: tfjm/templates/navbar.html:42 +#: participation/views.py:103 tfjm/templates/base.html:72 +#: tfjm/templates/navbar.html:48 msgid "Join team" msgstr "Rejoindre une équipe" @@ -2219,101 +2238,101 @@ msgstr "Participation de l'équipe {trigram}" msgid "Payments of {tournament}" msgstr "Paiements de {tournament}" -#: participation/views.py:751 +#: participation/views.py:752 msgid "Notes published!" msgstr "Notes publiées !" -#: participation/views.py:753 +#: participation/views.py:754 msgid "Notes hidden!" msgstr "Notes dissimulées !" -#: participation/views.py:784 +#: participation/views.py:785 #, python-brace-format msgid "Harmonize notes of {tournament} - Day {round}" msgstr "Harmoniser les notes de {tournament} - Jour {round}" -#: participation/views.py:897 +#: participation/views.py:898 msgid "You can't upload a solution after the deadline." msgstr "Vous ne pouvez pas envoyer de solution après la date limite." -#: participation/views.py:1017 +#: participation/views.py:1018 #, python-brace-format msgid "Solutions of team {trigram}.zip" msgstr "Solutions de l'équipe {trigram}.zip" -#: participation/views.py:1017 +#: participation/views.py:1018 #, python-brace-format msgid "Syntheses of team {trigram}.zip" msgstr "Notes de synthèse de l'équipe {trigram}.zip" -#: participation/views.py:1034 participation/views.py:1049 +#: participation/views.py:1035 participation/views.py:1050 #, python-brace-format msgid "Solutions of {tournament}.zip" msgstr "Solutions de {tournament}.zip" -#: participation/views.py:1034 participation/views.py:1049 +#: participation/views.py:1035 participation/views.py:1050 #, python-brace-format msgid "Syntheses of {tournament}.zip" msgstr "Notes de synthèse de {tournament}.zip" -#: participation/views.py:1058 +#: participation/views.py:1059 #, python-brace-format msgid "Solutions for pool {pool} of tournament {tournament}.zip" msgstr "Solutions pour la poule {pool} du tournoi {tournament}.zip" -#: participation/views.py:1059 +#: participation/views.py:1060 #, python-brace-format msgid "Syntheses for pool {pool} of tournament {tournament}.zip" msgstr "Notes de synthèses pour la poule {pool} du tournoi {tournament}.zip" -#: participation/views.py:1101 +#: participation/views.py:1102 #, python-brace-format msgid "Jury of pool {pool} for {tournament} with teams {teams}" msgstr "Jury de la poule {pool} pour {tournament} avec les équipes {teams}" -#: participation/views.py:1117 +#: participation/views.py:1118 #, python-brace-format msgid "The jury {name} is already in the pool!" msgstr "{name} est déjà dans la poule !" -#: participation/views.py:1137 +#: participation/views.py:1138 msgid "New TFJM² jury account" msgstr "Nouveau compte de juré⋅e pour le TFJM²" -#: participation/views.py:1158 +#: participation/views.py:1159 #, python-brace-format msgid "The jury {name} has been successfully added!" msgstr "{name} a été ajouté⋅e avec succès en tant que juré⋅e !" -#: participation/views.py:1194 +#: participation/views.py:1195 #, python-brace-format msgid "The jury {name} has been successfully removed!" msgstr "{name} a été retiré⋅e avec succès du jury !" -#: participation/views.py:1220 +#: participation/views.py:1221 #, python-brace-format msgid "The jury {name} has been successfully promoted president!" msgstr "{name} a été nommé⋅e président⋅e du jury !" -#: participation/views.py:1248 +#: participation/views.py:1249 msgid "The following user is not registered as a jury:" msgstr "L'utilisateur⋅rice suivant n'est pas inscrit⋅e en tant que juré⋅e :" -#: participation/views.py:1264 +#: participation/views.py:1265 msgid "Notes were successfully uploaded." msgstr "Les notes ont bien été envoyées." -#: participation/views.py:1842 +#: participation/views.py:1843 #, python-brace-format msgid "Notation sheets of pool {pool} of {tournament}.zip" msgstr "Feuilles de notations pour la poule {pool} du tournoi {tournament}.zip" -#: participation/views.py:1847 +#: participation/views.py:1848 #, python-brace-format msgid "Notation sheets of {tournament}.zip" msgstr "Feuilles de notation de {tournament}.zip" -#: participation/views.py:2012 +#: participation/views.py:2013 msgid "You can't upload a synthesis after the deadline." msgstr "Vous ne pouvez pas envoyer de note de synthèse après la date limite." @@ -2360,11 +2379,11 @@ msgstr "encadrant⋅e" msgid "This email address is already used." msgstr "Cette adresse e-mail est déjà utilisée." -#: registration/forms.py:272 +#: registration/forms.py:273 msgid "Pending" msgstr "En attente" -#: registration/forms.py:291 registration/forms.py:324 +#: registration/forms.py:292 registration/forms.py:325 msgid "You must upload your receipt." msgstr "Vous devez envoyer votre justificatif." @@ -3441,133 +3460,133 @@ msgstr "Genre :" msgid "Address:" msgstr "Adresse :" -#: registration/templates/registration/user_detail.html:53 +#: registration/templates/registration/user_detail.html:56 msgid "Phone number:" msgstr "Numéro de téléphone :" -#: registration/templates/registration/user_detail.html:57 +#: registration/templates/registration/user_detail.html:60 msgid "Health issues:" msgstr "Problèmes de santé :" -#: registration/templates/registration/user_detail.html:62 +#: registration/templates/registration/user_detail.html:65 msgid "Housing constraints:" msgstr "Contraintes de logement :" -#: registration/templates/registration/user_detail.html:66 +#: registration/templates/registration/user_detail.html:69 msgid "Photo authorization:" msgstr "Autorisation de droit à l'image :" -#: registration/templates/registration/user_detail.html:77 +#: registration/templates/registration/user_detail.html:80 msgid "Photo authorization (final):" msgstr "Autorisation de droit à l'image (finale) :" -#: registration/templates/registration/user_detail.html:89 +#: registration/templates/registration/user_detail.html:92 msgid "Health sheet:" msgstr "Fiche sanitaire :" -#: registration/templates/registration/user_detail.html:99 +#: registration/templates/registration/user_detail.html:102 msgid "Vaccine sheet:" msgstr "Carnet de vaccination :" -#: registration/templates/registration/user_detail.html:109 +#: registration/templates/registration/user_detail.html:112 msgid "Parental authorization:" msgstr "Autorisation parentale :" -#: registration/templates/registration/user_detail.html:120 +#: registration/templates/registration/user_detail.html:123 msgid "Parental authorization (final):" msgstr "Autorisation parentale (finale) :" -#: registration/templates/registration/user_detail.html:130 +#: registration/templates/registration/user_detail.html:133 msgid "Student class:" msgstr "Classe :" -#: registration/templates/registration/user_detail.html:133 +#: registration/templates/registration/user_detail.html:136 msgid "School:" msgstr "École :" -#: registration/templates/registration/user_detail.html:136 +#: registration/templates/registration/user_detail.html:139 msgid "Responsible name:" msgstr "Nom d'un⋅e responsable légal⋅e :" -#: registration/templates/registration/user_detail.html:139 +#: registration/templates/registration/user_detail.html:142 msgid "Responsible phone number:" msgstr "Numéro de téléphone d'un⋅e responsable légal⋅e :" -#: registration/templates/registration/user_detail.html:142 +#: registration/templates/registration/user_detail.html:145 msgid "Responsible email address:" msgstr "Adresse e-mail d'un⋅e responsable légal⋅e :" -#: registration/templates/registration/user_detail.html:147 +#: registration/templates/registration/user_detail.html:150 msgid "Most recent degree:" msgstr "Dernier diplôme obtenu :" -#: registration/templates/registration/user_detail.html:150 -#: registration/templates/registration/user_detail.html:154 +#: registration/templates/registration/user_detail.html:153 +#: registration/templates/registration/user_detail.html:157 msgid "Professional activity:" msgstr "Activité professionnelle :" -#: registration/templates/registration/user_detail.html:157 +#: registration/templates/registration/user_detail.html:160 msgid "Admin:" msgstr "Administrateur⋅rice :" -#: registration/templates/registration/user_detail.html:161 +#: registration/templates/registration/user_detail.html:164 msgid "Grant Animath to contact me in the future about other actions:" msgstr "Autorise Animath à recontacter à propos d'autres actions :" -#: registration/templates/registration/user_detail.html:171 +#: registration/templates/registration/user_detail.html:174 msgid "Payment information (final):" msgstr "Informations de paiement (finale) :" -#: registration/templates/registration/user_detail.html:173 +#: registration/templates/registration/user_detail.html:176 msgid "Payment information:" msgstr "Informations de paiement :" -#: registration/templates/registration/user_detail.html:177 +#: registration/templates/registration/user_detail.html:180 msgid "yes,no,pending" msgstr "oui,non,en attente" -#: registration/templates/registration/user_detail.html:181 #: registration/templates/registration/user_detail.html:184 +#: registration/templates/registration/user_detail.html:187 msgid "valid:" msgstr "valide :" -#: registration/templates/registration/user_detail.html:196 +#: registration/templates/registration/user_detail.html:199 msgid "Download scholarship attestation" msgstr "Télécharger l'attestation de bourse" -#: registration/templates/registration/user_detail.html:198 +#: registration/templates/registration/user_detail.html:201 msgid "Download bank transfer receipt" msgstr "Télécharger le justificatif de virement bancaire" -#: registration/templates/registration/user_detail.html:213 +#: registration/templates/registration/user_detail.html:216 msgid "Impersonate" msgstr "Impersonifier" -#: registration/templates/registration/user_detail.html:220 +#: registration/templates/registration/user_detail.html:223 #: registration/views.py:317 msgid "Upload photo authorization" msgstr "Téléverser l'autorisation de droit à l'image" -#: registration/templates/registration/user_detail.html:226 +#: registration/templates/registration/user_detail.html:229 #: registration/views.py:351 msgid "Upload health sheet" msgstr "Téléverser la fiche sanitaire" -#: registration/templates/registration/user_detail.html:231 +#: registration/templates/registration/user_detail.html:234 #: registration/views.py:372 msgid "Upload vaccine sheet" msgstr "Téléverser le carnet de vaccination" -#: registration/templates/registration/user_detail.html:236 +#: registration/templates/registration/user_detail.html:239 #: registration/views.py:392 msgid "Upload parental authorization" msgstr "Téléverser l'autorisation parentale" -#: registration/templates/registration/user_detail.html:244 +#: registration/templates/registration/user_detail.html:247 msgid "Upload photo authorization (final)" msgstr "Téléverser l'autorisation de droit à l'image (finale)" -#: registration/templates/registration/user_detail.html:250 +#: registration/templates/registration/user_detail.html:253 msgid "Upload parental authorization (final)" msgstr "Téléverser l'autorisation parentale (finale)" @@ -3800,7 +3819,7 @@ msgstr "Plateforme de l'ETEAM" msgid "Registration platform to the ETEAM." msgstr "Plateforme d'inscription à l'ETEAM." -#: tfjm/templates/base.html:68 +#: tfjm/templates/base.html:69 msgid "Search results" msgstr "Résultats de la recherche" @@ -3982,39 +4001,43 @@ msgstr "" msgid "Home" msgstr "Accueil" -#: tfjm/templates/navbar.html:23 +#: tfjm/templates/navbar.html:24 +msgid "Tournament" +msgstr "Tournoi" + +#: tfjm/templates/navbar.html:28 msgid "Tournaments" msgstr "Tournois" -#: tfjm/templates/navbar.html:28 +#: tfjm/templates/navbar.html:34 msgid "Users" msgstr "Utilisateur⋅rices" -#: tfjm/templates/navbar.html:48 +#: tfjm/templates/navbar.html:54 msgid "My team" msgstr "Mon équipe" -#: tfjm/templates/navbar.html:53 +#: tfjm/templates/navbar.html:59 msgid "My participation" msgstr "Ma participation" -#: tfjm/templates/navbar.html:74 +#: tfjm/templates/navbar.html:80 msgid "Administration" msgstr "Administration" -#: tfjm/templates/navbar.html:82 +#: tfjm/templates/navbar.html:88 msgid "Search…" msgstr "Chercher…" -#: tfjm/templates/navbar.html:91 +#: tfjm/templates/navbar.html:97 msgid "Return to admin view" msgstr "Retourner à l'interface administrateur⋅rice" -#: tfjm/templates/navbar.html:96 +#: tfjm/templates/navbar.html:102 msgid "Register" msgstr "S'inscrire" -#: tfjm/templates/navbar.html:112 +#: tfjm/templates/navbar.html:118 msgid "My account" msgstr "Mon compte" @@ -4058,3 +4081,8 @@ msgstr "Aucun résultat." #: tfjm/templates/sidebar.html:10 tfjm/templates/sidebar.html:21 msgid "Informations" msgstr "Informations" + +#~ msgid "date when solutions of round 2 are available" +#~ msgstr "" +#~ "date à partir de laquelle les solutions pour le second tour sont " +#~ "disponibles" diff --git a/participation/api/serializers.py b/participation/api/serializers.py index 5aa2b27..ce6866d 100644 --- a/participation/api/serializers.py +++ b/participation/api/serializers.py @@ -60,6 +60,7 @@ class TournamentSerializer(serializers.ModelSerializer): fields = ('id', 'pk', 'name', 'date_start', 'date_end', 'place', 'max_teams', 'price', 'remote', 'inscription_limit', 'solution_limit', 'solutions_draw', 'syntheses_first_phase_limit', 'solutions_available_second_phase', 'syntheses_second_phase_limit', + 'solutions_available_third_phase', 'syntheses_third_phase_limit', 'description', 'organizers', 'final', 'participations',) diff --git a/participation/api/views.py b/participation/api/views.py index aa6793a..0d709b9 100644 --- a/participation/api/views.py +++ b/participation/api/views.py @@ -66,6 +66,7 @@ class TournamentViewSet(ModelViewSet): filterset_fields = ['name', 'date_start', 'date_end', 'place', 'max_teams', 'price', 'remote', 'inscription_limit', 'solution_limit', 'solutions_draw', 'syntheses_first_phase_limit', 'solutions_available_second_phase', 'syntheses_second_phase_limit', + 'solutions_available_third_phase', 'syntheses_third_phase_limit', 'description', 'organizers', 'final', ] diff --git a/participation/forms.py b/participation/forms.py index 4dc32ae..098dc98 100644 --- a/participation/forms.py +++ b/participation/forms.py @@ -14,6 +14,7 @@ from django.utils.translation import gettext_lazy as _ import pandas from pypdf import PdfReader from registration.models import VolunteerRegistration +from tfjm import settings from .models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament @@ -125,6 +126,12 @@ class ValidateParticipationForm(forms.Form): class TournamentForm(forms.ModelForm): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if settings.TFJM_APP != "ETEAM": + del self.fields['solutions_available_third_phase'] + del self.fields['syntheses_third_phase_limit'] + class Meta: model = Tournament exclude = ('notes_sheet_id', ) @@ -136,10 +143,10 @@ class TournamentForm(forms.ModelForm): 'solutions_draw': forms.DateTimeInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%d %H:%M'), 'syntheses_first_phase_limit': forms.DateTimeInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%d %H:%M'), - 'solutions_available_second_phase': forms.DateTimeInput(attrs={'type': 'datetime-local'}, - format='%Y-%m-%d %H:%M'), 'syntheses_second_phase_limit': forms.DateTimeInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%d %H:%M'), + 'syntheses_third_phase_limit': forms.DateTimeInput(attrs={'type': 'datetime-local'}, + format='%Y-%m-%d %H:%M'), 'organizers': forms.SelectMultiple(attrs={ 'class': 'selectpicker', 'data-live-search': 'true', diff --git a/participation/migrations/0015_tournament_solutions_available_third_phase_and_more.py b/participation/migrations/0015_tournament_solutions_available_third_phase_and_more.py new file mode 100644 index 0000000..17adadb --- /dev/null +++ b/participation/migrations/0015_tournament_solutions_available_third_phase_and_more.py @@ -0,0 +1,42 @@ +# Generated by Django 5.0.6 on 2024-06-07 13:51 + +import django.utils.timezone +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("participation", "0014_alter_team_trigram"), + ] + + operations = [ + migrations.RemoveField( + model_name="tournament", + name="solutions_available_second_phase", + ), + migrations.AddField( + model_name="tournament", + name="solutions_available_second_phase", + field=models.BooleanField( + default=False, + verbose_name="check this case when solutions for the second round become available", + ), + ), + migrations.AddField( + model_name="tournament", + name="solutions_available_third_phase", + field=models.BooleanField( + default=False, + verbose_name="check this case when solutions for the third round become available", + ), + ), + migrations.AddField( + model_name="tournament", + name="syntheses_third_phase_limit", + field=models.DateTimeField( + default=django.utils.timezone.now, + verbose_name="limit date to upload the syntheses for the third phase", + ), + ) + ] diff --git a/participation/models.py b/participation/models.py index 66a39c2..f579253 100644 --- a/participation/models.py +++ b/participation/models.py @@ -315,9 +315,9 @@ class Tournament(models.Model): default=timezone.now, ) - solutions_available_second_phase = models.DateTimeField( - verbose_name=_("date when the solutions for the second round become available"), - default=timezone.now, + solutions_available_second_phase = models.BooleanField( + verbose_name=_("check this case when solutions for the second round become available"), + default=False, ) syntheses_second_phase_limit = models.DateTimeField( @@ -325,6 +325,16 @@ class Tournament(models.Model): default=timezone.now, ) + solutions_available_third_phase = models.BooleanField( + verbose_name=_("check this case when solutions for the third round become available"), + default=False, + ) + + syntheses_third_phase_limit = models.DateTimeField( + verbose_name=_("limit date to upload the syntheses for the third phase"), + default=timezone.now, + ) + description = models.TextField( verbose_name=_("description"), blank=True, @@ -901,6 +911,49 @@ class Participation(models.Model): for ext in ["pdf", "tex", "odt", "docx"]) syntheses_templates_content = f"

{_('Templates:')} {syntheses_templates}

" + content = defender_content + opponent_content + reporter_content + syntheses_templates_content + informations.append({ + 'title': _("Second round"), + 'type': "info", + 'priority': 1, + 'content': content, + }) + elif settings.TFJM_APP == "ETEAM" \ + and timezone.now() <= tournament.syntheses_third_phase_limit + timedelta(hours=2): + defender_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, defender=self) + opponent_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, opponent=self) + reporter_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, reporter=self) + + defender_text = _("

For the third round, you will defend " + "your solution of the problem {problem}.

") + draw_url = reverse_lazy("draw:index") + solution_url = defender_passage.defended_solution.file.url + defender_content = format_lazy(defender_text, draw_url=draw_url, + solution_url=solution_url, problem=defender_passage.solution_number) + + opponent_text = _("

You will oppose the solution of the team {opponent} on the " + "problem {problem}. " + "You can upload your synthesis sheet on this page.

") + solution_url = opponent_passage.defended_solution.file.url + passage_url = reverse_lazy("participation:passage_detail", args=(opponent_passage.pk,)) + opponent_content = format_lazy(opponent_text, opponent=opponent_passage.defender.team.trigram, + solution_url=solution_url, + problem=opponent_passage.solution_number, passage_url=passage_url) + + reporter_text = _("

You will report the solution of the team {reporter} on the " + "problem {problem}. " + "You can upload your synthesis sheet on this page.

") + solution_url = reporter_passage.defended_solution.file.url + passage_url = reverse_lazy("participation:passage_detail", args=(reporter_passage.pk,)) + reporter_content = format_lazy(reporter_text, reporter=reporter_passage.defender.team.trigram, + solution_url=solution_url, + problem=reporter_passage.solution_number, passage_url=passage_url) + + syntheses_template_begin = f"{settings.STATIC_URL}Fiche_synthèse." + syntheses_templates = " — ".join(f"{ext.upper()}" + for ext in ["pdf", "tex", "odt", "docx"]) + syntheses_templates_content = f"

{_('Templates:')} {syntheses_templates}

" + content = defender_content + opponent_content + reporter_content + syntheses_templates_content informations.append({ 'title': _("Second round"), diff --git a/participation/templates/participation/tournament_detail.html b/participation/templates/participation/tournament_detail.html index e041b54..caa65e7 100644 --- a/participation/templates/participation/tournament_detail.html +++ b/participation/templates/participation/tournament_detail.html @@ -39,12 +39,14 @@
{% trans 'date of maximal syntheses submission for the first round'|capfirst %}
{{ tournament.syntheses_first_phase_limit }}
-
{% trans 'date when solutions of round 2 are available'|capfirst %}
-
{{ tournament.solutions_available_second_phase }}
-
{% trans 'date of maximal syntheses submission for the second round'|capfirst %}
{{ tournament.syntheses_second_phase_limit }}
+ {% if TFJM_APP == "ETEAM" %} +
{% trans 'date of maximal syntheses submission for the third round'|capfirst %}
+
{{ tournament.syntheses_third_phase_limit }}
+ {% endif %} +
{% trans 'description'|capfirst %}
{{ tournament.description }}