1
0
mirror of https://gitlab.com/animath/si/plateforme.git synced 2024-12-02 16:06:54 +00:00

Compare commits

..

No commits in common. "dd397ae7c0288ac1ea76abd4c4e353f3d91086f6" and "2a298a3ee4bbd2dcbfdee2450a5d34f86eec3eac" have entirely different histories.

12 changed files with 195 additions and 492 deletions

View File

@ -508,8 +508,7 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
msg = _("The dice results are the following: {trigrams}. " msg = _("The dice results are the following: {trigrams}. "
"The passage order and the compositions of the different pools are displayed on the side. " "The passage order and the compositions of the different pools are displayed on the side. "
"The passage orders for the first round are determined from the dice scores, in increasing order. " "The passage orders for the first round are determined from the dice scores, in increasing order. "
"For the second round, the passage orders are determined from the passage orders of the first round.") \ "For the second round, the passage orders are determined from the passage orders of the first round.")
.format(trigrams=trigrams)
self.tournament.draw.last_message = msg self.tournament.draw.last_message = msg
await self.tournament.draw.asave() await self.tournament.draw.asave()

View File

@ -5,7 +5,6 @@ import os
from asgiref.sync import sync_to_async from asgiref.sync import sync_to_async
from django.conf import settings from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models from django.db import models
from django.db.models import QuerySet from django.db.models import QuerySet
@ -200,7 +199,7 @@ class Round(models.Model):
(3, _('Round 3'))], (3, _('Round 3'))],
verbose_name=_('number'), verbose_name=_('number'),
help_text=_("The number of the round, 1 or 2 (or 3 for ETEAM)"), help_text=_("The number of the round, 1 or 2 (or 3 for ETEAM)"),
validators=[MinValueValidator(1), MaxValueValidator(3)], validators=[MinValueValidator(1), MaxValueValidator(settings.NB_ROUNDS)],
) )
current_pool = models.ForeignKey( current_pool = models.ForeignKey(
@ -234,13 +233,6 @@ class Round(models.Model):
def __str__(self): def __str__(self):
return self.get_number_display() return self.get_number_display()
def clean(self):
if self.number is not None and self.number > settings.NB_ROUNDS:
raise ValidationError({'number': _("The number of the round must be between 1 and {nb}.")
.format(nb=settings.NB_ROUNDS)})
return super().clean()
class Meta: class Meta:
verbose_name = _('round') verbose_name = _('round')
verbose_name_plural = _('rounds') verbose_name_plural = _('rounds')
@ -400,11 +392,11 @@ class Pool(models.Model):
] ]
elif self.size == 5: elif self.size == 5:
table = [ table = [
[0, 2, 3, 4], [0, 2, 3],
[1, 3, 4, 0], [1, 3, 4],
[2, 4, 0, 1], [2, 4, 0],
[3, 0, 1, 2], [3, 0, 1],
[4, 1, 2, 3], [4, 1, 2],
] ]
for i, line in enumerate(table): for i, line in enumerate(table):
@ -416,20 +408,14 @@ class Pool(models.Model):
passage_pool = pool2 passage_pool = pool2
passage_position = 1 + i // 2 passage_position = 1 + i // 2
defender = tds[line[0]].participation
opponent = tds[line[1]].participation
reviewer = tds[line[2]].participation
observer = tds[line[3]].participation if self.size >= 4 and settings.TFJM_APP == "ETEAM" else None
# Create the passage # Create the passage
await Passage.objects.acreate( await Passage.objects.acreate(
pool=passage_pool, pool=passage_pool,
position=passage_position, position=passage_position,
solution_number=tds[line[0]].accepted, solution_number=tds[line[0]].accepted,
defender=defender, defender=tds[line[0]].participation,
opponent=opponent, opponent=tds[line[1]].participation,
reviewer=reviewer, reviewer=tds[line[2]].participation,
observer=observer,
defender_penalties=tds[line[0]].penalty_int, defender_penalties=tds[line[0]].penalty_int,
) )

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-07-05 11:45+0200\n" "POT-Creation-Date: 2024-07-05 10:48+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"
@ -77,9 +77,9 @@ msgid "Permission type that is required to write a message to a channel."
msgstr "Type de permission nécessaire pour écrire un message dans un canal." msgstr "Type de permission nécessaire pour écrire un message dans un canal."
#: chat/models.py:62 draw/admin.py:53 draw/admin.py:71 draw/admin.py:88 #: chat/models.py:62 draw/admin.py:53 draw/admin.py:71 draw/admin.py:88
#: draw/models.py:27 participation/admin.py:79 participation/admin.py:144 #: draw/models.py:26 participation/admin.py:79 participation/admin.py:140
#: participation/admin.py:176 participation/models.py:727 #: participation/admin.py:171 participation/models.py:727
#: participation/models.py:751 participation/models.py:1060 #: participation/models.py:751 participation/models.py:1012
#: registration/models.py:763 #: registration/models.py:763
#: registration/templates/registration/payment_form.html:53 #: registration/templates/registration/payment_form.html:53
msgid "tournament" msgid "tournament"
@ -93,9 +93,9 @@ msgstr ""
"Pour une permission qui concerne un tournoi, indique quel est le tournoi " "Pour une permission qui concerne un tournoi, indique quel est le tournoi "
"concerné." "concerné."
#: chat/models.py:73 draw/models.py:446 draw/models.py:473 #: chat/models.py:73 draw/models.py:432 draw/models.py:459
#: participation/admin.py:140 participation/admin.py:160 #: participation/admin.py:136 participation/admin.py:155
#: participation/models.py:1563 participation/models.py:1572 #: participation/models.py:1515 participation/models.py:1524
#: participation/tables.py:84 #: participation/tables.py:84
msgid "pool" msgid "pool"
msgstr "poule" msgstr "poule"
@ -108,7 +108,7 @@ msgstr ""
"concernée." "concernée."
#: chat/models.py:84 draw/templates/draw/tournament_content.html:277 #: chat/models.py:84 draw/templates/draw/tournament_content.html:277
#: participation/admin.py:172 participation/models.py:261 #: participation/admin.py:167 participation/models.py:261
#: participation/models.py:742 #: participation/models.py:742
#: participation/templates/participation/tournament_harmonize.html:15 #: participation/templates/participation/tournament_harmonize.html:15
#: registration/models.py:158 registration/models.py:754 #: registration/models.py:158 registration/models.py:754
@ -264,8 +264,8 @@ msgstr "Connexion"
msgid "teams" msgid "teams"
msgstr "équipes" msgstr "équipes"
#: draw/admin.py:92 draw/models.py:245 draw/models.py:465 #: draw/admin.py:92 draw/models.py:237 draw/models.py:451
#: participation/models.py:1064 #: participation/models.py:1016
msgid "round" msgid "round"
msgstr "tour" msgstr "tour"
@ -453,31 +453,31 @@ msgstr ""
msgid "The draw of the second round is starting!" msgid "The draw of the second round is starting!"
msgstr "Le tirage au sort du deuxième tour commence !" msgstr "Le tirage au sort du deuxième tour commence !"
#: draw/models.py:28 #: draw/models.py:27
msgid "The associated tournament." msgid "The associated tournament."
msgstr "Le tournoi associé." msgstr "Le tournoi associé."
#: draw/models.py:37 #: draw/models.py:36
msgid "current round" msgid "current round"
msgstr "tour actuel" msgstr "tour actuel"
#: draw/models.py:38 #: draw/models.py:37
msgid "The current round where teams select their problems." msgid "The current round where teams select their problems."
msgstr "Le tour en cours où les équipes choisissent leurs problèmes." msgstr "Le tour en cours où les équipes choisissent leurs problèmes."
#: draw/models.py:44 #: draw/models.py:43
msgid "last message" msgid "last message"
msgstr "dernier message" msgstr "dernier message"
#: draw/models.py:45 #: draw/models.py:44
msgid "The last message that is displayed on the drawing interface." msgid "The last message that is displayed on the drawing interface."
msgstr "Le dernier message qui est affiché sur l'interface de tirage." msgstr "Le dernier message qui est affiché sur l'interface de tirage."
#: draw/models.py:95 #: draw/models.py:94
msgid "State" msgid "State"
msgstr "État" msgstr "État"
#: draw/models.py:114 #: draw/models.py:113
msgid "" msgid ""
"We are going to start the problem draw.<br>You can ask any question if " "We are going to start the problem draw.<br>You can ask any question if "
"something is not clear or wrong.<br><br>We are going to first draw the pools " "something is not clear or wrong.<br><br>We are going to first draw the pools "
@ -490,7 +490,7 @@ msgstr ""
"toutes les équipes, puis pour chaque poule, nous allons tirer l'ordre de " "toutes les équipes, puis pour chaque poule, nous allons tirer l'ordre de "
"tirage et les problèmes." "tirage et les problèmes."
#: draw/models.py:119 #: draw/models.py:118
msgid "" msgid ""
"The captains, you can now all throw a 100-sided dice, by clicking on the big " "The captains, you can now all throw a 100-sided dice, by clicking on the big "
"dice button. The pools and the passage order during the first round will be " "dice button. The pools and the passage order during the first round will be "
@ -502,7 +502,7 @@ msgstr ""
"le premier tour seront l'ordre croissant des dés, c'est-à-dire que le plus " "le premier tour seront l'ordre croissant des dés, c'est-à-dire que le plus "
"petit dé passera en premier dans la poule A." "petit dé passera en premier dans la poule A."
#: draw/models.py:124 #: draw/models.py:123
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"We are going to start the problem draw for the pool <strong>{pool}</strong>, " "We are going to start the problem draw for the pool <strong>{pool}</strong>, "
@ -516,7 +516,7 @@ msgstr ""
"déterminer l'ordre de tirage. L'équipe avec le score le plus élevé tirera en " "déterminer l'ordre de tirage. L'équipe avec le score le plus élevé tirera en "
"premier." "premier."
#: draw/models.py:134 #: draw/models.py:133
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"The team <strong>{trigram}</strong> is going to draw a problem. Click on the " "The team <strong>{trigram}</strong> is going to draw a problem. Click on the "
@ -525,7 +525,7 @@ msgstr ""
"L'équipe <strong>{trigram}</strong> va tirer un problème. Cliquez sur l'urne " "L'équipe <strong>{trigram}</strong> va tirer un problème. Cliquez sur l'urne "
"au milieu pour tirer un problème." "au milieu pour tirer un problème."
#: draw/models.py:140 #: draw/models.py:139
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"The team <strong>{trigram}</strong> drew the problem <strong>{problem}: " "The team <strong>{trigram}</strong> drew the problem <strong>{problem}: "
@ -534,7 +534,7 @@ msgstr ""
"L'équipe <strong>{trigram}</strong> a tiré le problème <strong>{problem} : " "L'équipe <strong>{trigram}</strong> a tiré le problème <strong>{problem} : "
"{problem_name}</strong>." "{problem_name}</strong>."
#: draw/models.py:146 #: draw/models.py:145
msgid "" msgid ""
"It already refused this problem before, so it can refuse it without penalty " "It already refused this problem before, so it can refuse it without penalty "
"and draw a new problem immediately, or change its mind." "and draw a new problem immediately, or change its mind."
@ -542,24 +542,24 @@ msgstr ""
"Elle a déjà refusé ce problème auparavant, donc elle peut le refuser sans " "Elle a déjà refusé ce problème auparavant, donc elle peut le refuser sans "
"pénalité et tirer un nouveau problème immédiatement, ou changer d'avis." "pénalité et tirer un nouveau problème immédiatement, ou changer d'avis."
#: draw/models.py:150 #: draw/models.py:149
msgid "It can decide to accept or refuse this problem." msgid "It can decide to accept or refuse this problem."
msgstr "Elle peut décider d'accepter ou de refuser ce problème." msgstr "Elle peut décider d'accepter ou de refuser ce problème."
#: draw/models.py:152 #: draw/models.py:151
msgid "" msgid ""
"Refusing this problem will add a new 25% penalty on the coefficient of the " "Refusing this problem will add a new 25% penalty on the coefficient of "
"oral defense." "the oral defense."
msgstr "" msgstr ""
"Refuser ce problème ajoutera une nouvelle pénalité de 25nbsp;% sur le " "Refuser ce problème ajoutera une nouvelle pénalité de 25nbsp;% sur le "
"coefficient de l'oral de la défense." "coefficient de l'oral de la défense."
#: draw/models.py:155 #: draw/models.py:154
#, python-brace-format #, python-brace-format
msgid "There are still {remaining} refusals without penalty." msgid "There are still {remaining} refusals without penalty."
msgstr "Il reste {remaining} refus sans pénalité." msgstr "Il reste {remaining} refus sans pénalité."
#: draw/models.py:159 #: draw/models.py:158
msgid "" msgid ""
"The draw for the second round will take place at the end of the first round. " "The draw for the second round will take place at the end of the first round. "
"Good luck!" "Good luck!"
@ -567,7 +567,7 @@ msgstr ""
"Le tirage au sort du deuxième tour aura lieu à la fin du premier tour. Bonne " "Le tirage au sort du deuxième tour aura lieu à la fin du premier tour. Bonne "
"chance !" "chance !"
#: draw/models.py:162 #: draw/models.py:161
msgid "" msgid ""
"The draw is ended. The solutions of the other teams can be found in the tab " "The draw is ended. The solutions of the other teams can be found in the tab "
"\"My participation\"." "\"My participation\"."
@ -575,7 +575,7 @@ msgstr ""
"Le tirage est terminé. Les solutions des autres équipes peuvent être " "Le tirage est terminé. Les solutions des autres équipes peuvent être "
"trouvées dans l'onglet « Ma participation »." "trouvées dans l'onglet « Ma participation »."
#: draw/models.py:167 #: draw/models.py:166
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"For more details on the draw, the rules are available on <a class=\"alert-" "For more details on the draw, the rules are available on <a class=\"alert-"
@ -584,159 +584,154 @@ msgstr ""
"Pour plus de détails sur le tirage, les règles sont disponibles sur <a " "Pour plus de détails sur le tirage, les règles sont disponibles sur <a "
"class=\"alert-link\" href=\"{link}\">{link}</a>." "class=\"alert-link\" href=\"{link}\">{link}</a>."
#: draw/models.py:178 #: draw/models.py:177
#, python-brace-format #, python-brace-format
msgid "Draw of tournament {tournament}" msgid "Draw of tournament {tournament}"
msgstr "Tirage au sort du tournoi {tournament}" msgstr "Tirage au sort du tournoi {tournament}"
#: draw/models.py:181 draw/models.py:193 #: draw/models.py:180 draw/models.py:192
msgid "draw" msgid "draw"
msgstr "tirage au sort" msgstr "tirage au sort"
#: draw/models.py:182 #: draw/models.py:181
msgid "draws" msgid "draws"
msgstr "tirages au sort" msgstr "tirages au sort"
#: draw/models.py:198 #: draw/models.py:197
msgid "Round 1" msgid "Round 1"
msgstr "Tour 1" msgstr "Tour 1"
#: draw/models.py:199 #: draw/models.py:198
msgid "Round 2" msgid "Round 2"
msgstr "Tour 2" msgstr "Tour 2"
#: draw/models.py:200 #: draw/models.py:199
msgid "Round 3" msgid "Round 3"
msgstr "Tour 3" msgstr "Tour 3"
#: draw/models.py:201 #: draw/models.py:200
msgid "number" msgid "number"
msgstr "numéro" msgstr "numéro"
#: draw/models.py:202 #: draw/models.py:201
msgid "The number of the round, 1 or 2 (or 3 for ETEAM)" msgid "The number of the round, 1 or 2 (or 3 for ETEAM)"
msgstr "Le numéro du tour, 1 ou 2 (ou 3 pour ETEAM)" msgstr "Le numéro du tour, 1 ou 2 (ou 3 pour ETEAM)"
#: draw/models.py:212 #: draw/models.py:211
msgid "current pool" msgid "current pool"
msgstr "poule actuelle" msgstr "poule actuelle"
#: draw/models.py:213 #: draw/models.py:212
msgid "The current pool where teams select their problems." msgid "The current pool where teams select their problems."
msgstr "La poule en cours, où les équipes choisissent leurs problèmes" msgstr "La poule en cours, où les équipes choisissent leurs problèmes"
#: draw/models.py:239 #: draw/models.py:238
#, python-brace-format
msgid "The number of the round must be between 1 and {nb}."
msgstr "Le numéro du tour doit être entre 1 et {nb}."
#: draw/models.py:246
msgid "rounds" msgid "rounds"
msgstr "tours" msgstr "tours"
#: draw/models.py:268 participation/models.py:1072 #: draw/models.py:260 participation/models.py:1024
msgid "letter" msgid "letter"
msgstr "lettre" msgstr "lettre"
#: draw/models.py:269 #: draw/models.py:261
msgid "The letter of the pool: A, B, C or D." msgid "The letter of the pool: A, B, C or D."
msgstr "La lettre de la poule : A, B, C ou D." msgstr "La lettre de la poule : A, B, C ou D."
#: draw/models.py:273 #: draw/models.py:265
#: participation/templates/participation/tournament_detail.html:15 #: participation/templates/participation/tournament_detail.html:15
msgid "size" msgid "size"
msgstr "taille" msgstr "taille"
#: draw/models.py:275 #: draw/models.py:267
msgid "The number of teams in this pool, between 3 and 5." msgid "The number of teams in this pool, between 3 and 5."
msgstr "Le nombre d'équipes dans la poule, entre 3 et 5." msgstr "Le nombre d'équipes dans la poule, entre 3 et 5."
#: draw/models.py:284 #: draw/models.py:276
msgid "current team" msgid "current team"
msgstr "équipe actuelle" msgstr "équipe actuelle"
#: draw/models.py:285 #: draw/models.py:277
msgid "The current team that is selecting its problem." msgid "The current team that is selecting its problem."
msgstr "L'équipe qui est en train de choisir son problème." msgstr "L'équipe qui est en train de choisir son problème."
#: draw/models.py:294 #: draw/models.py:286
msgid "associated pool" msgid "associated pool"
msgstr "poule associée" msgstr "poule associée"
#: draw/models.py:295 #: draw/models.py:287
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:443 #: draw/models.py:429
#, 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:447 participation/models.py:1564 #: draw/models.py:433 participation/models.py:1516
msgid "pools" msgid "pools"
msgstr "poules" msgstr "poules"
#: draw/models.py:459 participation/models.py:1050 participation/models.py:1754 #: draw/models.py:445 participation/models.py:1002 participation/models.py:1665
#: participation/models.py:1784 participation/models.py:1826 #: participation/models.py:1695 participation/models.py:1737
msgid "participation" msgid "participation"
msgstr "participation" msgstr "participation"
#: draw/models.py:480 #: draw/models.py:466
msgid "passage index" msgid "passage index"
msgstr "numéro de passage" msgstr "numéro de passage"
#: draw/models.py:481 #: draw/models.py:467
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:489 #: draw/models.py:475
msgid "choose index" msgid "choose index"
msgstr "numéro de choix" msgstr "numéro de choix"
#: draw/models.py:490 #: draw/models.py:476
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:496 draw/models.py:519 participation/models.py:1586 #: draw/models.py:482 draw/models.py:505 participation/models.py:1538
#: participation/models.py:1791 #: participation/models.py:1702
#, 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:500 #: draw/models.py:486
msgid "accepted problem" msgid "accepted problem"
msgstr "problème accepté" msgstr "problème accepté"
#: draw/models.py:507 #: draw/models.py:493
msgid "passage dice" msgid "passage dice"
msgstr "dé d'ordre de passage" msgstr "dé d'ordre de passage"
#: draw/models.py:514 #: draw/models.py:500
msgid "choice dice" msgid "choice dice"
msgstr "dé d'ordre de choix" msgstr "dé d'ordre de choix"
#: draw/models.py:523 #: draw/models.py:509
msgid "purposed problem" msgid "purposed problem"
msgstr "problème proposé" msgstr "problème proposé"
#: draw/models.py:528 #: draw/models.py:514
msgid "rejected problems" msgid "rejected problems"
msgstr "problèmes rejetés" msgstr "problèmes rejetés"
#: draw/models.py:557 #: draw/models.py:543
#, 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:563 #: draw/models.py:549
msgid "team draw" msgid "team draw"
msgstr "tirage d'équipe" msgstr "tirage d'équipe"
#: draw/models.py:564 #: draw/models.py:550
msgid "team draws" msgid "team draws"
msgstr "tirages d'équipe" msgstr "tirages d'équipe"
@ -917,27 +912,22 @@ msgstr "valide"
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:188 #: participation/admin.py:124 participation/admin.py:183
#: participation/models.py:1593 participation/tables.py:114 #: participation/models.py:1545 participation/tables.py:112
msgid "defender" msgid "defender"
msgstr "défenseur⋅se" msgstr "défenseur⋅se"
#: participation/admin.py:128 participation/models.py:1600 #: participation/admin.py:128 participation/models.py:1552
#: participation/models.py:1838 #: participation/models.py:1749
msgid "opponent" msgid "opponent"
msgstr "opposant⋅e" msgstr "opposant⋅e"
#: participation/admin.py:132 participation/models.py:1607 #: participation/admin.py:132 participation/models.py:1559
#: participation/models.py:1839 #: participation/models.py:1750
msgid "reviewer" msgid "reviewer"
msgstr "rapporteur⋅rice" msgstr "rapporteur⋅rice"
#: participation/admin.py:136 participation/models.py:1614 #: participation/admin.py:187 participation/models.py:1700
#: participation/models.py:1840
msgid "observer"
msgstr "observateur⋅rice"
#: participation/admin.py:192 participation/models.py:1789
msgid "problem" msgid "problem"
msgstr "numéro de problème" msgstr "numéro de problème"
@ -1379,7 +1369,7 @@ msgstr ""
msgid "Draw of solutions" msgid "Draw of solutions"
msgstr "Tirage au sort des solutions" msgstr "Tirage au sort des solutions"
#: participation/models.py:865 #: participation/models.py:863
#, 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 "
@ -1391,8 +1381,8 @@ 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:874 participation/models.py:932 #: participation/models.py:872 participation/models.py:914
#: participation/models.py:991 #: participation/models.py:957
#, 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 "
@ -1403,8 +1393,8 @@ 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:883 participation/models.py:941 #: participation/models.py:881 participation/models.py:923
#: participation/models.py:1000 #: participation/models.py:966
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"<p>You will report the solution of the team {reviewer} on the <a " "<p>You will report the solution of the team {reviewer} on the <a "
@ -1415,23 +1405,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:893 participation/models.py:951 #: participation/models.py:897 registration/models.py:629
#: participation/models.py:1010
#, python-brace-format
msgid ""
"<p>You will observe the solution of the team {observer} on the <a "
"href='{solution_url}'>problem {problem}. You can upload your synthesis sheet "
"on <a href='{passage_url}'>this page</a>.</p>"
msgstr ""
"<p>Vous observerez la solution de l'équipe {observer} sur le <a "
"href='{solution_url}'>problème {problem}</a>. Vous pouvez envoyer votre note "
"de synthèse sur <a href='{passage_url}'>cette page</a>.</p>"
#: participation/models.py:913 registration/models.py:629
msgid "First round" msgid "First round"
msgstr "Premier tour" msgstr "Premier tour"
#: participation/models.py:925 #: participation/models.py:907
#, 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 "
@ -1440,12 +1418,12 @@ 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:971 participation/models.py:1030 #: participation/models.py:939 participation/models.py:982
#: registration/models.py:640 #: registration/models.py:640
msgid "Second round" msgid "Second round"
msgstr "Second tour" msgstr "Second tour"
#: participation/models.py:984 #: participation/models.py:950
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"<p>For the third round, you will defend <a href='{solution_url}'>your " "<p>For the third round, you will defend <a href='{solution_url}'>your "
@ -1454,7 +1432,7 @@ msgstr ""
"<p>Pour le troisième tour, vous défendrez <a href='{solution_url}'>votre " "<p>Pour le troisième 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:1036 #: participation/models.py:988
#, 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 "
@ -1463,57 +1441,57 @@ 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:1041 #: participation/models.py:993
msgid "Tournament ended" msgid "Tournament ended"
msgstr "Tournoi terminé" msgstr "Tournoi terminé"
#: participation/models.py:1051 participation/models.py:1094 #: participation/models.py:1003 participation/models.py:1046
msgid "participations" msgid "participations"
msgstr "participations" msgstr "participations"
#: participation/models.py:1066 participation/models.py:1067 #: participation/models.py:1018 participation/models.py:1019
#: participation/models.py:1068 #: participation/models.py:1020
#, python-brace-format #, python-brace-format
msgid "Round {round}" msgid "Round {round}"
msgstr "Tour {round}" msgstr "Tour {round}"
#: participation/models.py:1082 #: participation/models.py:1034
msgid "room" msgid "room"
msgstr "salle" msgstr "salle"
#: participation/models.py:1084 #: participation/models.py:1036
msgid "Room 1" msgid "Room 1"
msgstr "Salle 1" msgstr "Salle 1"
#: participation/models.py:1085 #: participation/models.py:1037
msgid "Room 2" msgid "Room 2"
msgstr "Salle 2" msgstr "Salle 2"
#: participation/models.py:1088 #: participation/models.py:1040
msgid "For 5-teams pools only" msgid "For 5-teams pools only"
msgstr "Pour les poules de 5 équipe uniquement" msgstr "Pour les poules de 5 équipe uniquement"
#: participation/models.py:1100 #: participation/models.py:1052
msgid "juries" msgid "juries"
msgstr "jurys" msgstr "jurys"
#: participation/models.py:1109 #: participation/models.py:1061
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:1116 #: participation/models.py:1068
msgid "BigBlueButton URL" msgid "BigBlueButton URL"
msgstr "Lien BigBlueButton" msgstr "Lien BigBlueButton"
#: participation/models.py:1117 #: participation/models.py:1069
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:1122 #: participation/models.py:1074
msgid "results available" msgid "results available"
msgstr "résultats disponibles" msgstr "résultats disponibles"
#: participation/models.py:1123 #: participation/models.py:1075
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."
@ -1522,33 +1500,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:1155 #: participation/models.py:1107
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:1544 #: participation/models.py:1496
#, 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:1557 #: participation/models.py:1509
#, python-brace-format #, python-brace-format
msgid "Pool {code} for tournament {tournament} with teams {teams}" msgid "Pool {code} for tournament {tournament} with teams {teams}"
msgstr "Poule {code} du tournoi {tournament} avec les équipes {teams}" msgstr "Poule {code} du tournoi {tournament} avec les équipes {teams}"
#: participation/models.py:1577 #: participation/models.py:1529
msgid "position" msgid "position"
msgstr "position" msgstr "position"
#: participation/models.py:1584 #: participation/models.py:1536
msgid "defended solution" msgid "defended solution"
msgstr "solution défendue" msgstr "solution défendue"
#: participation/models.py:1622 #: participation/models.py:1564
msgid "penalties" msgid "penalties"
msgstr "pénalités" msgstr "pénalités"
#: participation/models.py:1624 #: participation/models.py:1566
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."
@ -1556,128 +1534,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:1721 participation/models.py:1724 #: participation/models.py:1635 participation/models.py:1638
#: participation/models.py:1727 participation/models.py:1730 #: participation/models.py:1641
#, 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:1735 #: participation/models.py:1646
#, 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:1739 participation/models.py:1748 #: participation/models.py:1650 participation/models.py:1659
#: participation/models.py:1833 participation/models.py:1876 #: participation/models.py:1744 participation/models.py:1786
msgid "passage" msgid "passage"
msgstr "passage" msgstr "passage"
#: participation/models.py:1740 #: participation/models.py:1651
msgid "passages" msgid "passages"
msgstr "passages" msgstr "passages"
#: participation/models.py:1759 #: participation/models.py:1670
msgid "difference" msgid "difference"
msgstr "différence" msgstr "différence"
#: participation/models.py:1760 #: participation/models.py:1671
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:1767 #: participation/models.py:1678
msgid "tweak" msgid "tweak"
msgstr "harmonisation" msgstr "harmonisation"
#: participation/models.py:1768 #: participation/models.py:1679
msgid "tweaks" msgid "tweaks"
msgstr "harmonisations" msgstr "harmonisations"
#: participation/models.py:1796 #: participation/models.py:1707
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:1801 participation/models.py:1845 #: participation/models.py:1712 participation/models.py:1755
msgid "file" msgid "file"
msgstr "fichier" msgstr "fichier"
#: participation/models.py:1811 #: participation/models.py:1722
#, 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:1813 #: participation/models.py:1724
msgid "for final" msgid "for final"
msgstr "pour la finale" msgstr "pour la finale"
#: participation/models.py:1816 #: participation/models.py:1727
msgid "solution" msgid "solution"
msgstr "solution" msgstr "solution"
#: participation/models.py:1817 #: participation/models.py:1728
msgid "solutions" msgid "solutions"
msgstr "solutions" msgstr "solutions"
#: participation/models.py:1851 #: participation/models.py:1761
#, 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:1859 #: participation/models.py:1769
msgid "synthesis" msgid "synthesis"
msgstr "note de synthèse" msgstr "note de synthèse"
#: participation/models.py:1860 #: participation/models.py:1770
msgid "syntheses" msgid "syntheses"
msgstr "notes de synthèse" msgstr "notes de synthèse"
#: participation/models.py:1869 #: participation/models.py:1779
msgid "jury" msgid "jury"
msgstr "jury" msgstr "jury"
#: participation/models.py:1881 #: participation/models.py:1791
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:1887 #: participation/models.py:1797
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:1893 #: participation/models.py:1803
msgid "opponent writing note" msgid "opponent writing note"
msgstr "note d'écrit opposant⋅e" msgstr "note d'écrit opposant⋅e"
#: participation/models.py:1899 #: participation/models.py:1809
msgid "opponent oral note" msgid "opponent oral note"
msgstr "note d'oral opposant⋅e" msgstr "note d'oral opposant⋅e"
#: participation/models.py:1905 #: participation/models.py:1815
msgid "reviewer writing note" msgid "reviewer writing note"
msgstr "note d'écrit rapporteur⋅rice" msgstr "note d'écrit rapporteur⋅rice"
#: participation/models.py:1911 #: participation/models.py:1821
msgid "reviewer oral note" msgid "reviewer oral note"
msgstr "note d'oral du rapporteur⋅rice" msgstr "note d'oral du rapporteur⋅rice"
#: participation/models.py:1917 #: participation/models.py:1881
msgid "observer writing note"
msgstr "note d'écrit de l'observateur⋅rice"
#: participation/models.py:1923
msgid "observer oral note"
msgstr "note d'oral de l'observateur⋅rice"
#: participation/models.py:1988
#, 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:1991 #: participation/models.py:1884
msgid "note" msgid "note"
msgstr "note" msgstr "note"
#: participation/models.py:1992 #: participation/models.py:1885
msgid "notes" msgid "notes"
msgstr "notes" msgstr "notes"
@ -1715,11 +1685,11 @@ msgstr "Poule {code}"
msgid "No defined team" msgid "No defined team"
msgstr "Pas d'équipe définie" msgstr "Pas d'équipe définie"
#: participation/tables.py:147 #: participation/tables.py:142
#: participation/templates/participation/note_form.html:14 #: participation/templates/participation/note_form.html:14
#: participation/templates/participation/passage_detail.html:15 #: participation/templates/participation/passage_detail.html:15
#: participation/templates/participation/passage_detail.html:168 #: participation/templates/participation/passage_detail.html:140
#: participation/templates/participation/passage_detail.html:174 #: 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:152 #: participation/templates/participation/pool_detail.html:152
#: participation/templates/participation/team_detail.html:185 #: participation/templates/participation/team_detail.html:185
@ -1807,7 +1777,7 @@ msgid "Upload solution"
msgstr "Envoyer une solution" msgstr "Envoyer une solution"
#: participation/templates/participation/participation_detail.html:65 #: participation/templates/participation/participation_detail.html:65
#: participation/templates/participation/passage_detail.html:180 #: participation/templates/participation/passage_detail.html:152
#: participation/templates/participation/pool_detail.html:157 #: participation/templates/participation/pool_detail.html:157
#: participation/templates/participation/team_detail.html:245 #: participation/templates/participation/team_detail.html:245
#: participation/templates/participation/upload_motivation_letter.html:13 #: participation/templates/participation/upload_motivation_letter.html:13
@ -1844,94 +1814,78 @@ msgid "Opponent:"
msgstr "Opposant⋅e :" msgstr "Opposant⋅e :"
#: participation/templates/participation/passage_detail.html:34 #: participation/templates/participation/passage_detail.html:34
msgid "Reviewer:" msgid "reviewer:"
msgstr "Rapporteur⋅rice :" msgstr "Rapporteur⋅rice :"
#: participation/templates/participation/passage_detail.html:38 #: participation/templates/participation/passage_detail.html:37
msgid "Observer:"
msgstr "Observateur⋅rice :"
#: participation/templates/participation/passage_detail.html:42
msgid "Defended solution:" msgid "Defended solution:"
msgstr "Solution défendue" msgstr "Solution défendue"
#: participation/templates/participation/passage_detail.html:45 #: participation/templates/participation/passage_detail.html:40
msgid "Defender penalties count:" msgid "Defender penalties count:"
msgstr "Nombre de pénalités :" msgstr "Nombre de pénalités :"
#: participation/templates/participation/passage_detail.html:48 #: participation/templates/participation/passage_detail.html:43
#: participation/templates/participation/pool_detail.html:59 #: 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:53 #: participation/templates/participation/passage_detail.html:48
#: participation/templates/participation/pool_detail.html:68 #: 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."
#: participation/templates/participation/passage_detail.html:61 #: participation/templates/participation/passage_detail.html:56
#: participation/templates/participation/passage_detail.html:173 #: participation/templates/participation/passage_detail.html:145
msgid "Update notes" msgid "Update notes"
msgstr "Modifier les notes" msgstr "Modifier les notes"
#: participation/templates/participation/passage_detail.html:66 #: participation/templates/participation/passage_detail.html:61
#: participation/templates/participation/passage_detail.html:179 #: participation/templates/participation/passage_detail.html:151
msgid "Upload synthesis" msgid "Upload synthesis"
msgstr "Envoyer une note de synthèse" msgstr "Envoyer une note de synthèse"
#: participation/templates/participation/passage_detail.html:74 #: participation/templates/participation/passage_detail.html:69
msgid "Notes detail" msgid "Notes detail"
msgstr "Détails des notes" msgstr "Détails des notes"
#: participation/templates/participation/passage_detail.html:82 #: participation/templates/participation/passage_detail.html:77
msgid "Average points for the defender writing" msgid "Average points for the defender writing"
msgstr "Moyenne de l'écrit de l'équipe défenseuse" msgstr "Moyenne de l'écrit de l'équipe défenseuse"
#: participation/templates/participation/passage_detail.html:88 #: participation/templates/participation/passage_detail.html:83
msgid "Average points for the defender oral" msgid "Average points for the defender oral"
msgstr "Moyenne de l'oral de l'équipe défenseuse" msgstr "Moyenne de l'oral de l'équipe défenseuse"
#: participation/templates/participation/passage_detail.html:94 #: participation/templates/participation/passage_detail.html:89
msgid "Average points for the opponent writing" msgid "Average points for the opponent writing"
msgstr "Moyenne de l'écrit de l'équipe opposante" msgstr "Moyenne de l'écrit de l'équipe opposante"
#: participation/templates/participation/passage_detail.html:100 #: participation/templates/participation/passage_detail.html:95
msgid "Average points for the opponent oral" msgid "Average points for the opponent oral"
msgstr "Moyenne de l'oral de l'équipe opposante" msgstr "Moyenne de l'oral de l'équipe opposante"
#: participation/templates/participation/passage_detail.html:106 #: participation/templates/participation/passage_detail.html:101
msgid "Average points for the reviewer writing" msgid "Average points for the reviewer writing"
msgstr "Moyenne de l'écrit de l'équipe rapportrice" msgstr "Moyenne de l'écrit de l'équipe rapportrice"
#: participation/templates/participation/passage_detail.html:112 #: participation/templates/participation/passage_detail.html:107
msgid "Average points for the reviewer oral" msgid "Average points for the reviewer oral"
msgstr "Moyenne de l'oral de l'équipe rapportrice" msgstr "Moyenne de l'oral de l'équipe rapportrice"
#: participation/templates/participation/passage_detail.html:119 #: participation/templates/participation/passage_detail.html:117
msgid "Average points for the observer writing"
msgstr "Moyenne de l'écrit de l'équipe observatrice"
#: participation/templates/participation/passage_detail.html:125
msgid "Average points for the observer oral"
msgstr "Moyenne de l'oral de l'équipe observatrice"
#: participation/templates/participation/passage_detail.html:136
msgid "Defender points" msgid "Defender points"
msgstr "Points de l'équipe défenseuse" msgstr "Points de l'équipe défenseuse"
#: participation/templates/participation/passage_detail.html:142 #: participation/templates/participation/passage_detail.html:123
msgid "Opponent points" msgid "Opponent points"
msgstr "Points de l'équipe opposante" msgstr "Points de l'équipe opposante"
#: participation/templates/participation/passage_detail.html:148 #: participation/templates/participation/passage_detail.html:129
msgid "reviewer points" msgid "reviewer points"
msgstr "Points de l'équipe rapportrice" msgstr "Points de l'équipe rapportrice"
#: participation/templates/participation/passage_detail.html:155 #: participation/templates/participation/passage_detail.html:139
msgid "observer points"
msgstr "Points de l'équipe observatrice"
#: participation/templates/participation/passage_detail.html:167
#: participation/templates/participation/passage_form.html:11 #: participation/templates/participation/passage_form.html:11
msgid "Update passage" msgid "Update passage"
msgstr "Modifier le passage" msgstr "Modifier le passage"
@ -2625,7 +2579,7 @@ msgstr "Feuilles de notations pour la poule {pool} du tournoi {tournament}.zip"
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:2017 #: participation/views.py:2015
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

