1
0
mirror of https://gitlab.com/animath/si/plateforme.git synced 2024-12-25 07:02:22 +00:00

Split 5-teams pols in two pools for each room

Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
Emmy D'Anello 2024-04-18 14:53:58 +02:00
parent 059cae75c5
commit 266afaf5c9
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
9 changed files with 337 additions and 238 deletions

View File

@ -361,6 +361,17 @@ class Pool(models.Model):
.prefetch_related('participation')]) .prefetch_related('participation')])
await self.asave() await self.asave()
pool2 = None
if self.size == 5:
pool2, _created = await PPool.objects.aget_or_create(
tournament=self.round.draw.tournament,
round=self.round.number,
letter=self.letter,
room=2,
)
await pool2.participations.aset([td.participation async for td in self.team_draws
.prefetch_related('participation')])
# Define the passage matrix according to the number of teams # Define the passage matrix according to the number of teams
table = [] table = []
if self.size == 3: if self.size == 3:
@ -380,16 +391,24 @@ class Pool(models.Model):
table = [ table = [
[0, 2, 3], [0, 2, 3],
[1, 3, 4], [1, 3, 4],
[4, 0, 2], [2, 4, 0],
[3, 0, 1], [3, 0, 1],
[4, 1, 2], [4, 1, 2],
] ]
for i, line in enumerate(table): for i, line in enumerate(table):
passage_pool = self.associated_pool
passage_position = i + 1
if self.size == 5:
# In 5-teams pools, we may create some passages in the second room
if i % 2 == 1:
passage_pool = pool2
passage_position = 1 + i // 2
# Create the passage # Create the passage
await Passage.objects.acreate( await Passage.objects.acreate(
pool=self.associated_pool, pool=passage_pool,
position=i + 1, position=passage_position,
solution_number=tds[line[0]].accepted, solution_number=tds[line[0]].accepted,
defender=tds[line[0]].participation, defender=tds[line[0]].participation,
opponent=tds[line[1]].participation, opponent=tds[line[1]].participation,

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: TFJM\n" "Project-Id-Version: TFJM\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-04-16 23:57+0200\n" "POT-Creation-Date: 2024-04-17 22:47+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Emmy D'Anello <emmy.danello@animath.fr>\n" "Last-Translator: Emmy D'Anello <emmy.danello@animath.fr>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -29,15 +29,15 @@ msgstr "équipes"
#: draw/admin.py:53 draw/admin.py:71 draw/admin.py:88 draw/models.py:26 #: 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:79 participation/admin.py:140
#: participation/admin.py:171 participation/models.py:656 #: participation/admin.py:171 participation/models.py:683
#: participation/models.py:680 participation/models.py:886 #: participation/models.py:707 participation/models.py:927
#: registration/models.py:756 #: registration/models.py:756
#: registration/templates/registration/payment_form.html:53 #: registration/templates/registration/payment_form.html:53
msgid "tournament" msgid "tournament"
msgstr "tournoi" msgstr "tournoi"
#: draw/admin.py:92 draw/models.py:234 draw/models.py:429 #: draw/admin.py:92 draw/models.py:234 draw/models.py:448
#: participation/models.py:890 #: participation/models.py:931
msgid "round" msgid "round"
msgstr "tour" msgstr "tour"
@ -175,7 +175,7 @@ msgstr "La poule en cours, où les équipes choisissent leurs problèmes"
msgid "rounds" msgid "rounds"
msgstr "tours" msgstr "tours"
#: draw/models.py:257 participation/models.py:904 #: draw/models.py:257 participation/models.py:939
msgid "letter" msgid "letter"
msgstr "lettre" msgstr "lettre"
@ -208,82 +208,82 @@ msgstr "poule associée"
msgid "The full pool instance." msgid "The full pool instance."
msgstr "L'instance complète de la poule." msgstr "L'instance complète de la poule."
#: draw/models.py:407 #: draw/models.py:426
#, python-brace-format #, python-brace-format
msgid "Pool {letter}{number}" msgid "Pool {letter}{number}"
msgstr "Poule {letter}{number}" msgstr "Poule {letter}{number}"
#: draw/models.py:410 draw/models.py:437 participation/admin.py:136 #: draw/models.py:429 draw/models.py:456 participation/admin.py:136
#: participation/admin.py:155 participation/models.py:1364 #: participation/admin.py:155 participation/models.py:1397
#: participation/models.py:1373 participation/tables.py:84 #: participation/models.py:1406 participation/tables.py:84
msgid "pool" msgid "pool"
msgstr "poule" msgstr "poule"
#: draw/models.py:411 participation/models.py:1365 #: draw/models.py:430 participation/models.py:1398
msgid "pools" msgid "pools"
msgstr "poules" msgstr "poules"
#: draw/models.py:423 participation/models.py:876 participation/models.py:1514 #: draw/models.py:442 participation/models.py:917 participation/models.py:1547
#: participation/models.py:1544 participation/models.py:1586 #: participation/models.py:1577 participation/models.py:1619
msgid "participation" msgid "participation"
msgstr "participation" msgstr "participation"
#: draw/models.py:444 #: draw/models.py:463
msgid "passage index" msgid "passage index"
msgstr "numéro de passage" msgstr "numéro de passage"
#: draw/models.py:445 #: draw/models.py:464
msgid "" msgid ""
"The passage order in the pool, between 0 and the size of the pool minus 1." "The passage order in the pool, between 0 and the size of the pool minus 1."
msgstr "" msgstr ""
"L'ordre de passage dans la poule, de 0 à la taille de la poule moins 1." "L'ordre de passage dans la poule, de 0 à la taille de la poule moins 1."
#: draw/models.py:453 #: draw/models.py:472
msgid "choose index" msgid "choose index"
msgstr "numéro de choix" msgstr "numéro de choix"
#: draw/models.py:454 #: draw/models.py:473
msgid "" msgid ""
"The choice order in the pool, between 0 and the size of the pool minus 1." "The choice order in the pool, between 0 and the size of the pool minus 1."
msgstr "" msgstr ""
"L'ordre de choix dans la poule, entre 0 et la taille de la poule moins 1." "L'ordre de choix dans la poule, entre 0 et la taille de la poule moins 1."
#: draw/models.py:460 draw/models.py:483 participation/models.py:1387 #: draw/models.py:479 draw/models.py:502 participation/models.py:1420
#: participation/models.py:1551 #: participation/models.py:1584
#, python-brace-format #, python-brace-format
msgid "Problem #{problem}" msgid "Problem #{problem}"
msgstr "Problème n°{problem}" msgstr "Problème n°{problem}"
#: draw/models.py:464 #: draw/models.py:483
msgid "accepted problem" msgid "accepted problem"
msgstr "problème accepté" msgstr "problème accepté"
#: draw/models.py:471 #: draw/models.py:490
msgid "passage dice" msgid "passage dice"
msgstr "dé d'ordre de passage" msgstr "dé d'ordre de passage"
#: draw/models.py:478 #: draw/models.py:497
msgid "choice dice" msgid "choice dice"
msgstr "dé d'ordre de choix" msgstr "dé d'ordre de choix"
#: draw/models.py:487 #: draw/models.py:506
msgid "purposed problem" msgid "purposed problem"
msgstr "problème proposé" msgstr "problème proposé"
#: draw/models.py:492 #: draw/models.py:511
msgid "rejected problems" msgid "rejected problems"
msgstr "problèmes rejetés" msgstr "problèmes rejetés"
#: draw/models.py:521 #: draw/models.py:540
#, python-brace-format #, python-brace-format
msgid "Draw of the team {trigram} for the pool {letter}{number}" msgid "Draw of the team {trigram} for the pool {letter}{number}"
msgstr "Tirage de l'équipe {trigram} pour la poule {letter}{number}" msgstr "Tirage de l'équipe {trigram} pour la poule {letter}{number}"
#: draw/models.py:527 #: draw/models.py:546
msgid "team draw" msgid "team draw"
msgstr "tirage d'équipe" msgstr "tirage d'équipe"
#: draw/models.py:528 #: draw/models.py:547
msgid "team draws" msgid "team draws"
msgstr "tirages d'équipe" msgstr "tirages d'équipe"
@ -332,7 +332,7 @@ msgid "Continue draw"
msgstr "Continuer le tirage" msgstr "Continuer le tirage"
#: draw/templates/draw/tournament_content.html:216 participation/admin.py:167 #: draw/templates/draw/tournament_content.html:216 participation/admin.py:167
#: participation/models.py:252 participation/models.py:671 #: participation/models.py:252 participation/models.py:698
#: participation/templates/participation/tournament_harmonize.html:15 #: participation/templates/participation/tournament_harmonize.html:15
#: registration/models.py:157 registration/models.py:747 #: registration/models.py:157 registration/models.py:747
#: registration/tables.py:39 #: registration/tables.py:39
@ -345,35 +345,31 @@ msgstr "équipe"
#: draw/templates/draw/tournament_content.html:228 #: draw/templates/draw/tournament_content.html:228
#: draw/templates/draw/tournament_content.html:229 #: draw/templates/draw/tournament_content.html:229
#: draw/templates/draw/tournament_content.html:230 #: draw/templates/draw/tournament_content.html:230
#: participation/templates/participation/pool_detail.html:85
#: participation/templates/participation/pool_detail.html:89
#: participation/templates/participation/pool_detail.html:94
#: participation/templates/participation/pool_detail.html:98
msgid "Room" msgid "Room"
msgstr "Salle" msgstr "Salle"
#: draw/templates/draw/tournament_content.html:335 #: draw/templates/draw/tournament_content.html:334
#: draw/templates/draw/tournament_content.html:354 #: draw/templates/draw/tournament_content.html:353
msgid "Abort" msgid "Abort"
msgstr "Annuler" msgstr "Annuler"
#: draw/templates/draw/tournament_content.html:345 #: draw/templates/draw/tournament_content.html:344
msgid "Are you sure?" msgid "Are you sure?"
msgstr "Êtes-vous sûr⋅e ?" msgstr "Êtes-vous sûr⋅e ?"
#: draw/templates/draw/tournament_content.html:349 #: draw/templates/draw/tournament_content.html:348
msgid "This will reset the draw from the beginning." msgid "This will reset the draw from the beginning."
msgstr "Cela va réinitialiser le tirage au sort depuis le début." msgstr "Cela va réinitialiser le tirage au sort depuis le début."
#: draw/templates/draw/tournament_content.html:350 #: draw/templates/draw/tournament_content.html:349
msgid "This operation is irreversible." msgid "This operation is irreversible."
msgstr "Cette opération est irréversible." msgstr "Cette opération est irréversible."
#: draw/templates/draw/tournament_content.html:351 #: draw/templates/draw/tournament_content.html:350
msgid "Are you sure you want to abort this draw?" msgid "Are you sure you want to abort this draw?"
msgstr "Êtes-vous sûr·e de vouloir annuler le tirage au sort ?" msgstr "Êtes-vous sûr·e de vouloir annuler le tirage au sort ?"
#: draw/templates/draw/tournament_content.html:355 #: draw/templates/draw/tournament_content.html:354
#: tfjm/templates/base_modal.html:17 #: tfjm/templates/base_modal.html:17
msgid "Close" msgid "Close"
msgstr "Fermer" msgstr "Fermer"
@ -452,26 +448,26 @@ msgstr "Changelog de type \"{action}\" pour le modèle {model} le {timestamp}"
msgid "valid" msgid "valid"
msgstr "valide" msgstr "valide"
#: participation/admin.py:87 participation/models.py:692 #: participation/admin.py:87 participation/models.py:719
msgid "selected for final" msgid "selected for final"
msgstr "sélectionnée pour la finale" msgstr "sélectionnée pour la finale"
#: participation/admin.py:124 participation/admin.py:183 #: participation/admin.py:124 participation/admin.py:183
#: participation/models.py:1394 participation/tables.py:112 #: participation/models.py:1427 participation/tables.py:112
msgid "defender" msgid "defender"
msgstr "défenseur⋅se" msgstr "défenseur⋅se"
#: participation/admin.py:128 participation/models.py:1401 #: participation/admin.py:128 participation/models.py:1434
#: participation/models.py:1598 #: participation/models.py:1631
msgid "opponent" msgid "opponent"
msgstr "opposant⋅e" msgstr "opposant⋅e"
#: participation/admin.py:132 participation/models.py:1408 #: participation/admin.py:132 participation/models.py:1441
#: participation/models.py:1599 #: participation/models.py:1632
msgid "reporter" msgid "reporter"
msgstr "rapporteur⋅rice" msgstr "rapporteur⋅rice"
#: participation/admin.py:187 participation/models.py:1549 #: participation/admin.py:187 participation/models.py:1582
msgid "problem" msgid "problem"
msgstr "numéro de problème" msgstr "numéro de problème"
@ -799,28 +795,36 @@ msgstr "finale"
msgid "Google Sheet ID" msgid "Google Sheet ID"
msgstr "ID de la feuille Google Sheets" msgstr "ID de la feuille Google Sheets"
#: participation/models.py:657 registration/admin.py:125 #: participation/models.py:684 registration/admin.py:125
msgid "tournaments" msgid "tournaments"
msgstr "tournois" msgstr "tournois"
#: participation/models.py:686 #: participation/models.py:713
msgid "valid team" msgid "valid team"
msgstr "équipe valide" msgstr "équipe valide"
#: participation/models.py:687 #: participation/models.py:714
msgid "The participation got the validation of the organizers." msgid "The participation got the validation of the organizers."
msgstr "La participation a été validée par les organisateur⋅rices." msgstr "La participation a été validée par les organisateur⋅rices."
#: participation/models.py:693 #: participation/models.py:720
msgid "The team is selected for the final tournament." msgid "The team is selected for the final tournament."
msgstr "L'équipe est sélectionnée pour la finale." msgstr "L'équipe est sélectionnée pour la finale."
#: participation/models.py:700 #: participation/models.py:724
msgid "mention"
msgstr "mention"
#: participation/models.py:731
msgid "mention (final)"
msgstr "Mention (pour la finale) :"
#: participation/models.py:741
#, python-brace-format #, python-brace-format
msgid "Participation of the team {name} ({trigram})" msgid "Participation of the team {name} ({trigram})"
msgstr "Participation de l'équipe {name} ({trigram})" msgstr "Participation de l'équipe {name} ({trigram})"
#: participation/models.py:707 #: participation/models.py:748
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"<p>The team {trigram} has {nb_missing_payments} missing payments. Each " "<p>The team {trigram} has {nb_missing_payments} missing payments. Each "
@ -833,11 +837,11 @@ msgstr ""
"notification de bourse) pour participer au tournoi.</p><p>Les participant⋅es " "notification de bourse) pour participer au tournoi.</p><p>Les participant⋅es "
"qui n'ont pas encore payé sont : {participants}.</p>" "qui n'ont pas encore payé sont : {participants}.</p>"
#: participation/models.py:715 #: participation/models.py:756
msgid "Missing payments" msgid "Missing payments"
msgstr "Paiements manquants" msgstr "Paiements manquants"
#: participation/models.py:732 #: participation/models.py:773
msgid "" msgid ""
"<p>The solutions for the tournament of {tournament} are due on the {date:%Y-" "<p>The solutions for the tournament of {tournament} are due on the {date:%Y-"
"%m-%d %H:%M}.</p><p>You have currently sent <strong>{nb_solutions}</strong> " "%m-%d %H:%M}.</p><p>You have currently sent <strong>{nb_solutions}</strong> "
@ -852,11 +856,11 @@ msgstr ""
"pouvez envoyer vos solutions sur <a href='{url}'>votre page de " "pouvez envoyer vos solutions sur <a href='{url}'>votre page de "
"participation</a>.</p>" "participation</a>.</p>"
#: participation/models.py:742 participation/models.py:756 #: participation/models.py:783 participation/models.py:797
msgid "Solutions due" msgid "Solutions due"
msgstr "Rendu des solutions" msgstr "Rendu des solutions"
#: participation/models.py:748 #: participation/models.py:789
msgid "" msgid ""
"<p>The solutions for the tournament of {tournament} are due on the {date:%Y-" "<p>The solutions for the tournament of {tournament} are due on the {date:%Y-"
"%m-%d %H:%M}.</p><p>Remember that you can only fix minor changes to your " "%m-%d %H:%M}.</p><p>Remember that you can only fix minor changes to your "
@ -869,7 +873,7 @@ msgstr ""
"parties.</p><p>Vous pouvez envoyer vos solutions sur <a href='{url}'>votre " "parties.</p><p>Vous pouvez envoyer vos solutions sur <a href='{url}'>votre "
"page de participation</a>.</p>" "page de participation</a>.</p>"
#: participation/models.py:762 registration/models.py:600 #: participation/models.py:803 registration/models.py:600
msgid "" msgid ""
"<p>The draw of the solutions for the tournament {tournament} is planned on " "<p>The draw of the solutions for the tournament {tournament} is planned on "
"the {date:%Y-%m-%d %H:%M}. You can join it on <a href='{url}'>this link</a>." "the {date:%Y-%m-%d %H:%M}. You can join it on <a href='{url}'>this link</a>."
@ -879,11 +883,11 @@ msgstr ""
"{date:%d/%m/%Y %H:%M}. Vous pouvez y participer sur <a href='{url}'>ce lien</" "{date:%d/%m/%Y %H:%M}. Vous pouvez y participer sur <a href='{url}'>ce lien</"
"a>.</p>" "a>.</p>"
#: participation/models.py:768 registration/models.py:607 #: participation/models.py:809 registration/models.py:607
msgid "Draw of solutions" msgid "Draw of solutions"
msgstr "Tirage au sort des solutions" msgstr "Tirage au sort des solutions"
#: participation/models.py:779 #: participation/models.py:820
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"<p>The solutions draw is ended. You can check the result on <a " "<p>The solutions draw is ended. You can check the result on <a "
@ -895,7 +899,7 @@ msgstr ""
"tour, vous défendrez <a href='{solution_url}'>votre solution du problème " "tour, vous défendrez <a href='{solution_url}'>votre solution du problème "
"{problem}</a>.</p>" "{problem}</a>.</p>"
#: participation/models.py:788 participation/models.py:831 #: participation/models.py:829 participation/models.py:872
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"<p>You will oppose the solution of the team {opponent} on the <a " "<p>You will oppose the solution of the team {opponent} on the <a "
@ -906,7 +910,7 @@ msgstr ""
"href='{solution_url}'>problème {problem}</a>. Vous pouvez envoyer votre note " "href='{solution_url}'>problème {problem}</a>. Vous pouvez envoyer votre note "
"de synthèse sur <a href='{passage_url}'>cette page</a>.</p>" "de synthèse sur <a href='{passage_url}'>cette page</a>.</p>"
#: participation/models.py:797 participation/models.py:840 #: participation/models.py:838 participation/models.py:881
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"<p>You will report the solution of the team {reporter} on the <a " "<p>You will report the solution of the team {reporter} on the <a "
@ -917,11 +921,11 @@ msgstr ""
"href='{solution_url}'>problème {problem}</a>. Vous pouvez envoyer votre note " "href='{solution_url}'>problème {problem}</a>. Vous pouvez envoyer votre note "
"de synthèse sur <a href='{passage_url}'>cette page</a>.</p>" "de synthèse sur <a href='{passage_url}'>cette page</a>.</p>"
#: participation/models.py:813 registration/models.py:622 #: participation/models.py:854 registration/models.py:622
msgid "First round" msgid "First round"
msgstr "Premier tour" msgstr "Premier tour"
#: participation/models.py:824 #: participation/models.py:865
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"<p>For the second round, you will defend <a href='{solution_url}'>your " "<p>For the second round, you will defend <a href='{solution_url}'>your "
@ -930,11 +934,11 @@ msgstr ""
"<p>Pour le second tour, vous défendrez <a href='{solution_url}'>votre " "<p>Pour le second tour, vous défendrez <a href='{solution_url}'>votre "
"solution du problème {problem}</a>.</p>" "solution du problème {problem}</a>.</p>"
#: participation/models.py:856 registration/models.py:633 #: participation/models.py:897 registration/models.py:633
msgid "Second round" msgid "Second round"
msgstr "Second tour" msgstr "Second tour"
#: participation/models.py:862 #: participation/models.py:903
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"<p>The tournament {tournament} is ended. You can check the results on the <a " "<p>The tournament {tournament} is ended. You can check the results on the <a "
@ -943,40 +947,56 @@ msgstr ""
"<p>Le tournoi {tournament} est terminé. Vous pouvez consulter les résultats " "<p>Le tournoi {tournament} est terminé. Vous pouvez consulter les résultats "
"sur la <a href='{url}'>page du tournoi</a>.</p>" "sur la <a href='{url}'>page du tournoi</a>.</p>"
#: participation/models.py:867 #: participation/models.py:908
msgid "Tournament ended" msgid "Tournament ended"
msgstr "Tournoi terminé" msgstr "Tournoi terminé"
#: participation/models.py:877 participation/models.py:910 #: participation/models.py:918 participation/models.py:961
msgid "participations" msgid "participations"
msgstr "participations" msgstr "participations"
#: participation/models.py:892 participation/models.py:893 #: participation/models.py:933 participation/models.py:934
#, python-brace-format #, python-brace-format
msgid "Round {round}" msgid "Round {round}"
msgstr "Tour {round}" msgstr "Tour {round}"
#: participation/models.py:916 #: participation/models.py:949
msgid "room"
msgstr "salle"
#: participation/models.py:951
msgid "Room 1"
msgstr "Salle 1"
#: participation/models.py:952
msgid "Room 2"
msgstr "Salle 2"
#: participation/models.py:955
msgid "For 5-teams pools only"
msgstr "Pour les poules de 5 équipe uniquement"
#: participation/models.py:967
msgid "juries" msgid "juries"
msgstr "jurys" msgstr "jurys"
#: participation/models.py:925 #: participation/models.py:976
msgid "president of the jury" msgid "president of the jury"
msgstr "président⋅e du jury" msgstr "président⋅e du jury"
#: participation/models.py:932 #: participation/models.py:983
msgid "BigBlueButton URL" msgid "BigBlueButton URL"
msgstr "Lien BigBlueButton" msgstr "Lien BigBlueButton"
#: participation/models.py:933 #: participation/models.py:984
msgid "The link of the BBB visio for this pool." msgid "The link of the BBB visio for this pool."
msgstr "Le lien du salon BBB pour cette poule." msgstr "Le lien du salon BBB pour cette poule."
#: participation/models.py:938 #: participation/models.py:989
msgid "results available" msgid "results available"
msgstr "résultats disponibles" msgstr "résultats disponibles"
#: participation/models.py:939 #: participation/models.py:990
msgid "" msgid ""
"Check this case when results become accessible to teams. They stay " "Check this case when results become accessible to teams. They stay "
"accessible to you. Only averages are given." "accessible to you. Only averages are given."
@ -985,33 +1005,33 @@ msgstr ""
"Ils restent toujours accessibles pour vous. Seules les moyennes sont " "Ils restent toujours accessibles pour vous. Seules les moyennes sont "
"communiquées." "communiquées."
#: participation/models.py:964 #: participation/models.py:1018
msgid "The president of the jury must be part of the jury." msgid "The president of the jury must be part of the jury."
msgstr "Læ président⋅e du jury doit faire partie du jury." msgstr "Læ président⋅e du jury doit faire partie du jury."
#: participation/models.py:1345 #: participation/models.py:1378
#, python-brace-format #, python-brace-format
msgid "The jury {jury} is not part of the jury for this pool." msgid "The jury {jury} is not part of the jury for this pool."
msgstr "{jury} ne fait pas partie du jury pour cette poule." msgstr "{jury} ne fait pas partie du jury pour cette poule."
#: participation/models.py:1358 #: participation/models.py:1391
#, python-brace-format #, python-brace-format
msgid "Pool of day {round} for tournament {tournament} with teams {teams}" msgid "Pool of day {round} for tournament {tournament} with teams {teams}"
msgstr "Poule du jour {round} du tournoi {tournament} avec les équipes {teams}" msgstr "Poule du jour {round} du tournoi {tournament} avec les équipes {teams}"
#: participation/models.py:1378 #: participation/models.py:1411
msgid "position" msgid "position"
msgstr "position" msgstr "position"
#: participation/models.py:1385 #: participation/models.py:1418
msgid "defended solution" msgid "defended solution"
msgstr "solution défendue" msgstr "solution défendue"
#: participation/models.py:1413 #: participation/models.py:1446
msgid "penalties" msgid "penalties"
msgstr "pénalités" msgstr "pénalités"
#: participation/models.py:1415 #: participation/models.py:1448
msgid "" msgid ""
"Number of penalties for the defender. The defender will loose a 0.5 " "Number of penalties for the defender. The defender will loose a 0.5 "
"coefficient per penalty." "coefficient per penalty."
@ -1019,120 +1039,120 @@ msgstr ""
"Nombre de pénalités pour l'équipe défenseuse. Elle perd un coefficient 0.5 " "Nombre de pénalités pour l'équipe défenseuse. Elle perd un coefficient 0.5 "
"sur sa présentation orale par pénalité." "sur sa présentation orale par pénalité."
#: participation/models.py:1484 participation/models.py:1487 #: participation/models.py:1517 participation/models.py:1520
#: participation/models.py:1490 #: participation/models.py:1523
#, python-brace-format #, python-brace-format
msgid "Team {trigram} is not registered in the pool." msgid "Team {trigram} is not registered in the pool."
msgstr "L'équipe {trigram} n'est pas inscrite dans la poule." msgstr "L'équipe {trigram} n'est pas inscrite dans la poule."
#: participation/models.py:1495 #: participation/models.py:1528
#, python-brace-format #, python-brace-format
msgid "Passage of {defender} for problem {problem}" msgid "Passage of {defender} for problem {problem}"
msgstr "Passage de {defender} pour le problème {problem}" msgstr "Passage de {defender} pour le problème {problem}"
#: participation/models.py:1499 participation/models.py:1508 #: participation/models.py:1532 participation/models.py:1541
#: participation/models.py:1593 participation/models.py:1635 #: participation/models.py:1626 participation/models.py:1668
msgid "passage" msgid "passage"
msgstr "passage" msgstr "passage"
#: participation/models.py:1500 #: participation/models.py:1533
msgid "passages" msgid "passages"
msgstr "passages" msgstr "passages"
#: participation/models.py:1519 #: participation/models.py:1552
msgid "difference" msgid "difference"
msgstr "différence" msgstr "différence"
#: participation/models.py:1520 #: participation/models.py:1553
msgid "Score to add/remove on the final score" msgid "Score to add/remove on the final score"
msgstr "Score à ajouter/retrancher au score final" msgstr "Score à ajouter/retrancher au score final"
#: participation/models.py:1527 #: participation/models.py:1560
msgid "tweak" msgid "tweak"
msgstr "harmonisation" msgstr "harmonisation"
#: participation/models.py:1528 #: participation/models.py:1561
msgid "tweaks" msgid "tweaks"
msgstr "harmonisations" msgstr "harmonisations"
#: participation/models.py:1556 #: participation/models.py:1589
msgid "solution for the final tournament" msgid "solution for the final tournament"
msgstr "solution pour la finale" msgstr "solution pour la finale"
#: participation/models.py:1561 participation/models.py:1604 #: participation/models.py:1594 participation/models.py:1637
msgid "file" msgid "file"
msgstr "fichier" msgstr "fichier"
#: participation/models.py:1571 #: participation/models.py:1604
#, python-brace-format #, python-brace-format
msgid "Solution of team {team} for problem {problem}" msgid "Solution of team {team} for problem {problem}"
msgstr "Solution de l'équipe {team} pour le problème {problem}" msgstr "Solution de l'équipe {team} pour le problème {problem}"
#: participation/models.py:1573 #: participation/models.py:1606
msgid "for final" msgid "for final"
msgstr "pour la finale" msgstr "pour la finale"
#: participation/models.py:1576 #: participation/models.py:1609
msgid "solution" msgid "solution"
msgstr "solution" msgstr "solution"
#: participation/models.py:1577 #: participation/models.py:1610
msgid "solutions" msgid "solutions"
msgstr "solutions" msgstr "solutions"
#: participation/models.py:1610 #: participation/models.py:1643
#, python-brace-format #, python-brace-format
msgid "Synthesis of {team} as {type} for problem {problem} of {defender}" msgid "Synthesis of {team} as {type} for problem {problem} of {defender}"
msgstr "" msgstr ""
"Note de synthèse de l'équipe {team} en tant que {type} pour le problème " "Note de synthèse de l'équipe {team} en tant que {type} pour le problème "
"{problem} de {defender}" "{problem} de {defender}"
#: participation/models.py:1618 #: participation/models.py:1651
msgid "synthesis" msgid "synthesis"
msgstr "note de synthèse" msgstr "note de synthèse"
#: participation/models.py:1619 #: participation/models.py:1652
msgid "syntheses" msgid "syntheses"
msgstr "notes de synthèse" msgstr "notes de synthèse"
#: participation/models.py:1628 #: participation/models.py:1661
msgid "jury" msgid "jury"
msgstr "jury" msgstr "jury"
#: participation/models.py:1640 #: participation/models.py:1673
msgid "defender writing note" msgid "defender writing note"
msgstr "note d'écrit défenseur⋅se" msgstr "note d'écrit défenseur⋅se"
#: participation/models.py:1646 #: participation/models.py:1679
msgid "defender oral note" msgid "defender oral note"
msgstr "note d'oral défenseur⋅se" msgstr "note d'oral défenseur⋅se"
#: participation/models.py:1652 #: participation/models.py:1685
msgid "opponent writing note" msgid "opponent writing note"
msgstr "note d'écrit opposant⋅e" msgstr "note d'écrit opposant⋅e"
#: participation/models.py:1658 #: participation/models.py:1691
msgid "opponent oral note" msgid "opponent oral note"
msgstr "note d'oral opposant⋅e" msgstr "note d'oral opposant⋅e"
#: participation/models.py:1664 #: participation/models.py:1697
msgid "reporter writing note" msgid "reporter writing note"
msgstr "note d'écrit rapporteur⋅rice" msgstr "note d'écrit rapporteur⋅rice"
#: participation/models.py:1670 #: participation/models.py:1703
msgid "reporter oral note" msgid "reporter oral note"
msgstr "note d'oral du rapporteur⋅rice" msgstr "note d'oral du rapporteur⋅rice"
#: participation/models.py:1728 #: participation/models.py:1761
#, python-brace-format #, python-brace-format
msgid "Notes of {jury} for {passage}" msgid "Notes of {jury} for {passage}"
msgstr "Notes de {jury} pour le {passage}" msgstr "Notes de {jury} pour le {passage}"
#: participation/models.py:1731 #: participation/models.py:1764
msgid "note" msgid "note"
msgstr "note" msgstr "note"
#: participation/models.py:1732 #: participation/models.py:1765
msgid "notes" msgid "notes"
msgstr "notes" msgstr "notes"
@ -1159,8 +1179,8 @@ msgstr "Du {start} au {end}"
#: participation/tables.py:94 #: participation/tables.py:94
#, python-brace-format #, python-brace-format
msgid "Pool {letter}{round}" msgid "Pool {code}"
msgstr "Poule {letter}{round}" msgstr "Poule {code}"
#: participation/tables.py:98 #: participation/tables.py:98
msgid "No defined team" msgid "No defined team"
@ -1172,7 +1192,7 @@ msgstr "Pas d'équipe définie"
#: participation/templates/participation/passage_detail.html:140 #: participation/templates/participation/passage_detail.html:140
#: participation/templates/participation/passage_detail.html:146 #: participation/templates/participation/passage_detail.html:146
#: participation/templates/participation/pool_detail.html:13 #: participation/templates/participation/pool_detail.html:13
#: participation/templates/participation/pool_detail.html:157 #: participation/templates/participation/pool_detail.html:152
#: participation/templates/participation/team_detail.html:179 #: participation/templates/participation/team_detail.html:179
#: participation/templates/participation/team_detail.html:243 #: participation/templates/participation/team_detail.html:243
#: participation/templates/participation/tournament_form.html:12 #: participation/templates/participation/tournament_form.html:12
@ -1273,7 +1293,7 @@ msgstr "Envoyer une solution"
#: participation/templates/participation/participation_detail.html:65 #: participation/templates/participation/participation_detail.html:65
#: participation/templates/participation/passage_detail.html:152 #: participation/templates/participation/passage_detail.html:152
#: participation/templates/participation/pool_detail.html:162 #: participation/templates/participation/pool_detail.html:157
#: participation/templates/participation/team_detail.html:238 #: participation/templates/participation/team_detail.html:238
#: participation/templates/participation/upload_motivation_letter.html:13 #: participation/templates/participation/upload_motivation_letter.html:13
#: participation/templates/participation/upload_notes.html:24 #: participation/templates/participation/upload_notes.html:24
@ -1321,12 +1341,12 @@ msgid "Defender penalties count:"
msgstr "Nombre de pénalités :" msgstr "Nombre de pénalités :"
#: participation/templates/participation/passage_detail.html:43 #: participation/templates/participation/passage_detail.html:43
#: participation/templates/participation/pool_detail.html:54 #: participation/templates/participation/pool_detail.html:59
msgid "Syntheses:" msgid "Syntheses:"
msgstr "Notes de synthèse :" msgstr "Notes de synthèse :"
#: participation/templates/participation/passage_detail.html:48 #: participation/templates/participation/passage_detail.html:48
#: participation/templates/participation/pool_detail.html:63 #: participation/templates/participation/pool_detail.html:68
msgid "No synthesis was uploaded yet." msgid "No synthesis was uploaded yet."
msgstr "Aucune note de synthèse n'a encore été envoyée." msgstr "Aucune note de synthèse n'a encore été envoyée."
@ -1393,36 +1413,40 @@ msgstr "Tour :"
msgid "Letter:" msgid "Letter:"
msgstr "Lettre :" msgstr "Lettre :"
#: participation/templates/participation/pool_detail.html:29 #: participation/templates/participation/pool_detail.html:30
msgid "Room:"
msgstr "Salle :"
#: participation/templates/participation/pool_detail.html:34
msgid "Teams:" msgid "Teams:"
msgstr "Équipes :" msgstr "Équipes :"
#: participation/templates/participation/pool_detail.html:36 #: participation/templates/participation/pool_detail.html:41
msgid "Juries:" msgid "Juries:"
msgstr "Juré⋅es :" msgstr "Juré⋅es :"
#: participation/templates/participation/pool_detail.html:40 #: participation/templates/participation/pool_detail.html:45
msgid "Edit jury" msgid "Edit jury"
msgstr "Modifier le jury" msgstr "Modifier le jury"
#: participation/templates/participation/pool_detail.html:44 #: participation/templates/participation/pool_detail.html:49
msgid "Defended solutions:" msgid "Defended solutions:"
msgstr "Solutions défendues :" msgstr "Solutions défendues :"
#: participation/templates/participation/pool_detail.html:50 #: participation/templates/participation/pool_detail.html:55
#: participation/templates/participation/pool_detail.html:69 #: participation/templates/participation/pool_detail.html:74
msgid "Download all" msgid "Download all"
msgstr "Tout télécharger" msgstr "Tout télécharger"
#: participation/templates/participation/pool_detail.html:74 #: participation/templates/participation/pool_detail.html:79
msgid "BigBlueButton link:" msgid "BigBlueButton link:"
msgstr "Lien BigBlueButton :" msgstr "Lien BigBlueButton :"
#: participation/templates/participation/pool_detail.html:80 #: participation/templates/participation/pool_detail.html:85
msgid "Notation sheets:" msgid "Notation sheets:"
msgstr "Feuilles de notations :" msgstr "Feuilles de notations :"
#: participation/templates/participation/pool_detail.html:85 #: participation/templates/participation/pool_detail.html:90
msgid "Download the scale sheet" msgid "Download the scale sheet"
msgstr "Télécharger la feuille de barème" msgstr "Télécharger la feuille de barème"
@ -1430,42 +1454,42 @@ msgstr "Télécharger la feuille de barème"
msgid "Download the final notation sheet" msgid "Download the final notation sheet"
msgstr "Télécharger la fiche de notation finale" msgstr "Télécharger la fiche de notation finale"
#: participation/templates/participation/pool_detail.html:103 #: participation/templates/participation/pool_detail.html:98
msgid "Download all notation sheets" msgid "Download all notation sheets"
msgstr "Télécharger toutes les fiches de notation" msgstr "Télécharger toutes les fiches de notation"
#: participation/templates/participation/pool_detail.html:108 #: participation/templates/participation/pool_detail.html:103
msgid "Google Sheets Spreadsheet:" msgid "Google Sheets Spreadsheet:"
msgstr "Tableur Google Sheets :" msgstr "Tableur Google Sheets :"
#: participation/templates/participation/pool_detail.html:112 #: participation/templates/participation/pool_detail.html:107
msgid "Go to the Google Sheets page of the pool" msgid "Go to the Google Sheets page of the pool"
msgstr "Aller à la page Google Sheets de la poule" msgstr "Aller à la page Google Sheets de la poule"
#: participation/templates/participation/pool_detail.html:121 #: participation/templates/participation/pool_detail.html:116
#: participation/templates/participation/tournament_detail.html:101 #: participation/templates/participation/tournament_detail.html:101
#: participation/templates/participation/tournament_harmonize.html:8 #: participation/templates/participation/tournament_harmonize.html:8
msgid "Ranking" msgid "Ranking"
msgstr "Classement" msgstr "Classement"
#: participation/templates/participation/pool_detail.html:136 #: participation/templates/participation/pool_detail.html:131
msgid "Upload notes from a spreadsheet file" msgid "Upload notes from a spreadsheet file"
msgstr "Soumettre les notes à partir d'un tableur" msgstr "Soumettre les notes à partir d'un tableur"
#: participation/templates/participation/pool_detail.html:140 #: participation/templates/participation/pool_detail.html:135
msgid "Download notation spreadsheet" msgid "Download notation spreadsheet"
msgstr "Télécharger le tableur de notes" msgstr "Télécharger le tableur de notes"
#: participation/templates/participation/pool_detail.html:152 #: participation/templates/participation/pool_detail.html:147
msgid "Passages" msgid "Passages"
msgstr "Passages" msgstr "Passages"
#: participation/templates/participation/pool_detail.html:156 #: participation/templates/participation/pool_detail.html:151
#: participation/templates/participation/pool_form.html:11 #: participation/templates/participation/pool_form.html:11
msgid "Update pool" msgid "Update pool"
msgstr "Modifier la poule" msgstr "Modifier la poule"
#: participation/templates/participation/pool_detail.html:161 #: participation/templates/participation/pool_detail.html:156
msgid "Upload notes" msgid "Upload notes"
msgstr "Envoyer les notes" msgstr "Envoyer les notes"
@ -1763,41 +1787,41 @@ msgstr "Accéder à la liste des paiements"
msgid "Pools" msgid "Pools"
msgstr "Poules" msgstr "Poules"
#: participation/templates/participation/tournament_detail.html:111 #: participation/templates/participation/tournament_detail.html:119
msgid "Selected for final tournament" msgid "Selected for final tournament"
msgstr "Sélectionnée pour la finale" msgstr "Sélectionnée pour la finale"
#: participation/templates/participation/tournament_detail.html:119 #: participation/templates/participation/tournament_detail.html:127
msgid "Select for final tournament" msgid "Select for final tournament"
msgstr "Sélectionner pour la finale" msgstr "Sélectionner pour la finale"
#: participation/templates/participation/tournament_detail.html:132 #: participation/templates/participation/tournament_detail.html:140
#: participation/templates/participation/tournament_detail.html:136 #: participation/templates/participation/tournament_detail.html:144
msgid "Harmonize" msgid "Harmonize"
msgstr "Harmoniser" msgstr "Harmoniser"
#: participation/templates/participation/tournament_detail.html:132 #: participation/templates/participation/tournament_detail.html:140
#: participation/templates/participation/tournament_detail.html:136 #: participation/templates/participation/tournament_detail.html:144
msgid "Day" msgid "Day"
msgstr "Jour" msgstr "Jour"
#: participation/templates/participation/tournament_detail.html:145 #: participation/templates/participation/tournament_detail.html:153
msgid "Publish notes for first round" msgid "Publish notes for first round"
msgstr "Publier les notes pour le premier tour" msgstr "Publier les notes pour le premier tour"
#: participation/templates/participation/tournament_detail.html:150 #: participation/templates/participation/tournament_detail.html:158
msgid "Unpublish notes for first round" msgid "Unpublish notes for first round"
msgstr "Dépublier les notes pour le premier tour" msgstr "Dépublier les notes pour le premier tour"
#: participation/templates/participation/tournament_detail.html:156 #: participation/templates/participation/tournament_detail.html:164
msgid "Publish notes for second round" msgid "Publish notes for second round"
msgstr "Publier les notes pour le second tour" msgstr "Publier les notes pour le second tour"
#: participation/templates/participation/tournament_detail.html:161 #: participation/templates/participation/tournament_detail.html:169
msgid "Unpublish notes for second round" msgid "Unpublish notes for second round"
msgstr "Dépublier les notes pour le second tour" msgstr "Dépublier les notes pour le second tour"
#: participation/templates/participation/tournament_detail.html:173 #: participation/templates/participation/tournament_detail.html:181
msgid "Files available for download" msgid "Files available for download"
msgstr "Fichiers disponibles au téléchargement" msgstr "Fichiers disponibles au téléchargement"
@ -2061,17 +2085,17 @@ msgstr "L'utilisateur⋅rice suivant n'est pas inscrit⋅e en tant que juré⋅e
msgid "Notes were successfully uploaded." msgid "Notes were successfully uploaded."
msgstr "Les notes ont bien été envoyées." msgstr "Les notes ont bien été envoyées."
#: participation/views.py:1855 #: participation/views.py:1825
#, python-brace-format #, python-brace-format
msgid "Notation sheets of pool {pool} of {tournament}.zip" msgid "Notation sheets of pool {pool} of {tournament}.zip"
msgstr "Feuilles de notations pour la poule {pool} du tournoi {tournament}.zip" msgstr "Feuilles de notations pour la poule {pool} du tournoi {tournament}.zip"
#: participation/views.py:1860 #: participation/views.py:1830
#, python-brace-format #, python-brace-format
msgid "Notation sheets of {tournament}.zip" msgid "Notation sheets of {tournament}.zip"
msgstr "Feuilles de notation de {tournament}.zip" msgstr "Feuilles de notation de {tournament}.zip"
#: participation/views.py:2033 #: participation/views.py:1995
msgid "You can't upload a synthesis after the deadline." 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." msgstr "Vous ne pouvez pas envoyer de note de synthèse après la date limite."

View File

@ -100,8 +100,8 @@ class ParticipationAdmin(admin.ModelAdmin):
@admin.register(Pool) @admin.register(Pool)
class PoolAdmin(admin.ModelAdmin): class PoolAdmin(admin.ModelAdmin):
list_display = ('__str__', 'tournament', 'round', 'letter', 'teams', 'jury_president',) list_display = ('__str__', 'tournament', 'round', 'letter', 'room', 'teams', 'jury_president',)
list_filter = ('tournament', 'round', 'letter',) list_filter = ('tournament', 'round', 'letter', 'room',)
search_fields = ('participations__team__name', 'participations__team__trigram',) search_fields = ('participations__team__name', 'participations__team__trigram',)
autocomplete_fields = ('tournament', 'participations', 'jury_president', 'juries',) autocomplete_fields = ('tournament', 'participations', 'jury_president', 'juries',)
inlines = (PassageInline, TweakInline,) inlines = (PassageInline, TweakInline,)

View File

@ -0,0 +1,31 @@
# Generated by Django 5.0.3 on 2024-04-17 20:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("participation", "0012_participation_mention_participation_mention_final"),
]
operations = [
migrations.AlterModelOptions(
name="pool",
options={
"ordering": ("round", "letter", "room"),
"verbose_name": "pool",
"verbose_name_plural": "pools",
},
),
migrations.AddField(
model_name="pool",
name="room",
field=models.PositiveSmallIntegerField(
choices=[(1, "Room 1"), (2, "Room 2")],
default=1,
help_text="For 5-teams pools only",
verbose_name="room",
),
),
]

View File

@ -10,7 +10,7 @@ from django.core.validators import MaxValueValidator, MinValueValidator, RegexVa
from django.db import models from django.db import models
from django.db.models import Index from django.db.models import Index
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils import timezone from django.utils import timezone, translation
from django.utils.crypto import get_random_string from django.utils.crypto import get_random_string
from django.utils.text import format_lazy from django.utils.text import format_lazy
from django.utils.timezone import localtime from django.utils.timezone import localtime
@ -430,7 +430,9 @@ class Tournament(models.Model):
self.notes_sheet_id = spreadsheet.id self.notes_sheet_id = spreadsheet.id
self.save() self.save()
def update_ranking_spreadsheet(self): def update_ranking_spreadsheet(self): # noqa: C901
translation.activate('fr')
gc = gspread.service_account_from_dict(settings.GOOGLE_SERVICE_CLIENT) gc = gspread.service_account_from_dict(settings.GOOGLE_SERVICE_CLIENT)
spreadsheet = gc.open_by_key(self.notes_sheet_id) spreadsheet = gc.open_by_key(self.notes_sheet_id)
worksheets = spreadsheet.worksheets() worksheets = spreadsheet.worksheets()
@ -444,27 +446,35 @@ class Tournament(models.Model):
header = [["Équipe", "Score jour 1", "Harmonisation 1", "Score jour 2", "Harmonisation 2", "Total", "Rang"]] header = [["Équipe", "Score jour 1", "Harmonisation 1", "Score jour 2", "Harmonisation 2", "Total", "Rang"]]
lines = [] lines = []
participations = self.participations.filter(pools__round=1, pools__tournament=self).all() participations = self.participations.filter(pools__round=1, pools__tournament=self).distinct().all()
for i, participation in enumerate(participations): for i, participation in enumerate(participations):
line = [f"{participation.team.name} ({participation.team.trigram})"] line = [f"{participation.team.name} ({participation.team.trigram})"]
lines.append(line) lines.append(line)
pool1 = self.pools.get(round=1, participations=participation) passage1 = Passage.objects.get(pool__tournament=self, pool__round=1, defender=participation)
passage1 = pool1.passages.get(defender=participation) pool1 = passage1.pool
if pool1.participations.count() != 5:
position1 = passage1.position
else:
position1 = (passage1.position - 1) * 2 + pool1.room
tweak1_qs = Tweak.objects.filter(pool=pool1, participation=participation) tweak1_qs = Tweak.objects.filter(pool=pool1, participation=participation)
tweak1 = tweak1_qs.get() if tweak1_qs.exists() else None tweak1 = tweak1_qs.get() if tweak1_qs.exists() else None
line.append(f"=SIERREUR('Poule {pool1.short_name}'!$D{pool1.juries.count() + 10 + passage1.position}; 0)") line.append(f"=SIERREUR('Poule {pool1.short_name}'!$D{pool1.juries.count() + 10 + position1}; 0)")
line.append(tweak1.diff if tweak1 else 0) line.append(tweak1.diff if tweak1 else 0)
if self.pools.filter(round=2, participations=participation).exists(): if Passage.objects.filter(pool__tournament=self, pool__round=2, defender=participation).exists():
pool2 = self.pools.get(round=2, participations=participation) passage2 = Passage.objects.get(pool__tournament=self, pool__round=2, defender=participation)
passage2 = pool2.passages.get(defender=participation) pool2 = passage2.pool
if pool2.participations.count() != 5:
position2 = passage2.position
else:
position2 = (passage2.position - 1) * 2 + pool2.room
tweak2_qs = Tweak.objects.filter(pool=pool2, participation=participation) tweak2_qs = Tweak.objects.filter(pool=pool2, participation=participation)
tweak2 = tweak2_qs.get() if tweak2_qs.exists() else None tweak2 = tweak2_qs.get() if tweak2_qs.exists() else None
line.append( line.append(
f"=SIERREUR('Poule {pool2.short_name}'!$D{pool2.juries.count() + 10 + passage2.position}; 0)") f"=SIERREUR('Poule {pool2.short_name}'!$D{pool2.juries.count() + 10 + position2}; 0)")
line.append(tweak2.diff if tweak2 else 0) line.append(tweak2.diff if tweak2 else 0)
else: else:
# User has no second pool yet # User has no second pool yet
@ -936,13 +946,23 @@ class Pool(models.Model):
) )
letter = models.PositiveSmallIntegerField( letter = models.PositiveSmallIntegerField(
verbose_name=_('letter'),
choices=[ choices=[
(1, 'A'), (1, 'A'),
(2, 'B'), (2, 'B'),
(3, 'C'), (3, 'C'),
(4, 'D'), (4, 'D'),
], ],
verbose_name=_('letter'), )
room = models.PositiveSmallIntegerField(
verbose_name=_("room"),
choices=[
(1, _("Room 1")),
(2, _("Room 2")),
],
default=1,
help_text=_("For 5-teams pools only"),
) )
participations = models.ManyToManyField( participations = models.ManyToManyField(
@ -983,7 +1003,10 @@ class Pool(models.Model):
@property @property
def short_name(self): def short_name(self):
return f"{self.get_letter_display()}{self.round}" short_name = f"{self.get_letter_display()}{self.round}"
if self.participations.count() == 5:
short_name += f"{self.get_room_display()}"
return short_name
@property @property
def solutions(self): def solutions(self):
@ -1006,6 +1029,8 @@ class Pool(models.Model):
return super().validate_constraints() return super().validate_constraints()
def update_spreadsheet(self): # noqa: C901 def update_spreadsheet(self): # noqa: C901
translation.activate('fr')
# Create tournament sheet if it does not exist # Create tournament sheet if it does not exist
self.tournament.create_spreadsheet() self.tournament.create_spreadsheet()
@ -1085,18 +1110,38 @@ class Pool(models.Model):
ranking = [ ranking = [
["Équipe", "", "Problème", "Total", "Rang"], ["Équipe", "", "Problème", "Total", "Rang"],
] ]
for passage in passages: all_passages = Passage.objects.filter(pool__tournament=self.tournament,
pool__round=self.round,
pool__letter=self.letter).order_by('position', 'pool__room')
for i, passage in enumerate(all_passages):
participation = passage.defender participation = passage.defender
defender_pos = passage.position - 1 defender_passage = Passage.objects.get(defender=participation,
opponent_pos = passages.get(opponent=passage.defender).position - 1 pool__tournament=self.tournament, pool__round=self.round)
reporter_pos = passages.get(reporter=passage.defender).position - 1 defender_row = 5 + defender_passage.pool.juries.count()
defender_col = defender_passage.position - 1
opponent_passage = Passage.objects.get(opponent=participation,
pool__tournament=self.tournament, pool__round=self.round)
opponent_row = 5 + opponent_passage.pool.juries.count()
opponent_col = opponent_passage.position - 1
reporter_passage = Passage.objects.get(reporter=participation,
pool__tournament=self.tournament, pool__round=self.round)
reporter_row = 5 + reporter_passage.pool.juries.count()
reporter_col = reporter_passage.position - 1
formula = "=" formula = "="
formula += getcol(min_column + defender_pos * passage_width) + str(max_row + 3) # Defender formula += (f"'Poule {defender_passage.pool.short_name}'"
formula += " + " + getcol(min_column + opponent_pos * passage_width + 2) + str(max_row + 3) # Opponent f"!{getcol(min_column + defender_col * passage_width)}{defender_row + 3}") # Defender
formula += " + " + getcol(min_column + reporter_pos * passage_width + 4) + str(max_row + 3) # Reporter formula += (f" + 'Poule {opponent_passage.pool.short_name}'"
f"!{getcol(min_column + opponent_col * passage_width + 2)}{opponent_row + 3}") # Opponent
formula += (f" + 'Poule {reporter_passage.pool.short_name}'"
f"!{getcol(min_column + reporter_col * passage_width + 4)}{reporter_row + 3}") # Reporter
ranking.append([f"{participation.team.name} ({participation.team.trigram})", "", ranking.append([f"{participation.team.name} ({participation.team.trigram})", "",
f"=${getcol(3 + (passage.position - 1) * passage_width)}$1", formula, f"='Poule {defender_passage.pool.short_name}'"
f"=RANG(D{max_row + 5 + passage.position}; " f"!${getcol(3 + defender_col * passage_width)}$1",
formula,
f"=RANG(D{max_row + 6 + i}; "
f"D${max_row + 6}:D${max_row + 5 + pool_size})"]) f"D${max_row + 6}:D${max_row + 5 + pool_size})"])
all_values = header + notes + footer + ranking all_values = header + notes + footer + ranking
@ -1147,10 +1192,10 @@ class Pool(models.Model):
# Set background color for headers and footers # Set background color for headers and footers
bg_colors = [("A1:AF", (1, 1, 1)), bg_colors = [("A1:AF", (1, 1, 1)),
(f"A1:{getcol(2 + pool_size * passage_width)}3", (0.8, 0.8, 0.8)), (f"A1:{getcol(2 + passages.count() * passage_width)}3", (0.8, 0.8, 0.8)),
(f"A{min_row - 1}:B{max_row}", (0.95, 0.95, 0.95)), (f"A{min_row - 1}:B{max_row}", (0.95, 0.95, 0.95)),
(f"A{max_row + 1}:B{max_row + 3}", (0.8, 0.8, 0.8)), (f"A{max_row + 1}:B{max_row + 3}", (0.8, 0.8, 0.8)),
(f"C{max_row + 1}:{getcol(2 + pool_size * passage_width)}{max_row + 3}", (0.9, 0.9, 0.9)), (f"C{max_row + 1}:{getcol(2 + passages.count() * passage_width)}{max_row + 3}", (0.9, 0.9, 0.9)),
(f"A{max_row + 5}:E{max_row + 5}", (0.8, 0.8, 0.8)), (f"A{max_row + 5}:E{max_row + 5}", (0.8, 0.8, 0.8)),
(f"A{max_row + 6}:E{max_row + 5 + pool_size}", (0.9, 0.9, 0.9)),] (f"A{max_row + 6}:E{max_row + 5 + pool_size}", (0.9, 0.9, 0.9)),]
for bg_range, bg_color in bg_colors: for bg_range, bg_color in bg_colors:
@ -1233,11 +1278,11 @@ class Pool(models.Model):
# Define borders # Define borders
border_ranges = [("A1:AF", "0000"), border_ranges = [("A1:AF", "0000"),
(f"A1:{getcol(2 + pool_size * passage_width)}{max_row + 3}", "1111"), (f"A1:{getcol(2 + passages.count() * passage_width)}{max_row + 3}", "1111"),
(f"A{max_row + 5}:E{max_row + pool_size + 5}", "1111"), (f"A{max_row + 5}:E{max_row + pool_size + 5}", "1111"),
(f"A1:B{max_row + 3}", "1113"), (f"A1:B{max_row + 3}", "1113"),
(f"C1:{getcol(2 + (pool_size - 1) * passage_width)}1", "1113")] (f"C1:{getcol(2 + (passages.count() - 1) * passage_width)}1", "1113")]
for i in range(pool_size - 1): for i in range(passages.count() - 1):
border_ranges.append((f"{getcol(1 + (i + 1) * passage_width)}2" border_ranges.append((f"{getcol(1 + (i + 1) * passage_width)}2"
f":{getcol(2 + (i + 1) * passage_width)}2", "1113")) f":{getcol(2 + (i + 1) * passage_width)}2", "1113"))
border_ranges.append((f"{getcol(2 + (i + 1) * passage_width)}3" border_ranges.append((f"{getcol(2 + (i + 1) * passage_width)}3"
@ -1264,7 +1309,7 @@ class Pool(models.Model):
}) })
# Add range conditions # Add range conditions
for i in range(pool_size): for i in range(passages.count()):
for j in range(passage_width): for j in range(passage_width):
column = getcol(min_column + i * passage_width + j) column = getcol(min_column + i * passage_width + j)
min_note = 0 min_note = 0
@ -1286,9 +1331,9 @@ class Pool(models.Model):
}) })
# Set number format, display only one decimal # Set number format, display only one decimal
number_format_ranges = [f"C{max_row + 1}:{getcol(2 + passage_width * pool_size)}{max_row + 1}", number_format_ranges = [f"C{max_row + 1}:{getcol(2 + passage_width * passages.count())}{max_row + 1}",
f"C{max_row + 3}:{getcol(2 + passage_width * pool_size)}{max_row + 3}", f"C{max_row + 3}:{getcol(2 + passage_width * passages.count())}{max_row + 3}",
f"D{max_row + 6}:D{max_row + 5 + pool_size}",] f"D{max_row + 6}:D{max_row + 5 + passages.count()}",]
for number_format_range in number_format_ranges: for number_format_range in number_format_ranges:
format_requests.append({ format_requests.append({
"repeatCell": { "repeatCell": {
@ -1383,7 +1428,7 @@ class Pool(models.Model):
class Meta: class Meta:
verbose_name = _("pool") verbose_name = _("pool")
verbose_name_plural = _("pools") verbose_name_plural = _("pools")
ordering = ('round', 'letter',) ordering = ('round', 'letter', 'room',)
class Passage(models.Model): class Passage(models.Model):

View File

@ -91,7 +91,7 @@ class PoolTable(tables.Table):
) )
def render_letter(self, record): def render_letter(self, record):
return format_lazy(_("Pool {letter}{round}"), letter=record.get_letter_display(), round=record.round) return format_lazy(_("Pool {code}"), code=record.short_name)
def render_teams(self, record): def render_teams(self, record):
return ", ".join(participation.team.trigram for participation in record.participations.all()) \ return ", ".join(participation.team.trigram for participation in record.participations.all()) \

View File

@ -26,6 +26,11 @@
<dt class="col-sm-3">{% trans "Letter:" %}</dt> <dt class="col-sm-3">{% trans "Letter:" %}</dt>
<dd class="col-sm-9">{{ pool.get_letter_display }}</dd> <dd class="col-sm-9">{{ pool.get_letter_display }}</dd>
{% if pool.participations.count == 5 %}
<dt class="col-sm-3">{% trans "Room:" %}</dt>
<dd class="col-sm-9">{{ pool.get_room_display }}</dd>
{% endif %}
<dt class="col-sm-3">{% trans "Teams:" %}</dt> <dt class="col-sm-3">{% trans "Teams:" %}</dt>
<dd class="col-sm-9"> <dd class="col-sm-9">
{% for participation in pool.participations.all %} {% for participation in pool.participations.all %}
@ -82,22 +87,12 @@
<div class="btn-group"> <div class="btn-group">
<a class="btn btn-sm btn-info" href="{% url 'participation:pool_scale_note_sheet' pk=pool.pk %}"> <a class="btn btn-sm btn-info" href="{% url 'participation:pool_scale_note_sheet' pk=pool.pk %}">
<i class="fas fa-download"></i> <i class="fas fa-download"></i>
{% trans "Download the scale sheet" %}{% if pool.passages.count == 5 %} — {% trans "Room" %} 1{% endif %} {% trans "Download the scale sheet" %}
</a> </a>
{% if pool.passages.count == 5 %}
<a class="btn btn-info" href="{% url 'participation:pool_scale_note_sheet' pk=pool.pk %}?page=2">
{% trans "Room" %} 2
</a>
{% endif %}
<a class="btn btn-sm btn-info" href="{% url 'participation:pool_final_note_sheet' pk=pool.pk %}"> <a class="btn btn-sm btn-info" href="{% url 'participation:pool_final_note_sheet' pk=pool.pk %}">
<i class="fas fa-download"></i> <i class="fas fa-download"></i>
{% trans "Download the final notation sheet" %}{% if pool.passages.count == 5 %} — {% trans "Room" %} 1{% endif %} {% trans "Download the final notation sheet" %}
</a> </a>
{% if pool.passages.count == 5 %}
<a class="btn btn-sm btn-info" href="{% url 'participation:pool_final_note_sheet' pk=pool.pk %}?page=2">
{% trans "Room" %} 2
</a>
{% endif %}
<a class="btn btn-sm btn-info" href="{% url 'participation:pool_notation_sheets' pool_id=pool.id %}"> <a class="btn btn-sm btn-info" href="{% url 'participation:pool_notation_sheets' pool_id=pool.id %}">
<i class="fas fa-archive"></i> <i class="fas fa-archive"></i>
{% trans "Download all notation sheets" %} {% trans "Download all notation sheets" %}

View File

@ -37,14 +37,14 @@
\Large {\bf \tfjmedition$^{e}$ Tournoi Fran\c cais des Jeunes Math\'ematiciennes et Math\'ematiciens \tfjm}\\ \Large {\bf \tfjmedition$^{e}$ Tournoi Fran\c cais des Jeunes Math\'ematiciennes et Math\'ematiciens \tfjm}\\
\vspace{3mm} \vspace{3mm}
Tour {{ pool.round }} \;-- Poule {{ pool.get_letter_display }}{{ page }} \;-- {% if pool.round == 1 %}{{ pool.tournament.date_start }}{% else %}{{ pool.tournament.date_end }}{% endif %} Tour {{ pool.round }} \;-- Poule {{ pool.get_letter_display }}{% if pool.participations.count == 5 %} \;-- {{ pool.get_room_display }}{% endif %} \;-- {% if pool.round == 1 %}{{ pool.tournament.date_start }}{% else %}{{ pool.tournament.date_end }}{% endif %}
\vspace{15mm} \vspace{15mm}
\begin{tabular}{|p{35mm}{% for passage in passages.all %}{% if passages.count == 3 %}|p{3cm}|p{3cm}{% else %}|p{2.5cm}|p{2.5cm}{% endif %}{% endfor %}|}\hline \begin{tabular}{|p{40mm}{% for passage in passages.all %}{% if passages.count == 3 %}|p{3cm}|p{3cm}{% else %}|p{2.5cm}|p{2.5cm}{% endif %}{% endfor %}|}\hline
\multirow{2}{35mm}{\LARGE R\^ole} {% for passage in passages.all %}& \multicolumn{2}{c|}{ \Large Probl\`eme {{ passage.solution_number }}}{% endfor %} \\ \cline{2-{{ passages.count|add:passages.count|add:1 }}} \multirow{2}{40mm}{\LARGE R\^ole} {% for passage in passages.all %}& \multicolumn{2}{c|}{ \Large Probl\`eme {{ passage.solution_number }}}{% endfor %} \\ \cline{2-{{ passages.count|add:passages.count|add:1 }}}
{% for passage in passages.all %}& \hspace{4mm} {\Large \'ECRIT} & \hspace{4mm} {\Large ORAL}{% endfor %} \\ \hline {% for passage in passages.all %}& \hspace{4mm} {\Large \'ECRIT} & \hspace{4mm} {\Large ORAL}{% endfor %} \\ \hline
\multirow{2}{35mm}{\LARGE D\'efenseur\textperiodcentered{}se} {% for passage in passages.all %}& \multicolumn{2}{c|}{\Large {{ passage.defender.team.trigram }}}{% endfor %} \\ \cline{2-{{ passages.count|add:passages.count|add:1 }}} \multirow{2}{35mm}{\LARGE D\'efenseur\textperiodcentered{}se} {% for passage in passages.all %}& \multicolumn{2}{c|}{\Large {{ passage.defender.team.trigram }}}{% endfor %} \\ \cline{2-{{ passages.count|add:passages.count|add:1 }}}
{% for passage in passages.all %} {% for passage in passages.all %}

View File

@ -1760,13 +1760,6 @@ class NotationSheetTemplateView(VolunteerMixin, DetailView):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
passages = self.object.passages.all() passages = self.object.passages.all()
if passages.count() == 5:
page = self.request.GET.get('page', '1')
if not page.isnumeric() or page not in ['1', '2']:
page = '1'
passages = passages.filter(id__in=([passages[0].id, passages[2].id, passages[4].id]
if page == '1' else [passages[1].id, passages[3].id]))
context['page'] = page
context['passages'] = passages context['passages'] = passages
context['esp'] = passages.count() * '&' context['esp'] = passages.count() * '&'
@ -1841,44 +1834,36 @@ class NotationSheetsArchiveView(VolunteerMixin, DetailView):
for pool in pools: for pool in pools:
prefix = f"{pool.short_name}/" if len(pools) > 1 else "" prefix = f"{pool.short_name}/" if len(pools) > 1 else ""
for template_name in ['bareme', 'finale']: for template_name in ['bareme', 'finale']:
pages = [1] if pool.participations.count() < 5 else [1, 2] juries = list(pool.juries.all()) + [None]
for page in pages:
juries = list(pool.juries.all()) + [None]
for jury in juries: for jury in juries:
if jury is not None and template_name == "bareme": if jury is not None and template_name == "bareme":
continue continue
context = {'jury': jury, 'page': page, 'pool': pool, context = {'jury': jury, 'pool': pool,
'tfjm_number': timezone.now().year - 2010} 'tfjm_number': timezone.now().year - 2010}
passages = pool.passages.all() passages = pool.passages.all()
if passages.count() == 5: context['passages'] = passages
passages = passages.filter( context['esp'] = passages.count() * '&'
id__in=([passages[0].id, passages[2].id, passages[4].id]
if page == '1' else [passages[1].id, passages[3].id]))
context['passages'] = passages tex = render_to_string(f"participation/tex/{template_name}.tex",
context['esp'] = passages.count() * '&' context=context, request=self.request)
temp_dir = mkdtemp()
with open(os.path.join(temp_dir, "texput.tex"), "w") as f:
f.write(tex)
tex = render_to_string(f"participation/tex/{template_name}.tex", process = subprocess.Popen(
context=context, request=self.request) ["pdflatex", "-interaction=nonstopmode", f"-output-directory={temp_dir}",
temp_dir = mkdtemp() os.path.join(temp_dir, "texput.tex"), ])
with open(os.path.join(temp_dir, "texput.tex"), "w") as f: process.wait()
f.write(tex)
process = subprocess.Popen( sheet_name = f"Barème pour la poule {pool.short_name}" if template_name == "bareme" \
["pdflatex", "-interaction=nonstopmode", f"-output-directory={temp_dir}", else (f"Feuille de notation pour la poule {pool.short_name}"
os.path.join(temp_dir, "texput.tex"), ]) f" - {str(jury) if jury else 'Vierge'}")
process.wait()
sheet_name = f"Barème pour la poule {pool.short_name}" if template_name == "bareme" \ zf.write(os.path.join(temp_dir, "texput.pdf"),
else (f"Feuille de notation pour la poule {pool.short_name}" f"{prefix}{sheet_name}.pdf")
f" - {str(jury) if jury else 'Vierge'}")
sheet_name += " - page 2" if page == 2 else ""
zf.write(os.path.join(temp_dir, "texput.pdf"),
f"{prefix}{sheet_name}.pdf")
response = HttpResponse(content_type="application/zip") response = HttpResponse(content_type="application/zip")
response["Content-Disposition"] = f"attachment; filename=\"{filename}\"" response["Content-Disposition"] = f"attachment; filename=\"{filename}\""