Compare commits

...

4 Commits

Author SHA1 Message Date
Emmy D'Anello bacdd5cfcf
Replace pool name by its short name in severous views
Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
2024-04-18 15:12:45 +02:00
Emmy D'Anello 3e24e10780
Fix information display for participants in 5-teams pools
Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
2024-04-18 15:07:15 +02:00
Emmy D'Anello adc4634f3e
Better pool view for 5-teams pools
Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
2024-04-18 15:05:10 +02:00
Emmy D'Anello 266afaf5c9
Split 5-teams pols in two pools for each room
Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
2024-04-18 14:53:58 +02:00
9 changed files with 355 additions and 257 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-18 15:04+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:693
#: participation/models.py:680 participation/models.py:886 #: participation/models.py:717 participation/models.py:937
#: 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:941
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:949
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:1429
#: participation/models.py:1373 participation/tables.py:84 #: participation/models.py:1438 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:1430
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:927 participation/models.py:1579
#: participation/models.py:1544 participation/models.py:1586 #: participation/models.py:1609 participation/models.py:1651
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:1452
#: participation/models.py:1551 #: participation/models.py:1616
#, 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:708
#: 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:729
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:1459 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:1466
#: participation/models.py:1598 #: participation/models.py:1663
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:1473
#: participation/models.py:1599 #: participation/models.py:1664
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:1614
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:694 registration/admin.py:125
msgid "tournaments" msgid "tournaments"
msgstr "tournois" msgstr "tournois"
#: participation/models.py:686 #: participation/models.py:723
msgid "valid team" msgid "valid team"
msgstr "équipe valide" msgstr "équipe valide"
#: participation/models.py:687 #: participation/models.py:724
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:730
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:734
msgid "mention"
msgstr "mention"
#: participation/models.py:741
msgid "mention (final)"
msgstr "Mention (pour la finale) :"
#: participation/models.py:751
#, 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:758
#, 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:766
msgid "Missing payments" msgid "Missing payments"
msgstr "Paiements manquants" msgstr "Paiements manquants"
#: participation/models.py:732 #: participation/models.py:783
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:793 participation/models.py:807
msgid "Solutions due" msgid "Solutions due"
msgstr "Rendu des solutions" msgstr "Rendu des solutions"
#: participation/models.py:748 #: participation/models.py:799
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:813 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:819 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:830
#, 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:839 participation/models.py:882
#, 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:848 participation/models.py:891
#, 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:864 registration/models.py:622
msgid "First round" msgid "First round"
msgstr "Premier tour" msgstr "Premier tour"
#: participation/models.py:824 #: participation/models.py:875
#, 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:907 registration/models.py:633
msgid "Second round" msgid "Second round"
msgstr "Second tour" msgstr "Second tour"
#: participation/models.py:862 #: participation/models.py:913
#, 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:918
msgid "Tournament ended" msgid "Tournament ended"
msgstr "Tournoi terminé" msgstr "Tournoi terminé"
#: participation/models.py:877 participation/models.py:910 #: participation/models.py:928 participation/models.py:971
msgid "participations" msgid "participations"
msgstr "participations" msgstr "participations"
#: participation/models.py:892 participation/models.py:893 #: participation/models.py:943 participation/models.py:944
#, 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:959
msgid "room"
msgstr "salle"
#: participation/models.py:961
msgid "Room 1"
msgstr "Salle 1"
#: participation/models.py:962
msgid "Room 2"
msgstr "Salle 2"
#: participation/models.py:965
msgid "For 5-teams pools only"
msgstr "Pour les poules de 5 équipe uniquement"
#: participation/models.py:977
msgid "juries" msgid "juries"
msgstr "jurys" msgstr "jurys"
#: participation/models.py:925 #: participation/models.py:986
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:993
msgid "BigBlueButton URL" msgid "BigBlueButton URL"
msgstr "Lien BigBlueButton" msgstr "Lien BigBlueButton"
#: participation/models.py:933 #: participation/models.py:994
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:999
msgid "results available" msgid "results available"
msgstr "résultats disponibles" msgstr "résultats disponibles"
#: participation/models.py:939 #: participation/models.py:1000
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:1028
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:1410
#, 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:1423
#, python-brace-format #, python-brace-format
msgid "Pool of day {round} for tournament {tournament} with teams {teams}" msgid "Pool {code} for tournament {tournament} with teams {teams}"
msgstr "Poule du jour {round} du tournoi {tournament} avec les équipes {teams}" msgstr "Poule {code} du tournoi {tournament} avec les équipes {teams}"
#: participation/models.py:1378 #: participation/models.py:1443
msgid "position" msgid "position"
msgstr "position" msgstr "position"
#: participation/models.py:1385 #: participation/models.py:1450
msgid "defended solution" msgid "defended solution"
msgstr "solution défendue" msgstr "solution défendue"
#: participation/models.py:1413 #: participation/models.py:1478
msgid "penalties" msgid "penalties"
msgstr "pénalités" msgstr "pénalités"
#: participation/models.py:1415 #: participation/models.py:1480
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:1549 participation/models.py:1552
#: participation/models.py:1490 #: participation/models.py:1555
#, 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:1560
#, 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:1564 participation/models.py:1573
#: participation/models.py:1593 participation/models.py:1635 #: participation/models.py:1658 participation/models.py:1700
msgid "passage" msgid "passage"
msgstr "passage" msgstr "passage"
#: participation/models.py:1500 #: participation/models.py:1565
msgid "passages" msgid "passages"
msgstr "passages" msgstr "passages"
#: participation/models.py:1519 #: participation/models.py:1584
msgid "difference" msgid "difference"
msgstr "différence" msgstr "différence"
#: participation/models.py:1520 #: participation/models.py:1585
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:1592
msgid "tweak" msgid "tweak"
msgstr "harmonisation" msgstr "harmonisation"
#: participation/models.py:1528 #: participation/models.py:1593
msgid "tweaks" msgid "tweaks"
msgstr "harmonisations" msgstr "harmonisations"
#: participation/models.py:1556 #: participation/models.py:1621
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:1626 participation/models.py:1669
msgid "file" msgid "file"
msgstr "fichier" msgstr "fichier"
#: participation/models.py:1571 #: participation/models.py:1636
#, 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:1638
msgid "for final" msgid "for final"
msgstr "pour la finale" msgstr "pour la finale"
#: participation/models.py:1576 #: participation/models.py:1641
msgid "solution" msgid "solution"
msgstr "solution" msgstr "solution"
#: participation/models.py:1577 #: participation/models.py:1642
msgid "solutions" msgid "solutions"
msgstr "solutions" msgstr "solutions"
#: participation/models.py:1610 #: participation/models.py:1675
#, 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:1683
msgid "synthesis" msgid "synthesis"
msgstr "note de synthèse" msgstr "note de synthèse"
#: participation/models.py:1619 #: participation/models.py:1684
msgid "syntheses" msgid "syntheses"
msgstr "notes de synthèse" msgstr "notes de synthèse"
#: participation/models.py:1628 #: participation/models.py:1693
msgid "jury" msgid "jury"
msgstr "jury" msgstr "jury"
#: participation/models.py:1640 #: participation/models.py:1705
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:1711
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:1717
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:1723
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:1729
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:1735
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:1793
#, 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:1796
msgid "note" msgid "note"
msgstr "note" msgstr "note"
#: participation/models.py:1732 #: participation/models.py:1797
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,)
@ -135,7 +135,7 @@ class PassageAdmin(admin.ModelAdmin):
@admin.display(description=_("pool"), ordering='pool__letter') @admin.display(description=_("pool"), ordering='pool__letter')
def pool_abbr(self, record): def pool_abbr(self, record):
return f"{record.pool.get_letter_display()}{record.pool.round}" return f"{record.pool.short_name}"
@admin.display(description=_("tournament"), ordering='pool__tournament__name') @admin.display(description=_("tournament"), ordering='pool__tournament__name')
def tournament(self, record: Passage): def tournament(self, record: Passage):
@ -154,7 +154,7 @@ class NoteAdmin(admin.ModelAdmin):
@admin.display(description=_("pool")) @admin.display(description=_("pool"))
def pool(self, record): def pool(self, record):
return record.passage.pool.get_letter_display() return record.passage.pool.short_name
@admin.register(Solution) @admin.register(Solution)

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
@ -812,10 +822,9 @@ class Participation(models.Model):
'content': content, 'content': content,
}) })
elif timezone.now() <= tournament.syntheses_first_phase_limit + timedelta(hours=2): elif timezone.now() <= tournament.syntheses_first_phase_limit + timedelta(hours=2):
pool = self.pools.get(round=1, tournament=self.tournament) defender_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, defender=self)
defender_passage = pool.passages.get(defender=self) opponent_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, opponent=self)
opponent_passage = pool.passages.get(opponent=self) reporter_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, reporter=self)
reporter_passage = pool.passages.get(reporter=self)
defender_text = _("<p>The solutions draw is ended. You can check the result on " defender_text = _("<p>The solutions draw is ended. You can check the result on "
"<a href='{draw_url}'>this page</a>.</p>" "<a href='{draw_url}'>this page</a>.</p>"
@ -858,9 +867,9 @@ class Participation(models.Model):
}) })
elif timezone.now() <= tournament.syntheses_second_phase_limit + timedelta(hours=2): elif timezone.now() <= tournament.syntheses_second_phase_limit + timedelta(hours=2):
pool = self.pools.get(round=2, tournament=tournament) pool = self.pools.get(round=2, tournament=tournament)
defender_passage = pool.passages.get(defender=self) defender_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, defender=self)
opponent_passage = pool.passages.get(opponent=self) opponent_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, opponent=self)
reporter_passage = pool.passages.get(reporter=self) reporter_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, reporter=self)
defender_text = _("<p>For the second round, you will defend " defender_text = _("<p>For the second round, you will defend "
"<a href='{solution_url}'>your solution of the problem {problem}</a>.</p>") "<a href='{solution_url}'>your solution of the problem {problem}</a>.</p>")
@ -936,13 +945,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 +1002,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 +1028,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 +1109,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 +1191,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 +1277,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 +1308,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 +1330,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": {
@ -1375,15 +1419,15 @@ class Pool(models.Model):
note.save() note.save()
def __str__(self): def __str__(self):
return _("Pool of day {round} for tournament {tournament} with teams {teams}")\ return _("Pool {code} for tournament {tournament} with teams {teams}")\
.format(round=self.round, .format(code=self.short_name,
tournament=str(self.tournament), tournament=str(self.tournament),
teams=", ".join(participation.team.trigram for participation in self.participations.all())) teams=", ".join(participation.team.trigram for participation in self.participations.all()))
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