@ -51,7 +51,7 @@ class PassageInline(admin.TabularInline):
model = Passage model = Passage
extra = 0 extra = 0
ordering = ('position',) ordering = ('position',)
autocomplete_fields = ('defender', 'opponent', 'reviewer', 'observer',) autocomplete_fields = ('defender', 'opponent', 'reviewer',)
show_change_link = True show_change_link = True
@ -114,11 +114,11 @@ class PoolAdmin(admin.ModelAdmin):
@admin.register(Passage) @admin.register(Passage)
class PassageAdmin(admin.ModelAdmin): class PassageAdmin(admin.ModelAdmin):
list_display = ('__str__', 'defender_trigram', 'solution_number', 'opponent_trigram', 'reviewer_trigram', list_display = ('__str__', 'defender_trigram', 'solution_number', 'opponent_trigram', 'reviewer_trigram',
'observer_trigram', 'pool_abbr', 'position', 'tournament') 'pool_abbr', 'position', 'tournament')
list_filter = ('pool__tournament', 'pool__round', 'pool__letter', 'solution_number',) list_filter = ('pool__tournament', 'pool__round', 'pool__letter', 'solution_number',)
search_fields = ('pool__participations__team__name', 'pool__participations__team__trigram',) search_fields = ('pool__participations__team__name', 'pool__participations__team__trigram',)
ordering = ('pool__tournament', 'pool__round', 'pool__letter', 'position',) ordering = ('pool__tournament', 'pool__round', 'pool__letter', 'position',)
autocomplete_fields = ('pool', 'defender', 'opponent', 'reviewer', 'observer',) autocomplete_fields = ('pool', 'defender', 'opponent', 'reviewer',)
inlines = (NoteInline,) inlines = (NoteInline,)
@admin.display(description=_("defender"), ordering='defender__team__trigram') @admin.display(description=_("defender"), ordering='defender__team__trigram')
@ -133,10 +133,6 @@ class PassageAdmin(admin.ModelAdmin):
def reviewer_trigram(self, record: Passage): def reviewer_trigram(self, record: Passage):
return record.reviewer.team.trigram return record.reviewer.team.trigram
@admin.display(description=_("observer"), ordering='observer__team__trigram')
def observer_trigram(self, record: Passage):
return record.observer.team.trigram
@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.short_name}" return f"{record.pool.short_name}"
@ -149,11 +145,10 @@ class PassageAdmin(admin.ModelAdmin):
@admin.register(Note) @admin.register(Note)
class NoteAdmin(admin.ModelAdmin): class NoteAdmin(admin.ModelAdmin):
list_display = ('passage', 'pool', 'jury', 'defender_writing', 'defender_oral', list_display = ('passage', 'pool', 'jury', 'defender_writing', 'defender_oral',
'opponent_writing', 'opponent_oral', 'reviewer_writing', 'reviewer_oral', 'opponent_writing', 'opponent_oral', 'reviewer_writing', 'reviewer_oral',)
'observer_writing', 'observer_oral',)
list_filter = ('passage__pool__letter', 'passage__solution_number', 'jury', list_filter = ('passage__pool__letter', 'passage__solution_number', 'jury',
'defender_writing', 'defender_oral', 'opponent_writing', 'opponent_oral', 'defender_writing', 'defender_oral', 'opponent_writing', 'opponent_oral',
'reviewer_writing', 'reviewer_oral', 'observer_writing', 'observer_oral') 'reviewer_writing', 'reviewer_oral')
search_fields = ('jury__user__last_name', 'jury__user__first_name', 'passage__defender__team__trigram',) search_fields = ('jury__user__last_name', 'jury__user__first_name', 'passage__defender__team__trigram',)
autocomplete_fields = ('jury', 'passage',) autocomplete_fields = ('jury', 'passage',)

