Rename synthesis to written review
Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
parent
696863f6c3
commit
12205f953b
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: TFJM\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-07-06 10:16+0200\n"
|
||||
"POT-Creation-Date: 2024-07-06 21:27+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Emmy D'Anello <emmy.danello@animath.fr>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -79,7 +79,7 @@ msgstr "Type de permission nécessaire pour écrire un message dans un canal."
|
|||
#: chat/models.py:62 draw/admin.py:53 draw/admin.py:71 draw/admin.py:88
|
||||
#: draw/models.py:27 participation/admin.py:79 participation/admin.py:144
|
||||
#: participation/admin.py:176 participation/models.py:783
|
||||
#: participation/models.py:807 participation/models.py:1116
|
||||
#: participation/models.py:807 participation/models.py:1131
|
||||
#: registration/models.py:763
|
||||
#: registration/templates/registration/payment_form.html:53
|
||||
msgid "tournament"
|
||||
|
@ -95,7 +95,7 @@ msgstr ""
|
|||
|
||||
#: chat/models.py:73 draw/models.py:446 draw/models.py:473
|
||||
#: participation/admin.py:140 participation/admin.py:160
|
||||
#: participation/models.py:1651 participation/models.py:1660
|
||||
#: participation/models.py:1666 participation/models.py:1675
|
||||
#: participation/tables.py:84
|
||||
msgid "pool"
|
||||
msgstr "poule"
|
||||
|
@ -265,7 +265,7 @@ msgid "teams"
|
|||
msgstr "équipes"
|
||||
|
||||
#: draw/admin.py:92 draw/models.py:245 draw/models.py:465
|
||||
#: participation/models.py:1120
|
||||
#: participation/models.py:1135
|
||||
msgid "round"
|
||||
msgstr "tour"
|
||||
|
||||
|
@ -634,7 +634,7 @@ msgstr "Le numéro du tour doit être entre 1 et {nb}."
|
|||
msgid "rounds"
|
||||
msgstr "tours"
|
||||
|
||||
#: draw/models.py:268 participation/models.py:1128
|
||||
#: draw/models.py:268 participation/models.py:1143
|
||||
msgid "letter"
|
||||
msgstr "lettre"
|
||||
|
||||
|
@ -672,12 +672,12 @@ msgstr "L'instance complète de la poule."
|
|||
msgid "Pool {letter}{number}"
|
||||
msgstr "Poule {letter}{number}"
|
||||
|
||||
#: draw/models.py:447 participation/models.py:1652
|
||||
#: draw/models.py:447 participation/models.py:1667
|
||||
msgid "pools"
|
||||
msgstr "poules"
|
||||
|
||||
#: draw/models.py:459 participation/models.py:1106 participation/models.py:1871
|
||||
#: participation/models.py:1901 participation/models.py:1943
|
||||
#: draw/models.py:459 participation/models.py:1121 participation/models.py:1886
|
||||
#: participation/models.py:1920 participation/models.py:1962
|
||||
msgid "participation"
|
||||
msgstr "participation"
|
||||
|
||||
|
@ -701,9 +701,9 @@ msgid ""
|
|||
msgstr ""
|
||||
"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:1237
|
||||
#: participation/models.py:1674 participation/models.py:1908
|
||||
#: participation/views.py:1489 participation/views.py:1754
|
||||
#: draw/models.py:496 draw/models.py:519 participation/models.py:1252
|
||||
#: participation/models.py:1689 participation/models.py:1927
|
||||
#: participation/views.py:1492 participation/views.py:1757
|
||||
#, python-brace-format
|
||||
msgid "Problem #{problem}"
|
||||
msgstr "Problème n°{problem}"
|
||||
|
@ -919,26 +919,26 @@ msgid "selected for final"
|
|||
msgstr "sélectionnée pour la finale"
|
||||
|
||||
#: participation/admin.py:124 participation/admin.py:188
|
||||
#: participation/models.py:1681 participation/tables.py:114
|
||||
#: participation/models.py:1696 participation/tables.py:114
|
||||
msgid "defender"
|
||||
msgstr "défenseur⋅se"
|
||||
|
||||
#: participation/admin.py:128 participation/models.py:1688
|
||||
#: participation/models.py:1955
|
||||
#: participation/admin.py:128 participation/models.py:1703
|
||||
#: participation/models.py:1974
|
||||
msgid "opponent"
|
||||
msgstr "opposant⋅e"
|
||||
|
||||
#: participation/admin.py:132 participation/models.py:1695
|
||||
#: participation/models.py:1956
|
||||
#: participation/admin.py:132 participation/models.py:1710
|
||||
#: participation/models.py:1975
|
||||
msgid "reviewer"
|
||||
msgstr "rapporteur⋅rice"
|
||||
|
||||
#: participation/admin.py:136 participation/models.py:1702
|
||||
#: participation/models.py:1957
|
||||
#: participation/admin.py:136 participation/models.py:1717
|
||||
#: participation/models.py:1976
|
||||
msgid "observer"
|
||||
msgstr "observateur⋅rice"
|
||||
|
||||
#: participation/admin.py:192 participation/models.py:1906
|
||||
#: participation/admin.py:192 participation/models.py:1925
|
||||
msgid "problem"
|
||||
msgstr "numéro de problème"
|
||||
|
||||
|
@ -1239,7 +1239,7 @@ msgid "first phase date"
|
|||
msgstr "date du premier tour"
|
||||
|
||||
#: participation/models.py:327
|
||||
msgid "limit date to upload the syntheses for the first phase"
|
||||
msgid "limit date to upload the written reviews for the first phase"
|
||||
msgstr "date limite pour envoyer les notes de synthèses pour la première phase"
|
||||
|
||||
#: participation/models.py:332
|
||||
|
@ -1252,7 +1252,7 @@ msgstr ""
|
|||
"cocher la case lorsque les solutions pour le second tour sont accessibles"
|
||||
|
||||
#: participation/models.py:342
|
||||
msgid "limit date to upload the syntheses for the second phase"
|
||||
msgid "limit date to upload the written reviews for the second phase"
|
||||
msgstr "date limite d'envoi des notes de synthèse pour la seconde phase"
|
||||
|
||||
#: participation/models.py:347
|
||||
|
@ -1265,7 +1265,7 @@ msgstr ""
|
|||
"cocher la case lorsque les solutions pour le second tour sont accessibles"
|
||||
|
||||
#: participation/models.py:357
|
||||
msgid "limit date to upload the syntheses for the third phase"
|
||||
msgid "limit date to upload the written reviews for the third phase"
|
||||
msgstr ""
|
||||
"date limite pour envoyer les notes de synthèses pour la troisième phase"
|
||||
|
||||
|
@ -1294,7 +1294,7 @@ msgid "Final ranking"
|
|||
msgstr "Classement final"
|
||||
|
||||
#: participation/models.py:481 participation/models.py:553
|
||||
#: participation/models.py:1312 participation/views.py:1728
|
||||
#: participation/models.py:1327 participation/views.py:1731
|
||||
msgid "Team"
|
||||
msgstr "Équipe"
|
||||
|
||||
|
@ -1326,15 +1326,15 @@ msgstr "Scores jour 3"
|
|||
msgid "Tweaks day 3"
|
||||
msgstr "Ajustements 3"
|
||||
|
||||
#: participation/models.py:485 participation/models.py:1312
|
||||
#: participation/views.py:1735
|
||||
#: participation/models.py:485 participation/models.py:1327
|
||||
#: participation/views.py:1738
|
||||
msgid "Total"
|
||||
msgstr "Total"
|
||||
|
||||
#: participation/models.py:485 participation/models.py:553
|
||||
#: participation/models.py:1312
|
||||
#: participation/models.py:1327
|
||||
#: participation/templates/participation/tournament_harmonize.html:14
|
||||
#: participation/views.py:1738
|
||||
#: participation/views.py:1741
|
||||
msgid "Rank"
|
||||
msgstr "Rang"
|
||||
|
||||
|
@ -1346,7 +1346,7 @@ msgstr "Score"
|
|||
msgid "Mention"
|
||||
msgstr "Mention"
|
||||
|
||||
#: participation/models.py:698 participation/models.py:1581
|
||||
#: participation/models.py:698 participation/models.py:1596
|
||||
msgid "Don't update the table structure for a better automated integration."
|
||||
msgstr ""
|
||||
"Ne pas mettre à jour la structure de la table pour une meilleure intégration "
|
||||
|
@ -1456,47 +1456,47 @@ msgstr ""
|
|||
"tour, vous défendrez <a href='{solution_url}'>votre solution du problème "
|
||||
"{problem}</a>.</p>"
|
||||
|
||||
#: participation/models.py:930 participation/models.py:988
|
||||
#: participation/models.py:1047
|
||||
#: participation/models.py:930 participation/models.py:993
|
||||
#: participation/models.py:1057
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"<p>You will oppose the solution of the team {opponent} on the <a "
|
||||
"href='{solution_url}'>problem {problem}</a>. You can upload your synthesis "
|
||||
"sheet on <a href='{passage_url}'>this page</a>.</p>"
|
||||
"href='{solution_url}'>problem {problem}</a>. You can upload your written "
|
||||
"review on <a href='{passage_url}'>this page</a>.</p>"
|
||||
msgstr ""
|
||||
"<p>Vous opposerez la solution de l'équipe {opponent} 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:939 participation/models.py:997
|
||||
#: participation/models.py:1056
|
||||
#: participation/models.py:939 participation/models.py:1002
|
||||
#: participation/models.py:1066
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"<p>You will report the solution of the team {reviewer} on the <a "
|
||||
"href='{solution_url}'>problem {problem}. You can upload your synthesis sheet "
|
||||
"on <a href='{passage_url}'>this page</a>.</p>"
|
||||
"href='{solution_url}'>problem {problem}</a>. You can upload your written "
|
||||
"review on <a href='{passage_url}'>this page</a>.</p>"
|
||||
msgstr ""
|
||||
"<p>Vous rapporterez la solution de l'équipe {reviewer} 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:949 participation/models.py:1007
|
||||
#: participation/models.py:1066
|
||||
#: participation/models.py:949 participation/models.py:1012
|
||||
#: participation/models.py:1076
|
||||
#, 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>"
|
||||
"href='{solution_url}'>problem {problem}</a>. You can upload your written "
|
||||
"review 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:969 registration/models.py:629
|
||||
#: participation/models.py:974 registration/models.py:629
|
||||
msgid "First round"
|
||||
msgstr "Premier tour"
|
||||
|
||||
#: participation/models.py:981
|
||||
#: participation/models.py:986
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"<p>For the second round, you will defend <a href='{solution_url}'>your "
|
||||
|
@ -1505,12 +1505,12 @@ msgstr ""
|
|||
"<p>Pour le second tour, vous défendrez <a href='{solution_url}'>votre "
|
||||
"solution du problème {problem}</a>.</p>"
|
||||
|
||||
#: participation/models.py:1027 participation/models.py:1086
|
||||
#: participation/models.py:1037 participation/models.py:1101
|
||||
#: registration/models.py:640
|
||||
msgid "Second round"
|
||||
msgstr "Second tour"
|
||||
|
||||
#: participation/models.py:1040
|
||||
#: participation/models.py:1050
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"<p>For the third round, you will defend <a href='{solution_url}'>your "
|
||||
|
@ -1519,7 +1519,7 @@ msgstr ""
|
|||
"<p>Pour le troisième tour, vous défendrez <a href='{solution_url}'>votre "
|
||||
"solution du problème {problem}</a>.</p>"
|
||||
|
||||
#: participation/models.py:1092
|
||||
#: participation/models.py:1107
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"<p>The tournament {tournament} is ended. You can check the results on the <a "
|
||||
|
@ -1528,57 +1528,57 @@ msgstr ""
|
|||
"<p>Le tournoi {tournament} est terminé. Vous pouvez consulter les résultats "
|
||||
"sur la <a href='{url}'>page du tournoi</a>.</p>"
|
||||
|
||||
#: participation/models.py:1097
|
||||
#: participation/models.py:1112
|
||||
msgid "Tournament ended"
|
||||
msgstr "Tournoi terminé"
|
||||
|
||||
#: participation/models.py:1107 participation/models.py:1150
|
||||
#: participation/models.py:1122 participation/models.py:1165
|
||||
msgid "participations"
|
||||
msgstr "participations"
|
||||
|
||||
#: participation/models.py:1122 participation/models.py:1123
|
||||
#: participation/models.py:1124
|
||||
#: participation/models.py:1137 participation/models.py:1138
|
||||
#: participation/models.py:1139
|
||||
#, python-brace-format
|
||||
msgid "Round {round}"
|
||||
msgstr "Tour {round}"
|
||||
|
||||
#: participation/models.py:1138
|
||||
#: participation/models.py:1153
|
||||
msgid "room"
|
||||
msgstr "salle"
|
||||
|
||||
#: participation/models.py:1140
|
||||
#: participation/models.py:1155
|
||||
msgid "Room 1"
|
||||
msgstr "Salle 1"
|
||||
|
||||
#: participation/models.py:1141
|
||||
#: participation/models.py:1156
|
||||
msgid "Room 2"
|
||||
msgstr "Salle 2"
|
||||
|
||||
#: participation/models.py:1144
|
||||
#: participation/models.py:1159
|
||||
msgid "For 5-teams pools only"
|
||||
msgstr "Pour les poules de 5 équipe uniquement"
|
||||
|
||||
#: participation/models.py:1156
|
||||
#: participation/models.py:1171
|
||||
msgid "juries"
|
||||
msgstr "jurys"
|
||||
|
||||
#: participation/models.py:1165
|
||||
#: participation/models.py:1180
|
||||
msgid "president of the jury"
|
||||
msgstr "président⋅e du jury"
|
||||
|
||||
#: participation/models.py:1172
|
||||
#: participation/models.py:1187
|
||||
msgid "BigBlueButton URL"
|
||||
msgstr "Lien BigBlueButton"
|
||||
|
||||
#: participation/models.py:1173
|
||||
#: participation/models.py:1188
|
||||
msgid "The link of the BBB visio for this pool."
|
||||
msgstr "Le lien du salon BBB pour cette poule."
|
||||
|
||||
#: participation/models.py:1178
|
||||
#: participation/models.py:1193
|
||||
msgid "results available"
|
||||
msgstr "résultats disponibles"
|
||||
|
||||
#: participation/models.py:1179
|
||||
#: participation/models.py:1194
|
||||
msgid ""
|
||||
"Check this case when results become accessible to teams. They stay "
|
||||
"accessible to you. Only averages are given."
|
||||
|
@ -1587,65 +1587,65 @@ msgstr ""
|
|||
"Ils restent toujours accessibles pour vous. Seules les moyennes sont "
|
||||
"communiquées."
|
||||
|
||||
#: participation/models.py:1211
|
||||
#: participation/models.py:1226
|
||||
msgid "The president of the jury must be part of the jury."
|
||||
msgstr "Læ président⋅e du jury doit faire partie du jury."
|
||||
|
||||
#: participation/models.py:1238 participation/models.py:1312
|
||||
#: participation/views.py:1483 participation/views.py:1732
|
||||
#: participation/models.py:1253 participation/models.py:1327
|
||||
#: participation/views.py:1486 participation/views.py:1735
|
||||
msgid "Problem"
|
||||
msgstr "Problème"
|
||||
|
||||
#: participation/models.py:1243 participation/views.py:1498
|
||||
#: participation/models.py:1258 participation/views.py:1501
|
||||
msgid "Role"
|
||||
msgstr "Rôle"
|
||||
|
||||
#: participation/models.py:1248 participation/views.py:1532
|
||||
#: participation/views.py:1533
|
||||
#: participation/models.py:1263 participation/views.py:1535
|
||||
#: participation/views.py:1536
|
||||
msgid "Juree"
|
||||
msgstr "Juré⋅e"
|
||||
|
||||
#: participation/models.py:1271 participation/models.py:1597
|
||||
#: participation/models.py:1619 participation/views.py:1602
|
||||
#: participation/models.py:1286 participation/models.py:1612
|
||||
#: participation/models.py:1634 participation/views.py:1605
|
||||
msgid "Average"
|
||||
msgstr "Moyenne"
|
||||
|
||||
#: participation/models.py:1277 participation/views.py:1621
|
||||
#: participation/models.py:1292 participation/views.py:1624
|
||||
msgid "Coefficient"
|
||||
msgstr "Coefficien"
|
||||
|
||||
#: participation/models.py:1278 participation/views.py:1664
|
||||
#: participation/models.py:1293 participation/views.py:1667
|
||||
msgid "Subtotal"
|
||||
msgstr "Sous-total"
|
||||
|
||||
#: participation/models.py:1544
|
||||
#: participation/models.py:1559
|
||||
#, python-brace-format
|
||||
msgid "Input must be a valid integer between {min_note} and {max_note}."
|
||||
msgstr "L'entrée doit être un entier valide entre {min_note} et {max_note}."
|
||||
|
||||
#: participation/models.py:1632
|
||||
#: participation/models.py:1647
|
||||
#, python-brace-format
|
||||
msgid "The jury {jury} is not part of the jury for this pool."
|
||||
msgstr "{jury} ne fait pas partie du jury pour cette poule."
|
||||
|
||||
#: participation/models.py:1645
|
||||
#: participation/models.py:1660
|
||||
#, python-brace-format
|
||||
msgid "Pool {code} for tournament {tournament} with teams {teams}"
|
||||
msgstr "Poule {code} du tournoi {tournament} avec les équipes {teams}"
|
||||
|
||||
#: participation/models.py:1665
|
||||
#: participation/models.py:1680
|
||||
msgid "position"
|
||||
msgstr "position"
|
||||
|
||||
#: participation/models.py:1672
|
||||
#: participation/models.py:1687
|
||||
msgid "defended solution"
|
||||
msgstr "solution défendue"
|
||||
|
||||
#: participation/models.py:1710
|
||||
#: participation/models.py:1725
|
||||
msgid "penalties"
|
||||
msgstr "pénalités"
|
||||
|
||||
#: participation/models.py:1712
|
||||
#: participation/models.py:1727
|
||||
msgid ""
|
||||
"Number of penalties for the defender. The defender will loose a 0.5 "
|
||||
"coefficient per penalty."
|
||||
|
@ -1653,128 +1653,128 @@ msgstr ""
|
|||
"Nombre de pénalités pour l'équipe défenseuse. Elle perd un coefficient 0.5 "
|
||||
"sur sa présentation orale par pénalité."
|
||||
|
||||
#: participation/models.py:1838 participation/models.py:1841
|
||||
#: participation/models.py:1844 participation/models.py:1847
|
||||
#: participation/models.py:1853 participation/models.py:1856
|
||||
#: participation/models.py:1859 participation/models.py:1862
|
||||
#, python-brace-format
|
||||
msgid "Team {trigram} is not registered in the pool."
|
||||
msgstr "L'équipe {trigram} n'est pas inscrite dans la poule."
|
||||
|
||||
#: participation/models.py:1852
|
||||
#: participation/models.py:1867
|
||||
#, python-brace-format
|
||||
msgid "Passage of {defender} for problem {problem}"
|
||||
msgstr "Passage de {defender} pour le problème {problem}"
|
||||
|
||||
#: participation/models.py:1856 participation/models.py:1865
|
||||
#: participation/models.py:1950 participation/models.py:1993
|
||||
#: participation/models.py:1871 participation/models.py:1880
|
||||
#: participation/models.py:1969 participation/models.py:2012
|
||||
msgid "passage"
|
||||
msgstr "passage"
|
||||
|
||||
#: participation/models.py:1857
|
||||
#: participation/models.py:1872
|
||||
msgid "passages"
|
||||
msgstr "passages"
|
||||
|
||||
#: participation/models.py:1876
|
||||
#: participation/models.py:1891
|
||||
msgid "difference"
|
||||
msgstr "différence"
|
||||
|
||||
#: participation/models.py:1877
|
||||
#: participation/models.py:1892
|
||||
msgid "Score to add/remove on the final score"
|
||||
msgstr "Score à ajouter/retrancher au score final"
|
||||
|
||||
#: participation/models.py:1884
|
||||
#: participation/models.py:1899
|
||||
msgid "tweak"
|
||||
msgstr "harmonisation"
|
||||
|
||||
#: participation/models.py:1885
|
||||
#: participation/models.py:1900
|
||||
msgid "tweaks"
|
||||
msgstr "harmonisations"
|
||||
|
||||
#: participation/models.py:1913
|
||||
#: participation/models.py:1932
|
||||
msgid "solution for the final tournament"
|
||||
msgstr "solution pour la finale"
|
||||
|
||||
#: participation/models.py:1918 participation/models.py:1962
|
||||
#: participation/models.py:1937 participation/models.py:1981
|
||||
msgid "file"
|
||||
msgstr "fichier"
|
||||
|
||||
#: participation/models.py:1928
|
||||
#: participation/models.py:1947
|
||||
#, python-brace-format
|
||||
msgid "Solution of team {team} for problem {problem}"
|
||||
msgstr "Solution de l'équipe {team} pour le problème {problem}"
|
||||
|
||||
#: participation/models.py:1930
|
||||
#: participation/models.py:1949
|
||||
msgid "for final"
|
||||
msgstr "pour la finale"
|
||||
|
||||
#: participation/models.py:1933
|
||||
#: participation/models.py:1952
|
||||
msgid "solution"
|
||||
msgstr "solution"
|
||||
|
||||
#: participation/models.py:1934
|
||||
#: participation/models.py:1953
|
||||
msgid "solutions"
|
||||
msgstr "solutions"
|
||||
|
||||
#: participation/models.py:1968
|
||||
#: participation/models.py:1987
|
||||
#, python-brace-format
|
||||
msgid "Synthesis of {team} as {type} for problem {problem} of {defender}"
|
||||
msgid "Written review of {team} as {type} for problem {problem} of {defender}"
|
||||
msgstr ""
|
||||
"Note de synthèse de l'équipe {team} en tant que {type} pour le problème "
|
||||
"{problem} de {defender}"
|
||||
|
||||
#: participation/models.py:1976
|
||||
msgid "synthesis"
|
||||
#: participation/models.py:1995
|
||||
msgid "written review"
|
||||
msgstr "note de synthèse"
|
||||
|
||||
#: participation/models.py:1977
|
||||
msgid "syntheses"
|
||||
#: participation/models.py:1996
|
||||
msgid "written reviews"
|
||||
msgstr "notes de synthèse"
|
||||
|
||||
#: participation/models.py:1986
|
||||
#: participation/models.py:2005
|
||||
msgid "jury"
|
||||
msgstr "jury"
|
||||
|
||||
#: participation/models.py:1998
|
||||
#: participation/models.py:2017
|
||||
msgid "defender writing note"
|
||||
msgstr "note d'écrit défenseur⋅se"
|
||||
|
||||
#: participation/models.py:2004
|
||||
#: participation/models.py:2023
|
||||
msgid "defender oral note"
|
||||
msgstr "note d'oral défenseur⋅se"
|
||||
|
||||
#: participation/models.py:2010
|
||||
#: participation/models.py:2029
|
||||
msgid "opponent writing note"
|
||||
msgstr "note d'écrit opposant⋅e"
|
||||
|
||||
#: participation/models.py:2016
|
||||
#: participation/models.py:2035
|
||||
msgid "opponent oral note"
|
||||
msgstr "note d'oral opposant⋅e"
|
||||
|
||||
#: participation/models.py:2022
|
||||
#: participation/models.py:2041
|
||||
msgid "reviewer writing note"
|
||||
msgstr "note d'écrit rapporteur⋅rice"
|
||||
|
||||
#: participation/models.py:2028
|
||||
#: participation/models.py:2047
|
||||
msgid "reviewer oral note"
|
||||
msgstr "note d'oral du rapporteur⋅rice"
|
||||
|
||||
#: participation/models.py:2034
|
||||
#: participation/models.py:2053
|
||||
msgid "observer writing note"
|
||||
msgstr "note d'écrit de l'observateur⋅rice"
|
||||
|
||||
#: participation/models.py:2040
|
||||
#: participation/models.py:2059
|
||||
msgid "observer oral note"
|
||||
msgstr "note d'oral de l'observateur⋅rice"
|
||||
|
||||
#: participation/models.py:2105
|
||||
#: participation/models.py:2124
|
||||
#, python-brace-format
|
||||
msgid "Notes of {jury} for {passage}"
|
||||
msgstr "Notes de {jury} pour le {passage}"
|
||||
|
||||
#: participation/models.py:2108
|
||||
#: participation/models.py:2127
|
||||
msgid "note"
|
||||
msgstr "note"
|
||||
|
||||
#: participation/models.py:2109
|
||||
#: participation/models.py:2128
|
||||
msgid "notes"
|
||||
msgstr "notes"
|
||||
|
||||
|
@ -1910,7 +1910,7 @@ msgstr "Envoyer une solution"
|
|||
#: participation/templates/participation/upload_motivation_letter.html:13
|
||||
#: participation/templates/participation/upload_notes.html:24
|
||||
#: participation/templates/participation/upload_solution.html:11
|
||||
#: participation/templates/participation/upload_synthesis.html:18
|
||||
#: participation/templates/participation/upload_written_review.html:23
|
||||
#: registration/templates/registration/upload_health_sheet.html:17
|
||||
#: registration/templates/registration/upload_parental_authorization.html:17
|
||||
#: registration/templates/registration/upload_photo_authorization.html:18
|
||||
|
@ -1963,7 +1963,7 @@ msgstr "Notes de synthèse :"
|
|||
|
||||
#: participation/templates/participation/passage_detail.html:53
|
||||
#: participation/templates/participation/pool_detail.html:68
|
||||
msgid "No synthesis was uploaded yet."
|
||||
msgid "No review was uploaded yet."
|
||||
msgstr "Aucune note de synthèse n'a encore été envoyée."
|
||||
|
||||
#: participation/templates/participation/passage_detail.html:61
|
||||
|
@ -1973,8 +1973,8 @@ msgstr "Modifier les notes"
|
|||
|
||||
#: participation/templates/participation/passage_detail.html:66
|
||||
#: participation/templates/participation/passage_detail.html:187
|
||||
msgid "Upload synthesis"
|
||||
msgstr "Envoyer une note de synthèse"
|
||||
msgid "Upload review"
|
||||
msgstr "Envoyer la note de synthèse"
|
||||
|
||||
#: participation/templates/participation/passage_detail.html:74
|
||||
msgid "Notes detail"
|
||||
|
@ -2374,15 +2374,15 @@ msgid "date of the random draw"
|
|||
msgstr "date du tirage au sort"
|
||||
|
||||
#: participation/templates/participation/tournament_detail.html:41
|
||||
msgid "date of maximal syntheses submission for the first round"
|
||||
msgid "date of maximal written reviews submission for the first round"
|
||||
msgstr "date limite de soumission des notes de synthèse pour le premier tour"
|
||||
|
||||
#: participation/templates/participation/tournament_detail.html:44
|
||||
msgid "date of maximal syntheses submission for the second round"
|
||||
msgid "date of maximal written reviews submission for the second round"
|
||||
msgstr "date limite de soumission des notes de synthèse pour le second tour"
|
||||
|
||||
#: participation/templates/participation/tournament_detail.html:48
|
||||
msgid "date of maximal syntheses submission for the third round"
|
||||
msgid "date of maximal written reviews submission for the third round"
|
||||
msgstr "date limite de soumission des notes de synthèse pour le troisième tour"
|
||||
|
||||
#: participation/templates/participation/tournament_detail.html:56
|
||||
|
@ -2462,6 +2462,42 @@ msgstr "Dépublier les notes pour le troisième tour"
|
|||
msgid "Files available for download"
|
||||
msgstr "Fichiers disponibles au téléchargement"
|
||||
|
||||
#: participation/templates/participation/tournament_detail.html:236
|
||||
msgid "Validated team participant data spreadsheet"
|
||||
msgstr "Tableur des données des équipes validées"
|
||||
|
||||
#: participation/templates/participation/tournament_detail.html:241
|
||||
msgid "All teams participant data spreadsheet"
|
||||
msgstr "Tableur des données de toutes les équipes"
|
||||
|
||||
#: participation/templates/participation/tournament_detail.html:246
|
||||
msgid "Archive of all authorisations sorted by team and person"
|
||||
msgstr "Archive de toutes les autorisations triées par équipe et personne"
|
||||
|
||||
#: participation/templates/participation/tournament_detail.html:251
|
||||
msgid "Archive of all submitted solutions sorted by team"
|
||||
msgstr "Archive de toutes les solutions envoyées triées par équipe"
|
||||
|
||||
#: participation/templates/participation/tournament_detail.html:256
|
||||
msgid "Archive of all sent solutions sorted by problem"
|
||||
msgstr "Archive de toutes les solutions envoyées triées par problème"
|
||||
|
||||
#: participation/templates/participation/tournament_detail.html:261
|
||||
msgid "Archive of all sent solutions sorted by pool"
|
||||
msgstr "Archive de toutes les solutions envoyées triées par poule"
|
||||
|
||||
#: participation/templates/participation/tournament_detail.html:266
|
||||
msgid "Archive of all summary notes sorted by pool and passage"
|
||||
msgstr "Archive de toutes les notes de synthèse triées par poule et passage"
|
||||
|
||||
#: participation/templates/participation/tournament_detail.html:272
|
||||
msgid "Note spreadsheet on Google Sheets"
|
||||
msgstr "Tableur de notes sur Google Sheets"
|
||||
|
||||
#: participation/templates/participation/tournament_detail.html:277
|
||||
msgid "Archive of all printable note sheets sorted by pool"
|
||||
msgstr "Archive de toutes les fiches de notes imprimables triées par poule"
|
||||
|
||||
#: participation/templates/participation/tournament_harmonize.html:16
|
||||
#: registration/models.py:655
|
||||
msgid "Note"
|
||||
|
@ -2504,11 +2540,11 @@ msgstr ""
|
|||
msgid "Download empty notation sheet"
|
||||
msgstr "Télécharger la fiche de notation vierge"
|
||||
|
||||
#: participation/templates/participation/upload_synthesis.html:9
|
||||
#: participation/templates/participation/upload_written_review.html:9
|
||||
msgid "Templates:"
|
||||
msgstr "Modèles :"
|
||||
|
||||
#: participation/templates/participation/upload_synthesis.html:13
|
||||
#: participation/templates/participation/upload_written_review.html:14
|
||||
msgid "Warning: non-free format"
|
||||
msgstr "Attention : format non libre"
|
||||
|
||||
|
@ -2656,96 +2692,96 @@ msgstr "Vous ne pouvez pas envoyer de solution après la date limite."
|
|||
msgid "Solutions of team {trigram}.zip"
|
||||
msgstr "Solutions de l'équipe {trigram}.zip"
|
||||
|
||||
#: participation/views.py:1022
|
||||
#: participation/views.py:1023
|
||||
#, python-brace-format
|
||||
msgid "Syntheses of team {trigram}.zip"
|
||||
msgid "Written reviews of team {trigram}.zip"
|
||||
msgstr "Notes de synthèse de l'équipe {trigram}.zip"
|
||||
|
||||
#: participation/views.py:1039 participation/views.py:1054
|
||||
#: participation/views.py:1040 participation/views.py:1056
|
||||
#, python-brace-format
|
||||
msgid "Solutions of {tournament}.zip"
|
||||
msgstr "Solutions de {tournament}.zip"
|
||||
|
||||
#: participation/views.py:1039 participation/views.py:1054
|
||||
#: participation/views.py:1041 participation/views.py:1057
|
||||
#, python-brace-format
|
||||
msgid "Syntheses of {tournament}.zip"
|
||||
msgid "Written reviews of {tournament}.zip"
|
||||
msgstr "Notes de synthèse de {tournament}.zip"
|
||||
|
||||
#: participation/views.py:1063
|
||||
#: participation/views.py:1066
|
||||
#, python-brace-format
|
||||
msgid "Solutions for pool {pool} of tournament {tournament}.zip"
|
||||
msgstr "Solutions pour la poule {pool} du tournoi {tournament}.zip"
|
||||
|
||||
#: participation/views.py:1064
|
||||
#: participation/views.py:1067
|
||||
#, python-brace-format
|
||||
msgid "Syntheses for pool {pool} of tournament {tournament}.zip"
|
||||
msgid "Written reviews for pool {pool} of tournament {tournament}.zip"
|
||||
msgstr "Notes de synthèses pour la poule {pool} du tournoi {tournament}.zip"
|
||||
|
||||
#: participation/views.py:1106
|
||||
#: participation/views.py:1109
|
||||
#, python-brace-format
|
||||
msgid "Jury of pool {pool} for {tournament} with teams {teams}"
|
||||
msgstr "Jury de la poule {pool} pour {tournament} avec les équipes {teams}"
|
||||
|
||||
#: participation/views.py:1122
|
||||
#: participation/views.py:1125
|
||||
#, python-brace-format
|
||||
msgid "The jury {name} is already in the pool!"
|
||||
msgstr "{name} est déjà dans la poule !"
|
||||
|
||||
#: participation/views.py:1142
|
||||
#: participation/views.py:1145
|
||||
msgid "New jury account"
|
||||
msgstr "Nouveau compte de juré⋅e"
|
||||
|
||||
#: participation/views.py:1163
|
||||
#: participation/views.py:1166
|
||||
#, python-brace-format
|
||||
msgid "The jury {name} has been successfully added!"
|
||||
msgstr "{name} a été ajouté⋅e avec succès en tant que juré⋅e !"
|
||||
|
||||
#: participation/views.py:1199
|
||||
#: participation/views.py:1202
|
||||
#, python-brace-format
|
||||
msgid "The jury {name} has been successfully removed!"
|
||||
msgstr "{name} a été retiré⋅e avec succès du jury !"
|
||||
|
||||
#: participation/views.py:1225
|
||||
#: participation/views.py:1228
|
||||
#, python-brace-format
|
||||
msgid "The jury {name} has been successfully promoted president!"
|
||||
msgstr "{name} a été nommé⋅e président⋅e du jury !"
|
||||
|
||||
#: participation/views.py:1253
|
||||
#: participation/views.py:1256
|
||||
msgid "The following user is not registered as a jury:"
|
||||
msgstr "L'utilisateur⋅rice suivant n'est pas inscrit⋅e en tant que juré⋅e :"
|
||||
|
||||
#: participation/views.py:1269
|
||||
#: participation/views.py:1272
|
||||
msgid "Notes were successfully uploaded."
|
||||
msgstr "Les notes ont bien été envoyées."
|
||||
|
||||
#: participation/views.py:1504
|
||||
#: participation/views.py:1507
|
||||
msgid "Defender"
|
||||
msgstr "Défenseur⋅se"
|
||||
|
||||
#: participation/views.py:1510
|
||||
#: participation/views.py:1513
|
||||
msgid "Opponent"
|
||||
msgstr "Opposant⋅e"
|
||||
|
||||
#: participation/views.py:1517
|
||||
#: participation/views.py:1520
|
||||
msgid "Reviewer"
|
||||
msgstr "Rapporteur⋅rice"
|
||||
|
||||
#: participation/views.py:1524
|
||||
#: participation/views.py:1527
|
||||
msgid "Observer"
|
||||
msgstr "Observateur⋅rice"
|
||||
|
||||
#: participation/views.py:1895
|
||||
#: participation/views.py:1898
|
||||
#, python-brace-format
|
||||
msgid "Notation sheets of pool {pool} of {tournament}.zip"
|
||||
msgstr "Feuilles de notations pour la poule {pool} du tournoi {tournament}.zip"
|
||||
|
||||
#: participation/views.py:1900
|
||||
#: participation/views.py:1903
|
||||
#, python-brace-format
|
||||
msgid "Notation sheets of {tournament}.zip"
|
||||
msgstr "Feuilles de notation de {tournament}.zip"
|
||||
|
||||
#: participation/views.py:2067
|
||||
msgid "You can't upload a synthesis after the deadline."
|
||||
#: participation/views.py:2070
|
||||
msgid "You can't upload a written review after the deadline."
|
||||
msgstr "Vous ne pouvez pas envoyer de note de synthèse après la date limite."
|
||||
|
||||
#: registration/admin.py:53 registration/admin.py:69 registration/admin.py:85
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
from django.contrib import admin
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from .models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament, Tweak
|
||||
from .models import Note, Participation, Passage, Pool, Solution, Team, Tournament, Tweak, WrittenReview
|
||||
|
||||
|
||||
class ParticipationInline(admin.StackedInline):
|
||||
|
@ -32,8 +32,8 @@ class SolutionInline(admin.TabularInline):
|
|||
show_change_link = True
|
||||
|
||||
|
||||
class SynthesisInline(admin.TabularInline):
|
||||
model = Synthesis
|
||||
class WrittenReviewInline(admin.TabularInline):
|
||||
model = WrittenReview
|
||||
extra = 0
|
||||
ordering = ('passage__solution_number', 'type',)
|
||||
autocomplete_fields = ('passage',)
|
||||
|
@ -95,7 +95,7 @@ class ParticipationAdmin(admin.ModelAdmin):
|
|||
search_fields = ('team__name', 'team__trigram',)
|
||||
list_filter = ('valid', 'tournament',)
|
||||
autocomplete_fields = ('team', 'tournament',)
|
||||
inlines = (SolutionInline, SynthesisInline,)
|
||||
inlines = (SolutionInline, WrittenReviewInline,)
|
||||
|
||||
|
||||
@admin.register(Pool)
|
||||
|
@ -178,19 +178,19 @@ class SolutionAdmin(admin.ModelAdmin):
|
|||
return Tournament.final_tournament() if record.final_solution else record.participation.tournament
|
||||
|
||||
|
||||
@admin.register(Synthesis)
|
||||
class SynthesisAdmin(admin.ModelAdmin):
|
||||
@admin.register(WrittenReview)
|
||||
class WrittenReviewAdmin(admin.ModelAdmin):
|
||||
list_display = ('participation', 'type', 'defender', 'passage',)
|
||||
list_filter = ('participation__tournament', 'type', 'passage__solution_number',)
|
||||
search_fields = ('participation__team__name', 'participation__team__trigram',)
|
||||
autocomplete_fields = ('participation', 'passage',)
|
||||
|
||||
@admin.display(description=_("defender"))
|
||||
def defender(self, record: Synthesis):
|
||||
def defender(self, record: WrittenReview):
|
||||
return record.passage.defender
|
||||
|
||||
@admin.display(description=_("problem"))
|
||||
def problem(self, record: Synthesis):
|
||||
def problem(self, record: WrittenReview):
|
||||
return record.passage.solution_number
|
||||
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
from rest_framework import serializers
|
||||
|
||||
from ..models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament
|
||||
from ..models import Note, Participation, Passage, Pool, Solution, Team, Tournament, WrittenReview
|
||||
|
||||
|
||||
class NoteSerializer(serializers.ModelSerializer):
|
||||
|
@ -38,9 +38,9 @@ class SolutionSerializer(serializers.ModelSerializer):
|
|||
fields = '__all__'
|
||||
|
||||
|
||||
class SynthesisSerializer(serializers.ModelSerializer):
|
||||
class WrittenReviewSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Synthesis
|
||||
model = WrittenReview
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
|
@ -58,9 +58,9 @@ class TournamentSerializer(serializers.ModelSerializer):
|
|||
class Meta:
|
||||
model = Tournament
|
||||
fields = ('id', 'pk', 'name', 'date_start', 'date_end', 'place', 'max_teams', 'price', 'remote',
|
||||
'inscription_limit', 'solution_limit', 'solutions_draw', 'syntheses_first_phase_limit',
|
||||
'solutions_available_second_phase', 'syntheses_second_phase_limit',
|
||||
'solutions_available_third_phase', 'syntheses_third_phase_limit',
|
||||
'inscription_limit', 'solution_limit', 'solutions_draw', 'reviews_first_phase_limit',
|
||||
'solutions_available_second_phase', 'reviews_second_phase_limit',
|
||||
'solutions_available_third_phase', 'reviews_third_phase_limit',
|
||||
'description', 'organizers', 'final', 'participations',)
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from .views import NoteViewSet, ParticipationViewSet, PassageViewSet, PoolViewSet, \
|
||||
SolutionViewSet, SynthesisViewSet, TeamViewSet, TournamentViewSet, TweakViewSet
|
||||
SolutionViewSet, TeamViewSet, TournamentViewSet, TweakViewSet, WrittenReviewViewSet
|
||||
|
||||
|
||||
def register_participation_urls(router, path):
|
||||
|
@ -13,8 +13,8 @@ def register_participation_urls(router, path):
|
|||
router.register(path + "/participation", ParticipationViewSet)
|
||||
router.register(path + "/passage", PassageViewSet)
|
||||
router.register(path + "/pool", PoolViewSet)
|
||||
router.register(path + "/review", WrittenReviewViewSet)
|
||||
router.register(path + "/solution", SolutionViewSet)
|
||||
router.register(path + "/synthesis", SynthesisViewSet)
|
||||
router.register(path + "/team", TeamViewSet)
|
||||
router.register(path + "/tournament", TournamentViewSet)
|
||||
router.register(path + "/tweak", TweakViewSet)
|
||||
|
|
|
@ -4,8 +4,8 @@ from django_filters.rest_framework import DjangoFilterBackend
|
|||
from rest_framework.viewsets import ModelViewSet
|
||||
|
||||
from .serializers import NoteSerializer, ParticipationSerializer, PassageSerializer, PoolSerializer, \
|
||||
SolutionSerializer, SynthesisSerializer, TeamSerializer, TournamentSerializer, TweakSerializer
|
||||
from ..models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament, Tweak
|
||||
SolutionSerializer, TeamSerializer, TournamentSerializer, TweakSerializer, WrittenReviewSerializer
|
||||
from ..models import Note, Participation, Passage, Pool, Solution, Team, Tournament, Tweak, WrittenReview
|
||||
|
||||
|
||||
class NoteViewSet(ModelViewSet):
|
||||
|
@ -44,9 +44,9 @@ class SolutionViewSet(ModelViewSet):
|
|||
filterset_fields = ['participation', 'number', 'problem', 'final_solution', ]
|
||||
|
||||
|
||||
class SynthesisViewSet(ModelViewSet):
|
||||
queryset = Synthesis.objects.all()
|
||||
serializer_class = SynthesisSerializer
|
||||
class WrittenReviewViewSet(ModelViewSet):
|
||||
queryset = WrittenReview.objects.all()
|
||||
serializer_class = WrittenReviewSerializer
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
filterset_fields = ['participation', 'number', 'passage', 'type', ]
|
||||
|
||||
|
@ -64,9 +64,9 @@ class TournamentViewSet(ModelViewSet):
|
|||
serializer_class = TournamentSerializer
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
filterset_fields = ['name', 'date_start', 'date_end', 'place', 'max_teams', 'price', 'remote',
|
||||
'inscription_limit', 'solution_limit', 'solutions_draw', 'syntheses_first_phase_limit',
|
||||
'solutions_available_second_phase', 'syntheses_second_phase_limit',
|
||||
'solutions_available_third_phase', 'syntheses_third_phase_limit',
|
||||
'inscription_limit', 'solution_limit', 'solutions_draw', 'reviews_first_phase_limit',
|
||||
'solutions_available_second_phase', 'reviews_second_phase_limit',
|
||||
'solutions_available_third_phase', 'reviews_third_phase_limit',
|
||||
'description', 'organizers', 'final', ]
|
||||
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ from pypdf import PdfReader
|
|||
from registration.models import VolunteerRegistration
|
||||
from tfjm import settings
|
||||
|
||||
from .models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament
|
||||
from .models import Note, Participation, Passage, Pool, Solution, Team, Tournament, WrittenReview
|
||||
|
||||
|
||||
class TeamForm(forms.ModelForm):
|
||||
|
@ -137,7 +137,7 @@ class TournamentForm(forms.ModelForm):
|
|||
if settings.NB_ROUNDS < 3:
|
||||
del self.fields['date_third_phase']
|
||||
del self.fields['solutions_available_third_phase']
|
||||
del self.fields['syntheses_third_phase_limit']
|
||||
del self.fields['reviews_third_phase_limit']
|
||||
if not settings.PAYMENT_MANAGEMENT:
|
||||
del self.fields['price']
|
||||
|
||||
|
@ -151,14 +151,14 @@ class TournamentForm(forms.ModelForm):
|
|||
'solution_limit': forms.DateTimeInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%d %H:%M'),
|
||||
'solutions_draw': forms.DateTimeInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%d %H:%M'),
|
||||
'date_first_phase': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
|
||||
'syntheses_first_phase_limit': forms.DateTimeInput(attrs={'type': 'datetime-local'},
|
||||
format='%Y-%m-%d %H:%M'),
|
||||
'reviews_first_phase_limit': forms.DateTimeInput(attrs={'type': 'datetime-local'},
|
||||
format='%Y-%m-%d %H:%M'),
|
||||
'date_second_phase': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
|
||||
'syntheses_second_phase_limit': forms.DateTimeInput(attrs={'type': 'datetime-local'},
|
||||
format='%Y-%m-%d %H:%M'),
|
||||
'reviews_second_phase_limit': forms.DateTimeInput(attrs={'type': 'datetime-local'},
|
||||
format='%Y-%m-%d %H:%M'),
|
||||
'date_third_phase': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
|
||||
'syntheses_third_phase_limit': forms.DateTimeInput(attrs={'type': 'datetime-local'},
|
||||
format='%Y-%m-%d %H:%M'),
|
||||
'reviews_third_phase_limit': forms.DateTimeInput(attrs={'type': 'datetime-local'},
|
||||
format='%Y-%m-%d %H:%M'),
|
||||
'organizers': forms.SelectMultiple(attrs={
|
||||
'class': 'selectpicker',
|
||||
'data-live-search': 'true',
|
||||
|
@ -359,7 +359,7 @@ class PassageForm(forms.ModelForm):
|
|||
fields = ('position', 'solution_number', 'defender', 'opponent', 'reviewer', 'opponent', 'defender_penalties',)
|
||||
|
||||
|
||||
class SynthesisForm(forms.ModelForm):
|
||||
class WrittenReviewForm(forms.ModelForm):
|
||||
def clean_file(self):
|
||||
if "file" in self.files:
|
||||
file = self.files["file"]
|
||||
|
@ -375,11 +375,11 @@ class SynthesisForm(forms.ModelForm):
|
|||
|
||||
def save(self, commit=True):
|
||||
"""
|
||||
Don't save a synthesis with this way. Use a view instead
|
||||
Don't save a written review with this way. Use a view instead
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Synthesis
|
||||
model = WrittenReview
|
||||
fields = ('file',)
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
# Generated by Django 5.0.6 on 2024-07-06 19:19
|
||||
|
||||
import django.utils.timezone
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("participation", "0019_note_observer_oral_note_observer_writing_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameModel(
|
||||
old_name="Synthesis",
|
||||
new_name="WrittenReview",
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name="writtenreview",
|
||||
options={
|
||||
"ordering": ("passage__pool__round", "type"),
|
||||
"verbose_name": "written review",
|
||||
"verbose_name_plural": "written reviews",
|
||||
},
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name="tournament",
|
||||
old_name="syntheses_first_phase_limit",
|
||||
new_name="reviews_first_phase_limit",
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name="tournament",
|
||||
old_name="syntheses_second_phase_limit",
|
||||
new_name="reviews_second_phase_limit",
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name="tournament",
|
||||
old_name="syntheses_third_phase_limit",
|
||||
new_name="reviews_third_phase_limit",
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="tournament",
|
||||
name="reviews_first_phase_limit",
|
||||
field=models.DateTimeField(
|
||||
default=django.utils.timezone.now,
|
||||
verbose_name="limit date to upload the written reviews for the first phase",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="tournament",
|
||||
name="reviews_second_phase_limit",
|
||||
field=models.DateTimeField(
|
||||
default=django.utils.timezone.now,
|
||||
verbose_name="limit date to upload the written reviews for the second phase",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="tournament",
|
||||
name="reviews_third_phase_limit",
|
||||
field=models.DateTimeField(
|
||||
default=django.utils.timezone.now,
|
||||
verbose_name="limit date to upload the written reviews for the third phase",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="writtenreview",
|
||||
name="passage",
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="written_reviews",
|
||||
to="participation.passage",
|
||||
verbose_name="passage",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -323,8 +323,8 @@ class Tournament(models.Model):
|
|||
default=date.today,
|
||||
)
|
||||
|
||||
syntheses_first_phase_limit = models.DateTimeField(
|
||||
verbose_name=_("limit date to upload the syntheses for the first phase"),
|
||||
reviews_first_phase_limit = models.DateTimeField(
|
||||
verbose_name=_("limit date to upload the written reviews for the first phase"),
|
||||
default=timezone.now,
|
||||
)
|
||||
|
||||
|
@ -338,8 +338,8 @@ class Tournament(models.Model):
|
|||
default=False,
|
||||
)
|
||||
|
||||
syntheses_second_phase_limit = models.DateTimeField(
|
||||
verbose_name=_("limit date to upload the syntheses for the second phase"),
|
||||
reviews_second_phase_limit = models.DateTimeField(
|
||||
verbose_name=_("limit date to upload the written reviews for the second phase"),
|
||||
default=timezone.now,
|
||||
)
|
||||
|
||||
|
@ -353,8 +353,8 @@ class Tournament(models.Model):
|
|||
default=False,
|
||||
)
|
||||
|
||||
syntheses_third_phase_limit = models.DateTimeField(
|
||||
verbose_name=_("limit date to upload the syntheses for the third phase"),
|
||||
reviews_third_phase_limit = models.DateTimeField(
|
||||
verbose_name=_("limit date to upload the written reviews for the third phase"),
|
||||
default=timezone.now,
|
||||
)
|
||||
|
||||
|
@ -442,10 +442,10 @@ class Tournament(models.Model):
|
|||
return Solution.objects.filter(participation__tournament=self)
|
||||
|
||||
@property
|
||||
def syntheses(self):
|
||||
def written_reviews(self):
|
||||
if self.final:
|
||||
return Synthesis.objects.filter(final_solution=True)
|
||||
return Synthesis.objects.filter(participation__tournament=self)
|
||||
return WrittenReview.objects.filter(final_solution=True)
|
||||
return WrittenReview.objects.filter(participation__tournament=self)
|
||||
|
||||
@property
|
||||
def best_format(self):
|
||||
|
@ -911,7 +911,7 @@ class Participation(models.Model):
|
|||
'priority': 1,
|
||||
'content': content,
|
||||
})
|
||||
elif timezone.now() <= tournament.syntheses_first_phase_limit + timedelta(hours=2):
|
||||
elif timezone.now() <= tournament.reviews_first_phase_limit + timedelta(hours=2):
|
||||
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)
|
||||
reviewer_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, reviewer=self)
|
||||
|
@ -929,7 +929,7 @@ class Participation(models.Model):
|
|||
|
||||
opponent_text = _("<p>You will oppose the solution of the team {opponent} on the "
|
||||
"<a href='{solution_url}'>problem {problem}</a>. "
|
||||
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||
"You can upload your written review on <a href='{passage_url}'>this page</a>.</p>")
|
||||
solution_url = opponent_passage.defended_solution.file.url
|
||||
passage_url = reverse_lazy("participation:passage_detail", args=(opponent_passage.pk,))
|
||||
opponent_content = format_lazy(opponent_text, opponent=opponent_passage.defender.team.trigram,
|
||||
|
@ -938,7 +938,7 @@ class Participation(models.Model):
|
|||
|
||||
reviewer_text = _("<p>You will report the solution of the team {reviewer} on the "
|
||||
"<a href='{solution_url}'>problem {problem}</a>. "
|
||||
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||
"You can upload your written review on <a href='{passage_url}'>this page</a>.</p>")
|
||||
solution_url = reviewer_passage.defended_solution.file.url
|
||||
passage_url = reverse_lazy("participation:passage_detail", args=(reviewer_passage.pk,))
|
||||
reviewer_content = format_lazy(reviewer_text, reviewer=reviewer_passage.defender.team.trigram,
|
||||
|
@ -948,7 +948,7 @@ class Participation(models.Model):
|
|||
if observer_passage:
|
||||
observer_text = _("<p>You will observe the solution of the team {observer} on the "
|
||||
"<a href='{solution_url}'>problem {problem}</a>. "
|
||||
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||
"You can upload your written review 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,
|
||||
|
@ -959,24 +959,24 @@ class Participation(models.Model):
|
|||
observer_content = ""
|
||||
|
||||
if settings.TFJM_APP == "TFJM":
|
||||
syntheses_template_begin = f"{settings.STATIC_URL}tfjm/Fiche_synthèse."
|
||||
syntheses_templates = " — ".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
|
||||
for ext in ["pdf", "tex", "odt", "docx"])
|
||||
reviews_template_begin = f"{settings.STATIC_URL}tfjm/Fiche_synthèse."
|
||||
reviews_templates = " — ".join(f"<a href='{reviews_template_begin}{ext}'>{ext.upper()}</a>"
|
||||
for ext in ["pdf", "tex", "odt", "docx"])
|
||||
else:
|
||||
syntheses_template_begin = f"{settings.STATIC_URL}eteam/Written_review."
|
||||
syntheses_templates = " — ".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
|
||||
for ext in ["pdf", "tex"])
|
||||
syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>"
|
||||
reviews_template_begin = f"{settings.STATIC_URL}eteam/Written_review."
|
||||
reviews_templates = " — ".join(f"<a href='{reviews_template_begin}{ext}'>{ext.upper()}</a>"
|
||||
for ext in ["pdf", "tex"])
|
||||
reviews_templates_content = f"<p>{_('Templates:')} {reviews_templates}</p>"
|
||||
|
||||
content = defender_content + opponent_content + reviewer_content + observer_content \
|
||||
+ syntheses_templates_content
|
||||
+ reviews_templates_content
|
||||
informations.append({
|
||||
'title': _("First round"),
|
||||
'type': "info",
|
||||
'priority': 1,
|
||||
'content': content,
|
||||
})
|
||||
elif timezone.now() <= tournament.syntheses_second_phase_limit + timedelta(hours=2):
|
||||
elif timezone.now() <= tournament.reviews_second_phase_limit + timedelta(hours=2):
|
||||
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)
|
||||
reviewer_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, reviewer=self)
|
||||
|
@ -992,7 +992,7 @@ class Participation(models.Model):
|
|||
|
||||
opponent_text = _("<p>You will oppose the solution of the team {opponent} on the "
|
||||
"<a href='{solution_url}'>problem {problem}</a>. "
|
||||
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||
"You can upload your written review on <a href='{passage_url}'>this page</a>.</p>")
|
||||
solution_url = opponent_passage.defended_solution.file.url
|
||||
passage_url = reverse_lazy("participation:passage_detail", args=(opponent_passage.pk,))
|
||||
opponent_content = format_lazy(opponent_text, opponent=opponent_passage.defender.team.trigram,
|
||||
|
@ -1001,7 +1001,7 @@ class Participation(models.Model):
|
|||
|
||||
reviewer_text = _("<p>You will report the solution of the team {reviewer} on the "
|
||||
"<a href='{solution_url}'>problem {problem}</a>. "
|
||||
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||
"You can upload your written review on <a href='{passage_url}'>this page</a>.</p>")
|
||||
solution_url = reviewer_passage.defended_solution.file.url
|
||||
passage_url = reverse_lazy("participation:passage_detail", args=(reviewer_passage.pk,))
|
||||
reviewer_content = format_lazy(reviewer_text, reviewer=reviewer_passage.defender.team.trigram,
|
||||
|
@ -1011,7 +1011,7 @@ class Participation(models.Model):
|
|||
if observer_passage:
|
||||
observer_text = _("<p>You will observe the solution of the team {observer} on the "
|
||||
"<a href='{solution_url}'>problem {problem}</a>. "
|
||||
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||
"You can upload your written review 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,
|
||||
|
@ -1022,17 +1022,17 @@ class Participation(models.Model):
|
|||
observer_content = ""
|
||||
|
||||
if settings.TFJM_APP == "TFJM":
|
||||
syntheses_template_begin = f"{settings.STATIC_URL}tfjm/Fiche_synthèse."
|
||||
syntheses_templates = " — ".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
|
||||
for ext in ["pdf", "tex", "odt", "docx"])
|
||||
reviews_template_begin = f"{settings.STATIC_URL}tfjm/Fiche_synthèse."
|
||||
reviews_templates = " — ".join(f"<a href='{reviews_template_begin}{ext}'>{ext.upper()}</a>"
|
||||
for ext in ["pdf", "tex", "odt", "docx"])
|
||||
else:
|
||||
syntheses_template_begin = f"{settings.STATIC_URL}eteam/Written_review."
|
||||
syntheses_templates = " — ".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
|
||||
for ext in ["pdf", "tex"])
|
||||
syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>"
|
||||
reviews_template_begin = f"{settings.STATIC_URL}eteam/Written_review."
|
||||
reviews_templates = " — ".join(f"<a href='{reviews_template_begin}{ext}'>{ext.upper()}</a>"
|
||||
for ext in ["pdf", "tex"])
|
||||
reviews_templates_content = f"<p>{_('Templates:')} {reviews_templates}</p>"
|
||||
|
||||
content = defender_content + opponent_content + reviewer_content + observer_content \
|
||||
+ syntheses_templates_content
|
||||
+ reviews_templates_content
|
||||
informations.append({
|
||||
'title': _("Second round"),
|
||||
'type': "info",
|
||||
|
@ -1040,7 +1040,7 @@ class Participation(models.Model):
|
|||
'content': content,
|
||||
})
|
||||
elif settings.TFJM_APP == "ETEAM" \
|
||||
and timezone.now() <= tournament.syntheses_third_phase_limit + timedelta(hours=2):
|
||||
and timezone.now() <= tournament.reviews_third_phase_limit + timedelta(hours=2):
|
||||
defender_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, defender=self)
|
||||
opponent_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, opponent=self)
|
||||
reviewer_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, reviewer=self)
|
||||
|
@ -1056,7 +1056,7 @@ class Participation(models.Model):
|
|||
|
||||
opponent_text = _("<p>You will oppose the solution of the team {opponent} on the "
|
||||
"<a href='{solution_url}'>problem {problem}</a>. "
|
||||
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||
"You can upload your written review on <a href='{passage_url}'>this page</a>.</p>")
|
||||
solution_url = opponent_passage.defended_solution.file.url
|
||||
passage_url = reverse_lazy("participation:passage_detail", args=(opponent_passage.pk,))
|
||||
opponent_content = format_lazy(opponent_text, opponent=opponent_passage.defender.team.trigram,
|
||||
|
@ -1065,7 +1065,7 @@ class Participation(models.Model):
|
|||
|
||||
reviewer_text = _("<p>You will report the solution of the team {reviewer} on the "
|
||||
"<a href='{solution_url}'>problem {problem}</a>. "
|
||||
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||
"You can upload your written review on <a href='{passage_url}'>this page</a>.</p>")
|
||||
solution_url = reviewer_passage.defended_solution.file.url
|
||||
passage_url = reverse_lazy("participation:passage_detail", args=(reviewer_passage.pk,))
|
||||
reviewer_content = format_lazy(reviewer_text, reviewer=reviewer_passage.defender.team.trigram,
|
||||
|
@ -1075,7 +1075,7 @@ class Participation(models.Model):
|
|||
if observer_passage:
|
||||
observer_text = _("<p>You will observe the solution of the team {observer} on the "
|
||||
"<a href='{solution_url}'>problem {problem}</a>. "
|
||||
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||
"You can upload your written review 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,
|
||||
|
@ -1086,17 +1086,17 @@ class Participation(models.Model):
|
|||
observer_content = ""
|
||||
|
||||
if settings.TFJM_APP == "TFJM":
|
||||
syntheses_template_begin = f"{settings.STATIC_URL}tfjm/Fiche_synthèse."
|
||||
syntheses_templates = " — ".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
|
||||
for ext in ["pdf", "tex", "odt", "docx"])
|
||||
reviews_template_begin = f"{settings.STATIC_URL}tfjm/Fiche_synthèse."
|
||||
reviews_templates = " — ".join(f"<a href='{reviews_template_begin}{ext}'>{ext.upper()}</a>"
|
||||
for ext in ["pdf", "tex", "odt", "docx"])
|
||||
else:
|
||||
syntheses_template_begin = f"{settings.STATIC_URL}eteam/Written_review."
|
||||
syntheses_templates = " — ".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
|
||||
for ext in ["pdf", "tex"])
|
||||
syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>"
|
||||
reviews_template_begin = f"{settings.STATIC_URL}eteam/Written_review."
|
||||
reviews_templates = " — ".join(f"<a href='{reviews_template_begin}{ext}'>{ext.upper()}</a>"
|
||||
for ext in ["pdf", "tex"])
|
||||
reviews_templates_content = f"<p>{_('Templates:')} {reviews_templates}</p>"
|
||||
|
||||
content = defender_content + opponent_content + reviewer_content + observer_content \
|
||||
+ syntheses_templates_content
|
||||
+ reviews_templates_content
|
||||
informations.append({
|
||||
'title': _("Second round"),
|
||||
'type': "info",
|
||||
|
@ -1256,7 +1256,7 @@ class Pool(models.Model):
|
|||
f"{_('Reviewer')} ({passage.reviewer.team.trigram})", ""]
|
||||
+ ([f"{_('Observer')} ({passage.observer.team.trigram})", ""] if has_observer else [])
|
||||
for passage in passages), start=[str(_("Role")), ""]),
|
||||
sum(([f"{_('Writing')} (/{20 if settings.TFJM_APP == "TFJM" else 10})",
|
||||
sum(([f"{_('Writing')} (/{20 if settings.TFJM_APP == 'TFJM' else 10})",
|
||||
f"{_('Oral')} (/{20 if settings.TFJM_APP == 'TFJM' else 10})",
|
||||
f"{_('Writing')} (/10)", f"{_('Oral')} (/10)", f"{_('Writing')} (/10)", f"{_('Oral')} (/10)"]
|
||||
+ ([f"{_('Writing')} (/10)", f"{_('Oral')} (/10)"] if has_observer else [])
|
||||
|
@ -1905,8 +1905,12 @@ def get_solution_filename(instance, filename):
|
|||
+ ("_final" if instance.final_solution else "")
|
||||
|
||||
|
||||
def get_review_filename(instance, filename):
|
||||
return f"reviews/{instance.participation.team.trigram}_{instance.type}_{instance.passage.pk}"
|
||||
|
||||
|
||||
def get_synthesis_filename(instance, filename):
|
||||
return f"syntheses/{instance.participation.team.trigram}_{instance.type}_{instance.passage.pk}"
|
||||
return get_review_filename(instance, filename)
|
||||
|
||||
|
||||
class Solution(models.Model):
|
||||
|
@ -1951,7 +1955,7 @@ class Solution(models.Model):
|
|||
ordering = ('participation__team__trigram', 'final_solution', 'problem',)
|
||||
|
||||
|
||||
class Synthesis(models.Model):
|
||||
class WrittenReview(models.Model):
|
||||
participation = models.ForeignKey(
|
||||
Participation,
|
||||
on_delete=models.CASCADE,
|
||||
|
@ -1961,7 +1965,7 @@ class Synthesis(models.Model):
|
|||
passage = models.ForeignKey(
|
||||
Passage,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="syntheses",
|
||||
related_name="written_reviews",
|
||||
verbose_name=_("passage"),
|
||||
)
|
||||
|
||||
|
@ -1980,7 +1984,7 @@ class Synthesis(models.Model):
|
|||
)
|
||||
|
||||
def __str__(self):
|
||||
return _("Synthesis of {team} as {type} for problem {problem} of {defender}").format(
|
||||
return _("Written review of {team} as {type} for problem {problem} of {defender}").format(
|
||||
team=self.participation.team.trigram,
|
||||
type=self.get_type_display(),
|
||||
problem=self.passage.solution_number,
|
||||
|
@ -1988,8 +1992,8 @@ class Synthesis(models.Model):
|
|||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("synthesis")
|
||||
verbose_name_plural = _("syntheses")
|
||||
verbose_name = _("written review")
|
||||
verbose_name_plural = _("written reviews")
|
||||
unique_together = (('participation', 'passage', 'type', ), )
|
||||
ordering = ('passage__pool__round', 'type',)
|
||||
|
||||
|
|
|
@ -47,10 +47,10 @@
|
|||
|
||||
<dt class="col-sm-3">{% trans "Syntheses:" %}</dt>
|
||||
<dd class="col-sm-9">
|
||||
{% for synthesis in passage.syntheses.all %}
|
||||
<a href="{{ synthesis.file.url }}">{{ synthesis }}{% if not forloop.last %}, {% endif %}</a>
|
||||
{% for review in passage.written_reviews.all %}
|
||||
<a href="{{ review.file.url }}">{{ review }}{% if not forloop.last %}, {% endif %}</a>
|
||||
{% empty %}
|
||||
{% trans "No synthesis was uploaded yet." %}
|
||||
{% trans "No review was uploaded yet." %}
|
||||
{% endfor %}
|
||||
</dd>
|
||||
</dl>
|
||||
|
@ -63,7 +63,7 @@
|
|||
</div>
|
||||
{% elif user.registration.participates %}
|
||||
<div class="card-footer text-center">
|
||||
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#uploadSynthesisModal">{% trans "Upload synthesis" %}</button>
|
||||
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#uploadWrittenReviewModal">{% trans "Upload review" %}</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
@ -184,10 +184,10 @@
|
|||
{% include "base_modal.html" with modal_id=note.modal_name %}
|
||||
{% endfor %}
|
||||
{% elif user.registration.participates %}
|
||||
{% trans "Upload synthesis" as modal_title %}
|
||||
{% trans "Upload review" as modal_title %}
|
||||
{% trans "Upload" as modal_button %}
|
||||
{% url "participation:upload_synthesis" pk=passage.pk as modal_action %}
|
||||
{% include "base_modal.html" with modal_id="uploadSynthesis" modal_enctype="multipart/form-data" %}
|
||||
{% url "participation:upload_review" pk=passage.pk as modal_action %}
|
||||
{% include "base_modal.html" with modal_id="uploadWrittenReview" modal_enctype="multipart/form-data" %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
@ -201,8 +201,8 @@
|
|||
initModal("{{ note.modal_name }}", "{% url "participation:update_notes" pk=note.pk %}")
|
||||
{% endfor %}
|
||||
{% elif user.registration.participates %}
|
||||
initModal("uploadSynthesis", "{% url "participation:upload_synthesis" pk=passage.pk %}")
|
||||
initModal("uploadWrittenReview", "{% url "participation:upload_review" pk=passage.pk %}")
|
||||
{% endif %}
|
||||
});
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -62,15 +62,15 @@
|
|||
{% for passage in pool.passages.all %}
|
||||
<li class="list-group-item">
|
||||
{{ passage.defender.team.trigram }} — {{ passage.get_solution_number_display }} :
|
||||
{% for synthesis in passage.syntheses.all %}
|
||||
<a href="{{ synthesis.file.url }}">{{ synthesis.participation.team.trigram }} ({{ synthesis.get_type_display }})</a>{% if not forloop.last %}, {% endif %}
|
||||
{% for review in passage.written_reviews.all %}
|
||||
<a href="{{ review.file.url }}">{{ review.participation.team.trigram }} ({{ review.get_type_display }})</a>{% if not forloop.last %}, {% endif %}
|
||||
{% empty %}
|
||||
{% trans "No synthesis was uploaded yet." %}
|
||||
{% trans "No review was uploaded yet." %}
|
||||
{% endfor %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<a href="{% url 'participation:pool_download_syntheses' pool_id=pool.id %}" class="badge rounded-pill text-bg-secondary">
|
||||
<a href="{% url 'participation:pool_download_written_review' pool_id=pool.id %}" class="badge rounded-pill text-bg-secondary">
|
||||
<i class="fas fa-download"></i> {% trans "Download all" %}
|
||||
</a>
|
||||
</dd>
|
||||
|
|
|
@ -38,15 +38,15 @@
|
|||
<dt class="col-sm-6 text-sm-end">{% trans 'date of the random draw'|capfirst %}</dt>
|
||||
<dd class="col-sm-6">{{ tournament.solutions_draw }}</dd>
|
||||
|
||||
<dt class="col-sm-6 text-sm-end">{% trans 'date of maximal syntheses submission for the first round'|capfirst %}</dt>
|
||||
<dd class="col-sm-6">{{ tournament.syntheses_first_phase_limit }}</dd>
|
||||
<dt class="col-sm-6 text-sm-end">{% trans 'date of maximal written reviews submission for the first round'|capfirst %}</dt>
|
||||
<dd class="col-sm-6">{{ tournament.reviews_first_phase_limit }}</dd>
|
||||
|
||||
<dt class="col-sm-6 text-sm-end">{% trans 'date of maximal syntheses submission for the second round'|capfirst %}</dt>
|
||||
<dd class="col-sm-6">{{ tournament.syntheses_second_phase_limit }}</dd>
|
||||
<dt class="col-sm-6 text-sm-end">{% trans 'date of maximal written reviews submission for the second round'|capfirst %}</dt>
|
||||
<dd class="col-sm-6">{{ tournament.reviews_second_phase_limit }}</dd>
|
||||
|
||||
{% if TFJM.APP == "ETEAM" %}
|
||||
<dt class="col-sm-6 text-sm-end">{% trans 'date of maximal syntheses submission for the third round'|capfirst %}</dt>
|
||||
<dd class="col-sm-6">{{ tournament.syntheses_third_phase_limit }}</dd>
|
||||
<dt class="col-sm-6 text-sm-end">{% trans 'date of maximal written reviews submission for the third round'|capfirst %}</dt>
|
||||
<dd class="col-sm-6">{{ tournament.reviews_third_phase_limit }}</dd>
|
||||
{% endif %}
|
||||
|
||||
<dt class="col-sm-6 text-sm-end">{% trans 'description'|capfirst %}</dt>
|
||||
|
@ -233,48 +233,48 @@
|
|||
<ul>
|
||||
<li>
|
||||
<a href="{% url "participation:tournament_csv" pk=tournament.pk %}">
|
||||
Validated team participant data spreadsheet
|
||||
{% trans "Validated team participant data spreadsheet" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url "participation:tournament_csv" pk=tournament.pk %}?all">
|
||||
All teams participant data spreadsheet
|
||||
{% trans "All teams participant data spreadsheet" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url "participation:tournament_authorizations" tournament_id=tournament.id %}">
|
||||
Archive of all authorisations sorted by team and person
|
||||
{% trans "Archive of all authorisations sorted by team and person" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url "participation:tournament_solutions" tournament_id=tournament.id %}">
|
||||
Archive of all submitted solutions sorted by team
|
||||
{% trans "Archive of all submitted solutions sorted by team" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url "participation:tournament_solutions" tournament_id=tournament.id %}?sort_by=problem">
|
||||
Archive of all sent solutions sorted by problem
|
||||
{% trans "Archive of all sent solutions sorted by problem" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url "participation:tournament_solutions" tournament_id=tournament.id %}?sort_by=pool">
|
||||
Archive of all sent solutions sorted by pool
|
||||
{% trans "Archive of all sent solutions sorted by pool" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url "participation:tournament_syntheses" tournament_id=tournament.id %}?sort_by=pool">
|
||||
Archive of all summary notes sorted by pool and passage
|
||||
<a href="{% url "participation:tournament_written_reviews" tournament_id=tournament.id %}?sort_by=pool">
|
||||
{% trans "Archive of all summary notes sorted by pool and passage" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://docs.google.com/spreadsheets/d/{{ tournament.notes_sheet_id }}/edit">
|
||||
<i class="fas fa-table"></i>
|
||||
Note spreadsheet on Google Sheets
|
||||
{% trans "Note spreadsheet on Google Sheets" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url "participation:tournament_notation_sheets" tournament_id=tournament.id %}">
|
||||
Archive of all printable note sheets sorted by pool
|
||||
{% trans "Archive of all printable note sheets sorted by pool" %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
@ -8,11 +8,11 @@ from .views import CreateTeamView, FinalNotationSheetTemplateView, GSheetNotific
|
|||
PassageDetailView, PassageUpdateView, PoolCreateView, PoolDetailView, PoolJuryView, PoolNotesTemplateView, \
|
||||
PoolPresideJuryView, PoolRemoveJuryView, PoolUpdateView, PoolUploadNotesView, \
|
||||
ScaleNotationSheetTemplateView, SelectTeamFinalView, \
|
||||
SolutionsDownloadView, SolutionUploadView, SynthesisUploadView, \
|
||||
SolutionsDownloadView, SolutionUploadView, \
|
||||
TeamAuthorizationsView, TeamDetailView, TeamLeaveView, TeamListView, TeamUpdateView, \
|
||||
TeamUploadMotivationLetterView, TournamentCreateView, TournamentDetailView, TournamentExportCSVView, \
|
||||
TournamentHarmonizeNoteView, TournamentHarmonizeView, TournamentListView, TournamentPaymentsView, \
|
||||
TournamentPublishNotesView, TournamentUpdateView
|
||||
TournamentPublishNotesView, TournamentUpdateView, WrittenReviewUploadView
|
||||
|
||||
|
||||
app_name = "participation"
|
||||
|
@ -42,8 +42,8 @@ urlpatterns = [
|
|||
name="tournament_authorizations"),
|
||||
path("tournament/<int:tournament_id>/solutions/", SolutionsDownloadView.as_view(),
|
||||
name="tournament_solutions"),
|
||||
path("tournament/<int:tournament_id>/syntheses/", SolutionsDownloadView.as_view(),
|
||||
name="tournament_syntheses"),
|
||||
path("tournament/<int:tournament_id>/written_reviews/", SolutionsDownloadView.as_view(),
|
||||
name="tournament_written_reviews"),
|
||||
path("tournament/<int:tournament_id>/notation/sheets/", NotationSheetsArchiveView.as_view(),
|
||||
name="tournament_notation_sheets"),
|
||||
path("tournament/<int:pk>/notation/notifications/", GSheetNotificationsView.as_view(),
|
||||
|
@ -60,7 +60,7 @@ urlpatterns = [
|
|||
path("pools/<int:pk>/", PoolDetailView.as_view(), name="pool_detail"),
|
||||
path("pools/<int:pk>/update/", PoolUpdateView.as_view(), name="pool_update"),
|
||||
path("pools/<int:pool_id>/solutions/", SolutionsDownloadView.as_view(), name="pool_download_solutions"),
|
||||
path("pools/<int:pool_id>/syntheses/", SolutionsDownloadView.as_view(), name="pool_download_syntheses"),
|
||||
path("pools/<int:pool_id>/written_reviews/", SolutionsDownloadView.as_view(), name="pool_download_written_reviews"),
|
||||
path("pools/<int:pk>/notation/scale/", ScaleNotationSheetTemplateView.as_view(), name="pool_scale_note_sheet"),
|
||||
path("pools/<int:pk>/notation/final/", FinalNotationSheetTemplateView.as_view(), name="pool_final_note_sheet"),
|
||||
path("pools/<int:pool_id>/notation/sheets/", NotationSheetsArchiveView.as_view(), name="pool_notation_sheets"),
|
||||
|
@ -71,6 +71,6 @@ urlpatterns = [
|
|||
path("pools/<int:pk>/upload-notes/template/", PoolNotesTemplateView.as_view(), name="pool_notes_template"),
|
||||
path("pools/passages/<int:pk>/", PassageDetailView.as_view(), name="passage_detail"),
|
||||
path("pools/passages/<int:pk>/update/", PassageUpdateView.as_view(), name="passage_update"),
|
||||
path("pools/passages/<int:pk>/solution/", SynthesisUploadView.as_view(), name="upload_synthesis"),
|
||||
path("pools/passages/<int:pk>/written_review/", WrittenReviewUploadView.as_view(), name="upload_written_review"),
|
||||
path("pools/passages/notes/<int:pk>/", NoteUpdateView.as_view(), name="update_notes"),
|
||||
]
|
||||
|
|
|
@ -46,9 +46,9 @@ from tfjm.lists import get_sympa_client
|
|||
from tfjm.views import AdminMixin, VolunteerMixin
|
||||
|
||||
from .forms import AddJuryForm, JoinTeamForm, MotivationLetterForm, NoteForm, ParticipationForm, PassageForm, \
|
||||
PoolForm, RequestValidationForm, SolutionForm, SynthesisForm, TeamForm, TournamentForm, \
|
||||
UploadNotesForm, ValidateParticipationForm
|
||||
from .models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament, Tweak
|
||||
PoolForm, RequestValidationForm, SolutionForm, TeamForm, TournamentForm, UploadNotesForm, \
|
||||
ValidateParticipationForm, WrittenReviewForm
|
||||
from .models import Note, Participation, Passage, Pool, Solution, Team, Tournament, Tweak, WrittenReview
|
||||
from .tables import NoteTable, ParticipationTable, PassageTable, PoolTable, TeamTable, TournamentTable
|
||||
|
||||
|
||||
|
@ -977,7 +977,7 @@ class PoolUpdateView(VolunteerMixin, UpdateView):
|
|||
|
||||
class SolutionsDownloadView(VolunteerMixin, View):
|
||||
"""
|
||||
Download all solutions or syntheses as a ZIP archive.
|
||||
Download all solutions or written reviews as a ZIP archive.
|
||||
"""
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
|
@ -1018,11 +1018,12 @@ class SolutionsDownloadView(VolunteerMixin, View):
|
|||
if 'team_id' in kwargs:
|
||||
team = Team.objects.get(pk=kwargs["team_id"])
|
||||
solutions = Solution.objects.filter(participation=team.participation).all()
|
||||
syntheses = Synthesis.objects.filter(participation=team.participation).all()
|
||||
filename = _("Solutions of team {trigram}.zip") if is_solution else _("Syntheses of team {trigram}.zip")
|
||||
written_reviews = WrittenReview.objects.filter(participation=team.participation).all()
|
||||
filename = _("Solutions of team {trigram}.zip") if is_solution \
|
||||
else _("Written reviews of team {trigram}.zip")
|
||||
filename = filename.format(trigram=team.trigram)
|
||||
|
||||
def prefix(s: Solution | Synthesis) -> str:
|
||||
def prefix(s: Solution | WrittenReview) -> str:
|
||||
return ""
|
||||
elif 'tournament_id' in kwargs:
|
||||
tournament = Tournament.objects.get(pk=kwargs["tournament_id"])
|
||||
|
@ -1035,11 +1036,12 @@ class SolutionsDownloadView(VolunteerMixin, View):
|
|||
for sol in pool.solutions:
|
||||
sol.pool = pool
|
||||
solutions.append(sol)
|
||||
syntheses = Synthesis.objects.filter(passage__pool__tournament=tournament).all()
|
||||
filename = _("Solutions of {tournament}.zip") if is_solution else _("Syntheses of {tournament}.zip")
|
||||
written_reviews = WrittenReview.objects.filter(passage__pool__tournament=tournament).all()
|
||||
filename = _("Solutions of {tournament}.zip") if is_solution \
|
||||
else _("Written reviews of {tournament}.zip")
|
||||
filename = filename.format(tournament=tournament.name)
|
||||
|
||||
def prefix(s: Solution | Synthesis) -> str:
|
||||
def prefix(s: Solution | WrittenReview) -> str:
|
||||
pool = s.pool if is_solution else s.passage.pool
|
||||
p = f"Poule {pool.short_name}/"
|
||||
if not is_solution:
|
||||
|
@ -1050,27 +1052,28 @@ class SolutionsDownloadView(VolunteerMixin, View):
|
|||
solutions = Solution.objects.filter(participation__tournament=tournament).all()
|
||||
else:
|
||||
solutions = Solution.objects.filter(final_solution=True).all()
|
||||
syntheses = Synthesis.objects.filter(passage__pool__tournament=tournament).all()
|
||||
filename = _("Solutions of {tournament}.zip") if is_solution else _("Syntheses of {tournament}.zip")
|
||||
written_reviews = WrittenReview.objects.filter(passage__pool__tournament=tournament).all()
|
||||
filename = _("Solutions of {tournament}.zip") if is_solution \
|
||||
else _("Written reviews of {tournament}.zip")
|
||||
filename = filename.format(tournament=tournament.name)
|
||||
|
||||
def prefix(s: Solution | Synthesis) -> str:
|
||||
def prefix(s: Solution | WrittenReview) -> str:
|
||||
return f"{s.participation.team.trigram}/" if sort_by == "team" else f"Problème {s.problem}/"
|
||||
else:
|
||||
pool = Pool.objects.get(pk=kwargs["pool_id"])
|
||||
solutions = pool.solutions
|
||||
syntheses = Synthesis.objects.filter(passage__pool=pool).all()
|
||||
written_reviews = WrittenReview.objects.filter(passage__pool=pool).all()
|
||||
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 _("Written reviews for pool {pool} of tournament {tournament}.zip")
|
||||
filename = filename.format(pool=pool.short_name,
|
||||
tournament=pool.tournament.name)
|
||||
|
||||
def prefix(s: Solution | Synthesis) -> str:
|
||||
def prefix(s: Solution | WrittenReview) -> str:
|
||||
return ""
|
||||
|
||||
output = BytesIO()
|
||||
zf = ZipFile(output, "w")
|
||||
for s in (solutions if is_solution else syntheses):
|
||||
for s in (solutions if is_solution else written_reviews):
|
||||
if s.file.storage.exists(s.file.path):
|
||||
zf.write("media/" + s.file.name, prefix(s) + f"{s}.pdf")
|
||||
|
||||
|
@ -2028,9 +2031,9 @@ class PassageUpdateView(VolunteerMixin, UpdateView):
|
|||
return self.handle_no_permission()
|
||||
|
||||
|
||||
class SynthesisUploadView(LoginRequiredMixin, FormView):
|
||||
template_name = "participation/upload_synthesis.html"
|
||||
form_class = SynthesisForm
|
||||
class WrittenReviewUploadView(LoginRequiredMixin, FormView):
|
||||
template_name = "participation/upload_written_review.html"
|
||||
form_class = WrittenReviewForm
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.user.is_authenticated or not request.user.registration.participates:
|
||||
|
@ -2057,14 +2060,14 @@ class SynthesisUploadView(LoginRequiredMixin, FormView):
|
|||
form_syn = form.instance
|
||||
form_syn.type = 1 if self.participation == self.passage.opponent \
|
||||
else 2 if self.participation == self.passage.reviewer else 3
|
||||
syn_qs = Synthesis.objects.filter(participation=self.participation,
|
||||
passage=self.passage,
|
||||
type=form_syn.type).all()
|
||||
syn_qs = WrittenReview.objects.filter(participation=self.participation,
|
||||
passage=self.passage,
|
||||
type=form_syn.type).all()
|
||||
|
||||
deadline = self.passage.pool.tournament.syntheses_first_phase_limit if self.passage.pool.round == 1 \
|
||||
else self.passage.pool.tournament.syntheses_second_phase_limit
|
||||
deadline = self.passage.pool.tournament.reviews_first_phase_limit if self.passage.pool.round == 1 \
|
||||
else self.passage.pool.tournament.reviews_second_phase_limit
|
||||
if syn_qs.exists() and timezone.now() > deadline:
|
||||
form.add_error(None, _("You can't upload a synthesis after the deadline."))
|
||||
form.add_error(None, _("You can't upload a written review after the deadline."))
|
||||
return self.form_invalid(form)
|
||||
|
||||
# Drop previous solution if existing
|
||||
|
|
|
@ -26,7 +26,7 @@ from django.utils.translation import gettext_lazy as _
|
|||
from django.views.generic import CreateView, DetailView, RedirectView, TemplateView, UpdateView, View
|
||||
from django_tables2 import SingleTableView
|
||||
from magic import Magic
|
||||
from participation.models import Passage, Solution, Synthesis, Tournament
|
||||
from participation.models import Passage, Solution, Tournament, WrittenReview
|
||||
from tfjm.tokens import email_validation_token
|
||||
from tfjm.views import UserMixin, UserRegistrationMixin, VolunteerMixin
|
||||
|
||||
|
@ -871,30 +871,30 @@ class SolutionView(LoginRequiredMixin, View):
|
|||
return FileResponse(open(path, "rb"), content_type=mime_type, filename=true_file_name)
|
||||
|
||||
|
||||
class SynthesisView(LoginRequiredMixin, View):
|
||||
class WrittenReviewView(LoginRequiredMixin, View):
|
||||
"""
|
||||
Display the sent synthesis.
|
||||
Display the sent written reviews.
|
||||
"""
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
filename = kwargs["filename"]
|
||||
path = f"media/syntheses/{filename}"
|
||||
path = f"media/reviews/{filename}"
|
||||
if not os.path.exists(path):
|
||||
raise Http404
|
||||
synthesis = Synthesis.objects.get(file__endswith=filename)
|
||||
reviews = WrittenReview.objects.get(file__endswith=filename)
|
||||
user = request.user
|
||||
if not (user.registration.is_admin or user.registration.is_volunteer
|
||||
and (user.registration in synthesis.passage.pool.juries.all()
|
||||
or user.registration in synthesis.passage.pool.tournament.organizers.all()
|
||||
or user.registration.pools_presided.filter(tournament=synthesis.passage.pool.tournament).exists())
|
||||
or user.registration.participates and user.registration.team == synthesis.participation.team):
|
||||
and (user.registration in reviews.passage.pool.juries.all()
|
||||
or user.registration in reviews.passage.pool.tournament.organizers.all()
|
||||
or user.registration.pools_presided.filter(tournament=reviews.passage.pool.tournament).exists())
|
||||
or user.registration.participates and user.registration.team == reviews.participation.team):
|
||||
raise PermissionDenied
|
||||
# Guess mime type of the file
|
||||
mime = Magic(mime=True)
|
||||
mime_type = mime.from_file(path)
|
||||
ext = mime_type.split("/")[1].replace("jpeg", "jpg")
|
||||
# Replace file name
|
||||
true_file_name = str(synthesis) + f".{ext}"
|
||||
true_file_name = str(reviews) + f".{ext}"
|
||||
return FileResponse(open(path, "rb"), content_type=mime_type, filename=true_file_name)
|
||||
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ from django.views.defaults import bad_request, page_not_found, permission_denied
|
|||
from django.views.generic import TemplateView
|
||||
from participation.views import MotivationLetterView
|
||||
from registration.views import HealthSheetView, ParentalAuthorizationView, PhotoAuthorizationView, \
|
||||
ReceiptView, SolutionView, SynthesisView, VaccineSheetView
|
||||
ReceiptView, SolutionView, VaccineSheetView, WrittenReviewView
|
||||
|
||||
from .views import AdminSearchView
|
||||
|
||||
|
@ -61,8 +61,8 @@ urlpatterns = [
|
|||
|
||||
path('media/solutions/<str:filename>/', SolutionView.as_view(),
|
||||
name='solution'),
|
||||
path('media/syntheses/<str:filename>/', SynthesisView.as_view(),
|
||||
name='synthesis'),
|
||||
path('media/reviews/<str:filename>/', WrittenReviewView.as_view(),
|
||||
name='reviews'),
|
||||
]
|
||||
|
||||
if settings.DEBUG:
|
||||
|
|
Loading…
Reference in New Issue