@ -25,6 +25,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">
@ -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

@ -632,7 +632,7 @@ class TournamentDetailView(MultiTableMixin, DetailView):
def get_tables(self): def get_tables(self):
return [ return [
ParticipationTable(self.object.participations.all()), ParticipationTable(self.object.participations.all()),
PoolTable(self.object.pools.order_by('id').all()), PoolTable(self.object.pools.all()),
] ]
@ -1030,7 +1030,7 @@ class SolutionsDownloadView(VolunteerMixin, View):
def prefix(s: Solution | Synthesis) -> str: def prefix(s: Solution | Synthesis) -> str:
pool = s.pool if is_solution else s.passage.pool pool = s.pool if is_solution else s.passage.pool
p = f"Poule {pool.get_letter_display()}{pool.round}/" p = f"Poule {pool.short_name}/"
if not is_solution: if not is_solution:
p += f"Passage {s.passage.position}/" p += f"Passage {s.passage.position}/"
return p return p
@ -1051,7 +1051,7 @@ class SolutionsDownloadView(VolunteerMixin, View):
syntheses = Synthesis.objects.filter(passage__pool=pool).all() syntheses = Synthesis.objects.filter(passage__pool=pool).all()
filename = _("Solutions for pool {pool} of tournament {tournament}.zip") \ filename = _("Solutions for pool {pool} of tournament {tournament}.zip") \
if is_solution else _("Syntheses for pool {pool} of tournament {tournament}.zip") if is_solution else _("Syntheses for pool {pool} of tournament {tournament}.zip")
filename = filename.format(pool=pool.get_letter_display() + str(pool.round), filename = filename.format(pool=pool.short_name,
tournament=pool.tournament.name) tournament=pool.tournament.name)
def prefix(s: Solution | Synthesis) -> str: def prefix(s: Solution | Synthesis) -> str:
@ -1093,7 +1093,7 @@ class PoolJuryView(VolunteerMixin, FormView, DetailView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context['title'] = _("Jury of pool {pool} for {tournament} with teams {teams}") \ context['title'] = _("Jury of pool {pool} for {tournament} with teams {teams}") \
.format(pool=f"{self.object.get_letter_display()}{self.object.round}", .format(pool=f"{self.object.short_name}",
tournament=self.object.tournament.name, tournament=self.object.tournament.name,
teams=", ".join(participation.team.trigram for participation in self.object.participations.all())) teams=", ".join(participation.team.trigram for participation in self.object.participations.all()))
return context return context
@ -1453,7 +1453,7 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
col_style.addElement(TableColumnProperties(columnwidth="2.6cm", breakbefore="auto")) col_style.addElement(TableColumnProperties(columnwidth="2.6cm", breakbefore="auto"))
doc.automaticstyles.addElement(col_style) doc.automaticstyles.addElement(col_style)
table = Table(name=f"Poule {self.object.get_letter_display()}{self.object.round}") table = Table(name=f"Poule {self.object.short_name}")
doc.spreadsheet.addElement(table) doc.spreadsheet.addElement(table)
table.addElement(TableColumn(stylename=first_col_style)) table.addElement(TableColumn(stylename=first_col_style))
@ -1736,7 +1736,7 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
return FileResponse(streaming_content=open("/tmp/notes.ods", "rb"), return FileResponse(streaming_content=open("/tmp/notes.ods", "rb"),
content_type="application/vnd.oasis.opendocument.spreadsheet", content_type="application/vnd.oasis.opendocument.spreadsheet",
filename=f"Feuille de notes - {self.object.tournament.name} " filename=f"Feuille de notes - {self.object.tournament.name} "
f"- Poule {self.object.get_letter_display()}{self.object.round}.ods") f"- Poule {self.object.short_name}.ods")
class NotationSheetTemplateView(VolunteerMixin, DetailView): class NotationSheetTemplateView(VolunteerMixin, DetailView):
@ -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}\""