View File

@ -13,7 +13,7 @@ class NoteViewSet(ModelViewSet):
serializer_class = NoteSerializer serializer_class = NoteSerializer
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_fields = ['jury', 'passage', 'defender_writing', 'defender_oral', 'opponent_writing', filterset_fields = ['jury', 'passage', 'defender_writing', 'defender_oral', 'opponent_writing',
'opponent_oral', 'reviewer_writing', 'reviewer_oral', 'observer_writing', 'observer_oral', ] 'opponent_oral', 'reviewer_writing', 'reviewer_oral', ]
class ParticipationViewSet(ModelViewSet): class ParticipationViewSet(ModelViewSet):
@ -27,7 +27,7 @@ class PassageViewSet(ModelViewSet):
queryset = Passage.objects.all() queryset = Passage.objects.all()
serializer_class = PassageSerializer serializer_class = PassageSerializer
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_fields = ['pool', 'solution_number', 'defender', 'opponent', 'reviewer', 'observer', 'pool_tournament', ] filterset_fields = ['pool', 'solution_number', 'defender', 'opponent', 'reviewer', 'pool_tournament', ]
class PoolViewSet(ModelViewSet): class PoolViewSet(ModelViewSet):

View File

@ -355,7 +355,7 @@ class PassageForm(forms.ModelForm):
class Meta: class Meta:
model = Passage model = Passage
fields = ('position', 'solution_number', 'defender', 'opponent', 'reviewer', 'opponent', 'defender_penalties',) fields = ('position', 'solution_number', 'defender', 'opponent', 'reviewer', 'defender_penalties',)
class SynthesisForm(forms.ModelForm): class SynthesisForm(forms.ModelForm):
@ -386,4 +386,4 @@ class NoteForm(forms.ModelForm):
class Meta: class Meta:
model = Note model = Note
fields = ('defender_writing', 'defender_oral', 'opponent_writing', fields = ('defender_writing', 'defender_oral', 'opponent_writing',
'opponent_oral', 'reviewer_writing', 'reviewer_oral', 'observer_writing', 'observer_oral', ) 'opponent_oral', 'reviewer_writing', 'reviewer_oral', )

View File

@ -1,86 +0,0 @@
# Generated by Django 5.0.6 on 2024-07-05 09:47
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("participation", "0018_rename_reporter_to_reviewer"),
]
operations = [
migrations.AddField(
model_name="note",
name="observer_oral",
field=models.PositiveSmallIntegerField(
choices=[
(-10, -10),
(-9, -9),
(-8, -8),
(-7, -7),
(-6, -6),
(-5, -5),
(-4, -4),
(-3, -3),
(-2, -2),
(-1, -1),
(0, 0),
(1, 1),
(2, 2),
(3, 3),
(4, 4),
(5, 5),
(6, 6),
(7, 7),
(8, 8),
(9, 9),
(10, 10),
],
default=0,
verbose_name="observer oral note",
),
),
migrations.AddField(
model_name="note",
name="observer_writing",
field=models.PositiveSmallIntegerField(
choices=[
(0, 0),
(1, 1),
(2, 2),
(3, 3),
(4, 4),
(5, 5),
(6, 6),
(7, 7),
(8, 8),
(9, 9),
(10, 10),
],
default=0,
verbose_name="observer writing note",
),
),
migrations.AddField(
model_name="passage",
name="observer",
field=models.ForeignKey(
blank=True,
default=None,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="+",
to="participation.participation",
verbose_name="observer",
),
),
migrations.AlterField(
model_name="synthesis",
name="type",
field=models.PositiveSmallIntegerField(
choices=[(1, "opponent"), (2, "reviewer"), (3, "observer")]
),
),
]

View File

@ -859,8 +859,6 @@ class Participation(models.Model):
defender_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, defender=self) defender_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, defender=self)
opponent_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, opponent=self) opponent_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, opponent=self)
reviewer_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, reviewer=self) reviewer_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, reviewer=self)
observer_passage = Passage.objects.filter(pool__tournament=self.tournament, pool__round=1, observer=self)
observer_passage = observer_passage.get() if observer_passage.exists() else None
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>"
@ -889,26 +887,12 @@ class Participation(models.Model):
solution_url=solution_url, solution_url=solution_url,
problem=reviewer_passage.solution_number, passage_url=passage_url) problem=reviewer_passage.solution_number, passage_url=passage_url)
if observer_passage:
observer_text = _("<p>You will observe the solution of the team {observer} on the "
"<a href='{solution_url}'>problem {problem}. "
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
solution_url = observer_passage.defended_solution.file.url
passage_url = reverse_lazy("participation:passage_detail", args=(observer_passage.pk,))
observer_content = format_lazy(observer_text,
observer=observer_passage.defender.team.trigram,
solution_url=solution_url,
problem=observer_passage.solution_number, passage_url=passage_url)
else:
observer_content = ""
syntheses_template_begin = f"{settings.STATIC_URL}Fiche_synthèse." syntheses_template_begin = f"{settings.STATIC_URL}Fiche_synthèse."
syntheses_templates = "".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>" syntheses_templates = "".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
for ext in ["pdf", "tex", "odt", "docx"]) for ext in ["pdf", "tex", "odt", "docx"])
syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>" syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>"
content = defender_content + opponent_content + reviewer_content + observer_content \ content = defender_content + opponent_content + reviewer_content + syntheses_templates_content
+ syntheses_templates_content
informations.append({ informations.append({
'title': _("First round"), 'title': _("First round"),
'type': "info", 'type': "info",
@ -919,8 +903,6 @@ class Participation(models.Model):
defender_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, defender=self) defender_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, defender=self)
opponent_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, opponent=self) opponent_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, opponent=self)
reviewer_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, reviewer=self) reviewer_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, reviewer=self)
observer_passage = Passage.objects.filter(pool__tournament=self.tournament, pool__round=2, observer=self)
observer_passage = observer_passage.get() if observer_passage.exists() else None
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>")
@ -947,26 +929,12 @@ class Participation(models.Model):
solution_url=solution_url, solution_url=solution_url,
problem=reviewer_passage.solution_number, passage_url=passage_url) problem=reviewer_passage.solution_number, passage_url=passage_url)
if observer_passage:
observer_text = _("<p>You will observe the solution of the team {observer} on the "
"<a href='{solution_url}'>problem {problem}. "
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
solution_url = observer_passage.defended_solution.file.url
passage_url = reverse_lazy("participation:passage_detail", args=(observer_passage.pk,))
observer_content = format_lazy(observer_text,
observer=observer_passage.defender.team.trigram,
solution_url=solution_url,
problem=observer_passage.solution_number, passage_url=passage_url)
else:
observer_content = ""
syntheses_template_begin = f"{settings.STATIC_URL}Fiche_synthèse." syntheses_template_begin = f"{settings.STATIC_URL}Fiche_synthèse."
syntheses_templates = "".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>" syntheses_templates = "".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
for ext in ["pdf", "tex", "odt", "docx"]) for ext in ["pdf", "tex", "odt", "docx"])
syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>" syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>"
content = defender_content + opponent_content + reviewer_content + observer_content \ content = defender_content + opponent_content + reviewer_content + syntheses_templates_content
+ syntheses_templates_content
informations.append({ informations.append({
'title': _("Second round"), 'title': _("Second round"),
'type': "info", 'type': "info",
@ -978,8 +946,6 @@ class Participation(models.Model):
defender_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, defender=self) defender_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, defender=self)
opponent_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, opponent=self) opponent_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, opponent=self)
reviewer_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, reviewer=self) reviewer_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, reviewer=self)
observer_passage = Passage.objects.filter(pool__tournament=self.tournament, pool__round=3, observer=self)
observer_passage = observer_passage.get() if observer_passage.exists() else None
defender_text = _("<p>For the third round, you will defend " defender_text = _("<p>For the third 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>")
@ -1006,26 +972,12 @@ class Participation(models.Model):
solution_url=solution_url, solution_url=solution_url,
problem=reviewer_passage.solution_number, passage_url=passage_url) problem=reviewer_passage.solution_number, passage_url=passage_url)
if observer_passage:
observer_text = _("<p>You will observe the solution of the team {observer} on the "
"<a href='{solution_url}'>problem {problem}. "
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
solution_url = observer_passage.defended_solution.file.url
passage_url = reverse_lazy("participation:passage_detail", args=(observer_passage.pk,))
observer_content = format_lazy(observer_text,
observer=observer_passage.defender.team.trigram,
solution_url=solution_url,
problem=observer_passage.solution_number, passage_url=passage_url)
else:
observer_content = ""
syntheses_template_begin = f"{settings.STATIC_URL}Fiche_synthèse." syntheses_template_begin = f"{settings.STATIC_URL}Fiche_synthèse."
syntheses_templates = "".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>" syntheses_templates = "".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
for ext in ["pdf", "tex", "odt", "docx"]) for ext in ["pdf", "tex", "odt", "docx"])
syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>" syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>"
content = defender_content + opponent_content + reviewer_content + observer_content \ content = defender_content + opponent_content + reviewer_content + syntheses_templates_content
+ syntheses_templates_content
informations.append({ informations.append({
'title': _("Second round"), 'title': _("Second round"),
'type': "info", 'type': "info",
@ -1608,16 +1560,6 @@ class Passage(models.Model):
related_name="+", related_name="+",
) )
observer = models.ForeignKey(
Participation,
on_delete=models.SET_NULL,
verbose_name=_("observer"),
related_name="+",
null=True,
blank=True,
default=None,
)
defender_penalties = models.PositiveSmallIntegerField( defender_penalties = models.PositiveSmallIntegerField(
verbose_name=_("penalties"), verbose_name=_("penalties"),
default=0, default=0,
@ -1646,10 +1588,7 @@ class Passage(models.Model):
@property @property
def average_defender(self) -> float: def average_defender(self) -> float:
writing_coeff = 1 if settings.TFJM_APP == "TFJM" else 2 return self.average_defender_writing + (1.6 - 0.4 * self.defender_penalties) * self.average_defender_oral
oral_coeff = 1.6 if settings.TFJM_APP == "TFJM" else 3
oral_coeff *= 1 - 0.25 * self.defender_penalties
return writing_coeff * self.average_defender_writing + oral_coeff * self.average_defender_oral
@property @property
def average_opponent_writing(self) -> float: def average_opponent_writing(self) -> float:
@ -1661,9 +1600,7 @@ class Passage(models.Model):
@property @property
def average_opponent(self) -> float: def average_opponent(self) -> float:
writing_coeff = 0.9 if not self.observer else 0.6 return 0.9 * self.average_opponent_writing + 2 * self.average_opponent_oral
oral_coeff = 2
return writing_coeff * self.average_opponent_writing + oral_coeff * self.average_opponent_oral
@property @property
def average_reviewer_writing(self) -> float: def average_reviewer_writing(self) -> float:
@ -1675,21 +1612,7 @@ class Passage(models.Model):
@property @property
def average_reviewer(self) -> float: def average_reviewer(self) -> float:
writing_coeff = 0.9 if not self.observer else 0.6 return 0.9 * self.average_reviewer_writing + self.average_reviewer_oral
oral_coeff = 1 if settings.TFJM_APP == "TFJM" else 1.2
return writing_coeff * self.average_reviewer_writing + oral_coeff * self.average_reviewer_oral
@property
def average_observer_writing(self) -> float:
return self.avg(note.observer_writing for note in self.notes.all())
@property
def average_observer_oral(self) -> float:
return self.avg(note.observer_oral for note in self.notes.all())
@property
def average_observer(self) -> float:
return 0.6 * self.average_observer_writing + 0.5 * self.average_observer_oral
@property @property
def averages(self): def averages(self):
@ -1699,19 +1622,10 @@ class Passage(models.Model):
yield self.average_opponent_oral yield self.average_opponent_oral
yield self.average_reviewer_writing yield self.average_reviewer_writing
yield self.average_reviewer_oral yield self.average_reviewer_oral
if self.observer:
yield self.average_observer_writing
yield self.average_observer_oral
def average(self, participation): def average(self, participation):
avg = self.average_defender if participation == self.defender else self.average_opponent \ return self.average_defender if participation == self.defender else self.average_opponent \
if participation == self.opponent else self.average_reviewer if participation == self.reviewer \ if participation == self.opponent else self.average_reviewer if participation == self.reviewer else 0
else self.average_observer if participation == self.observer else 0
if self.pool.round == 3 and settings.TFJM_APP == "ETEAM":
avg *= math.pi - 2
return avg
def get_absolute_url(self): def get_absolute_url(self):
return reverse_lazy("participation:passage_detail", args=(self.pk,)) return reverse_lazy("participation:passage_detail", args=(self.pk,))
@ -1726,9 +1640,6 @@ class Passage(models.Model):
if self.reviewer not in self.pool.participations.all(): if self.reviewer not in self.pool.participations.all():
raise ValidationError(_("Team {trigram} is not registered in the pool.") raise ValidationError(_("Team {trigram} is not registered in the pool.")
.format(trigram=self.reviewer.team.trigram)) .format(trigram=self.reviewer.team.trigram))
if self.observer and self.observer not in self.pool.participations.all():
raise ValidationError(_("Team {trigram} is not registered in the pool.")
.format(trigram=self.observer.team.trigram))
return super().clean() return super().clean()
def __str__(self): def __str__(self):
@ -1837,7 +1748,6 @@ class Synthesis(models.Model):
choices=[ choices=[
(1, _("opponent"), ), (1, _("opponent"), ),
(2, _("reviewer"), ), (2, _("reviewer"), ),
(3, _("observer"), ),
] ]
) )
@ -1913,18 +1823,6 @@ class Note(models.Model):
default=0, default=0,
) )
observer_writing = models.PositiveSmallIntegerField(
verbose_name=_("observer writing note"),
choices=[(i, i) for i in range(0, 11)],
default=0,
)
observer_oral = models.PositiveSmallIntegerField(
verbose_name=_("observer oral note"),
choices=[(i, i) for i in range(-10, 11)],
default=0,
)
def get_all(self): def get_all(self):
yield self.defender_writing yield self.defender_writing
yield self.defender_oral yield self.defender_oral
@ -1932,20 +1830,15 @@ class Note(models.Model):
yield self.opponent_oral yield self.opponent_oral
yield self.reviewer_writing yield self.reviewer_writing
yield self.reviewer_oral yield self.reviewer_oral
if self.passage.observer:
yield self.observer_writing
yield self.observer_oral
def set_all(self, defender_writing: int, defender_oral: int, opponent_writing: int, opponent_oral: int, def set_all(self, defender_writing: int, defender_oral: int, opponent_writing: int, opponent_oral: int,
reviewer_writing: int, reviewer_oral: int, observer_writing: int = 0, observer_oral: int = 0): reviewer_writing: int, reviewer_oral: int):
self.defender_writing = defender_writing self.defender_writing = defender_writing
self.defender_oral = defender_oral self.defender_oral = defender_oral
self.opponent_writing = opponent_writing self.opponent_writing = opponent_writing
self.opponent_oral = opponent_oral self.opponent_oral = opponent_oral
self.reviewer_writing = reviewer_writing self.reviewer_writing = reviewer_writing
self.reviewer_oral = reviewer_oral self.reviewer_oral = reviewer_oral
self.observer_writing = observer_writing
self.observer_oral = observer_oral
def update_spreadsheet(self): def update_spreadsheet(self):
if not self.has_any_note(): if not self.has_any_note():

View File

@ -106,8 +106,6 @@ class PoolTable(tables.Table):
class PassageTable(tables.Table): class PassageTable(tables.Table):
# FIXME Ne pas afficher l'équipe observatrice si non nécessaire
defender = tables.LinkColumn( defender = tables.LinkColumn(
"participation:passage_detail", "participation:passage_detail",
args=[tables.A("id")], args=[tables.A("id")],
@ -123,15 +121,12 @@ class PassageTable(tables.Table):
def render_reviewer(self, value): def render_reviewer(self, value):
return value.team.trigram return value.team.trigram
def render_observer(self, value):
return value.team.trigram
class Meta: class Meta:
attrs = { attrs = {
'class': 'table table-condensed table-striped text-center', 'class': 'table table-condensed table-striped text-center',
} }
model = Passage model = Passage
fields = ('defender', 'opponent', 'reviewer', 'observer', 'solution_number', ) fields = ('defender', 'opponent', 'reviewer', 'solution_number', )
class NoteTable(tables.Table): class NoteTable(tables.Table):
@ -160,4 +155,4 @@ class NoteTable(tables.Table):
} }
model = Note model = Note
fields = ('jury', 'defender_writing', 'defender_oral', 'opponent_writing', 'opponent_oral', fields = ('jury', 'defender_writing', 'defender_oral', 'opponent_writing', 'opponent_oral',
'reviewer_writing', 'reviewer_oral', 'observer_writing', 'observer_oral', 'update',) 'reviewer_writing', 'reviewer_oral', 'update',)

View File

@ -31,14 +31,9 @@
<dt class="col-sm-3">{% trans "Opponent:" %}</dt> <dt class="col-sm-3">{% trans "Opponent:" %}</dt>
<dd class="col-sm-9"><a href="{{ passage.opponent.get_absolute_url }}">{{ passage.opponent.team }}</a></dd> <dd class="col-sm-9"><a href="{{ passage.opponent.get_absolute_url }}">{{ passage.opponent.team }}</a></dd>
<dt class="col-sm-3">{% trans "Reviewer:" %}</dt> <dt class="col-sm-3">{% trans "reviewer:" %}</dt>
<dd class="col-sm-9"><a href="{{ passage.reviewer.get_absolute_url }}">{{ passage.reviewer.team }}</a></dd> <dd class="col-sm-9"><a href="{{ passage.reviewer.get_absolute_url }}">{{ passage.reviewer.team }}</a></dd>
{% if passage.observer %}
<dt class="col-sm-3">{% trans "Observer:" %}</dt>
<dd class="col-sm-9"><a href="{{ passage.observer.get_absolute_url }}">{{ passage.observer.team }}</a></dd>
{% endif %}
<dt class="col-sm-3">{% trans "Defended solution:" %}</dt> <dt class="col-sm-3">{% trans "Defended solution:" %}</dt>
<dd class="col-sm-9"><a href="{{ passage.defended_solution.file.url }}">{{ passage.defended_solution }}</a></dd> <dd class="col-sm-9"><a href="{{ passage.defended_solution.file.url }}">{{ passage.defended_solution }}</a></dd>
@ -113,20 +108,6 @@
({{ passage.reviewer.team.trigram }}) : ({{ passage.reviewer.team.trigram }}) :
</dt> </dt>
<dd class="col-sm-4">{{ passage.average_reviewer_oral|floatformat }}/10</dd> <dd class="col-sm-4">{{ passage.average_reviewer_oral|floatformat }}/10</dd>
{% if passage.observer %}
<dt class="col-sm-8">
{% trans "Average points for the observer writing" %}
({{ passage.observer.team.trigram }}) :
</dt>
<dd class="col-sm-4">{{ passage.average_observer_writing|floatformat }}/10</dd>
<dt class="col-sm-8">
{% trans "Average points for the observer oral" %}
({{ passage.observer.team.trigram }}) :
</dt>
<dd class="col-sm-4">{{ passage.average_observer_oral|floatformat }}/10</dd>
{% endif %}
</dl> </dl>
<hr> <hr>
@ -149,15 +130,6 @@
({{ passage.reviewer.team.trigram }}) : ({{ passage.reviewer.team.trigram }}) :
</dt> </dt>
<dd class="col-sm-4">{{ passage.average_reviewer|floatformat }}/19</dd> <dd class="col-sm-4">{{ passage.average_reviewer|floatformat }}/19</dd>
{% if passage.observer %}
<dt class="col-sm-8">
{% trans "observer points" %}
({{ passage.observer.team.trigram }}) :
</dt>
<dd class="col-sm-4">{{ passage.average_observer|floatformat }}/10</dd>
{% endif %}
</dl> </dl>
</div> </div>
</div> </div>

View File

@ -685,7 +685,7 @@ class TournamentExportCSVView(VolunteerMixin, DetailView):
) )
writer = csv.DictWriter(resp, ('Tournoi', 'Équipe', 'Trigramme', 'Sélectionnée', writer = csv.DictWriter(resp, ('Tournoi', 'Équipe', 'Trigramme', 'Sélectionnée',
'Nom', 'Prénom', 'Email', 'Type', 'Genre', 'Date de naissance', 'Nom', 'Prénom', 'Email', 'Type', 'Genre', 'Date de naissance',
'Adresse', 'Code postal', 'Ville', 'Pays', 'Téléphone', 'Adresse', 'Code postal', 'Ville', 'Téléphone',
'Classe', 'Établissement', 'Classe', 'Établissement',
'Nom responsable légal⋅e', 'Téléphone responsable légal⋅e', 'Nom responsable légal⋅e', 'Téléphone responsable légal⋅e',
'Email responsable légal⋅e', 'Email responsable légal⋅e',
@ -1992,8 +1992,7 @@ class SynthesisUploadView(LoginRequiredMixin, FormView):
self.participation = self.request.user.registration.team.participation self.participation = self.request.user.registration.team.participation
self.passage = qs.get() self.passage = qs.get()
if self.participation \ if self.participation not in [self.passage.opponent, self.passage.reviewer]:
and self.participation not in [self.passage.opponent, self.passage.reviewer, self.passage.observer]:
return self.handle_no_permission() return self.handle_no_permission()
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
@ -2005,8 +2004,7 @@ class SynthesisUploadView(LoginRequiredMixin, FormView):
It is discriminating whenever the team is selected for the final tournament or not. It is discriminating whenever the team is selected for the final tournament or not.
""" """
form_syn = form.instance form_syn = form.instance
form_syn.type = 1 if self.participation == self.passage.opponent \ form_syn.type = 1 if self.participation == self.passage.opponent else 2
else 2 if self.participation == self.passage.reviewer else 3
syn_qs = Synthesis.objects.filter(participation=self.participation, syn_qs = Synthesis.objects.filter(participation=self.participation,
passage=self.passage, passage=self.passage,
type=form_syn.type).all() type=form_syn.type).all()
@ -2054,8 +2052,6 @@ class NoteUpdateView(VolunteerMixin, UpdateView):
form.fields['opponent_oral'].label += f" ({self.object.passage.opponent.team.trigram})" form.fields['opponent_oral'].label += f" ({self.object.passage.opponent.team.trigram})"
form.fields['reviewer_writing'].label += f" ({self.object.passage.reviewer.team.trigram})" form.fields['reviewer_writing'].label += f" ({self.object.passage.reviewer.team.trigram})"
form.fields['reviewer_oral'].label += f" ({self.object.passage.reviewer.team.trigram})" form.fields['reviewer_oral'].label += f" ({self.object.passage.reviewer.team.trigram})"
form.fields['observer_writing'].label += f" ({self.object.passage.observer.team.trigram})"
form.fields['observer_oral'].label += f" ({self.object.passage.observer.team.trigram})"
return form return form
def form_valid(self, form): def form_valid(self, form):

View File

@ -836,11 +836,10 @@ class SolutionView(LoginRequiredMixin, View):
raise Http404 raise Http404
solution = Solution.objects.get(file__endswith=filename) solution = Solution.objects.get(file__endswith=filename)
user = request.user user = request.user
if user.registration.participates and user.registration.team.participation: if user.registration.participates:
passage_participant_qs = Passage.objects.filter(Q(defender=user.registration.team.participation) passage_participant_qs = Passage.objects.filter(Q(defender=user.registration.team.participation)
| Q(opponent=user.registration.team.participation) | Q(opponent=user.registration.team.participation)
| Q(reviewer=user.registration.team.participation) | Q(reviewer=user.registration.team.participation),
| Q(observer=user.registration.team.participation),
defender=solution.participation, defender=solution.participation,
solution_number=solution.problem) solution_number=solution.problem)
else: else: