mirror of
https://gitlab.com/animath/si/plateforme.git
synced 2024-11-30 10:53:01 +00:00
Compare commits
No commits in common. "620bbe78170815b35f96c01c0b8bf24ceb8e62ad" and "696863f6c365f18ddba8db339aed5d4e0cf6d6ff" have entirely different histories.
620bbe7817
...
696863f6c3
@ -416,7 +416,7 @@ class Pool(models.Model):
|
|||||||
passage_pool = pool2
|
passage_pool = pool2
|
||||||
passage_position = 1 + i // 2
|
passage_position = 1 + i // 2
|
||||||
|
|
||||||
reporter = tds[line[0]].participation
|
defender = tds[line[0]].participation
|
||||||
opponent = tds[line[1]].participation
|
opponent = tds[line[1]].participation
|
||||||
reviewer = tds[line[2]].participation
|
reviewer = tds[line[2]].participation
|
||||||
observer = tds[line[3]].participation if self.size >= 4 and settings.TFJM_APP == "ETEAM" else None
|
observer = tds[line[3]].participation if self.size >= 4 and settings.TFJM_APP == "ETEAM" else None
|
||||||
@ -426,11 +426,11 @@ class Pool(models.Model):
|
|||||||
pool=passage_pool,
|
pool=passage_pool,
|
||||||
position=passage_position,
|
position=passage_position,
|
||||||
solution_number=tds[line[0]].accepted,
|
solution_number=tds[line[0]].accepted,
|
||||||
reporter=reporter,
|
defender=defender,
|
||||||
opponent=opponent,
|
opponent=opponent,
|
||||||
reviewer=reviewer,
|
reviewer=reviewer,
|
||||||
observer=observer,
|
observer=observer,
|
||||||
reporter_penalties=tds[line[0]].penalty_int,
|
defender_penalties=tds[line[0]].penalty_int,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Update Google Sheets
|
# Update Google Sheets
|
||||||
@ -549,7 +549,7 @@ class TeamDraw(models.Model):
|
|||||||
@property
|
@property
|
||||||
def penalty(self):
|
def penalty(self):
|
||||||
"""
|
"""
|
||||||
The penalty multiplier on the reporter oral, in percentage, which is a malus of 25% for each penalty.
|
The penalty multiplier on the defender oral, in percentage, which is a malus of 25% for each penalty.
|
||||||
"""
|
"""
|
||||||
return 25 * self.penalty_int
|
return 25 * self.penalty_int
|
||||||
|
|
||||||
|
@ -521,9 +521,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
teamTd.innerText = team
|
teamTd.innerText = team
|
||||||
teamTr.append(teamTd)
|
teamTr.append(teamTd)
|
||||||
|
|
||||||
let reporterTd = document.createElement('td')
|
let defenderTd = document.createElement('td')
|
||||||
reporterTd.classList.add('text-center')
|
defenderTd.classList.add('text-center')
|
||||||
reporterTd.innerText = 'Déf'
|
defenderTd.innerText = 'Déf'
|
||||||
|
|
||||||
let opponentTd = document.createElement('td')
|
let opponentTd = document.createElement('td')
|
||||||
opponentTd.classList.add('text-center')
|
opponentTd.classList.add('text-center')
|
||||||
@ -537,29 +537,29 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
if (poule.teams.length === 3) {
|
if (poule.teams.length === 3) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0:
|
case 0:
|
||||||
teamTr.append(reporterTd, reviewerTd, opponentTd)
|
teamTr.append(defenderTd, reviewerTd, opponentTd)
|
||||||
break
|
break
|
||||||
case 1:
|
case 1:
|
||||||
teamTr.append(opponentTd, reporterTd, reviewerTd)
|
teamTr.append(opponentTd, defenderTd, reviewerTd)
|
||||||
break
|
break
|
||||||
case 2:
|
case 2:
|
||||||
teamTr.append(reviewerTd, opponentTd, reporterTd)
|
teamTr.append(reviewerTd, opponentTd, defenderTd)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
} else if (poule.teams.length === 4) {
|
} else if (poule.teams.length === 4) {
|
||||||
let emptyTd = document.createElement('td')
|
let emptyTd = document.createElement('td')
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0:
|
case 0:
|
||||||
teamTr.append(reporterTd, emptyTd, reviewerTd, opponentTd)
|
teamTr.append(defenderTd, emptyTd, reviewerTd, opponentTd)
|
||||||
break
|
break
|
||||||
case 1:
|
case 1:
|
||||||
teamTr.append(opponentTd, reporterTd, emptyTd, reviewerTd)
|
teamTr.append(opponentTd, defenderTd, emptyTd, reviewerTd)
|
||||||
break
|
break
|
||||||
case 2:
|
case 2:
|
||||||
teamTr.append(reviewerTd, opponentTd, reporterTd, emptyTd)
|
teamTr.append(reviewerTd, opponentTd, defenderTd, emptyTd)
|
||||||
break
|
break
|
||||||
case 3:
|
case 3:
|
||||||
teamTr.append(emptyTd, reviewerTd, opponentTd, reporterTd)
|
teamTr.append(emptyTd, reviewerTd, opponentTd, defenderTd)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
} else if (poule.teams.length === 5) {
|
} else if (poule.teams.length === 5) {
|
||||||
@ -567,19 +567,19 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
let emptyTd2 = document.createElement('td')
|
let emptyTd2 = document.createElement('td')
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0:
|
case 0:
|
||||||
teamTr.append(reporterTd, emptyTd, opponentTd, reviewerTd, emptyTd2)
|
teamTr.append(defenderTd, emptyTd, opponentTd, reviewerTd, emptyTd2)
|
||||||
break
|
break
|
||||||
case 1:
|
case 1:
|
||||||
teamTr.append(emptyTd, reporterTd, reviewerTd, emptyTd2, opponentTd)
|
teamTr.append(emptyTd, defenderTd, reviewerTd, emptyTd2, opponentTd)
|
||||||
break
|
break
|
||||||
case 2:
|
case 2:
|
||||||
teamTr.append(opponentTd, emptyTd, reporterTd, emptyTd2, reviewerTd)
|
teamTr.append(opponentTd, emptyTd, defenderTd, emptyTd2, reviewerTd)
|
||||||
break
|
break
|
||||||
case 3:
|
case 3:
|
||||||
teamTr.append(reviewerTd, opponentTd, emptyTd, reporterTd, emptyTd2)
|
teamTr.append(reviewerTd, opponentTd, emptyTd, defenderTd, emptyTd2)
|
||||||
break
|
break
|
||||||
case 4:
|
case 4:
|
||||||
teamTr.append(emptyTd, reviewerTd, emptyTd2, opponentTd, reporterTd)
|
teamTr.append(emptyTd, reviewerTd, emptyTd2, opponentTd, defenderTd)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -662,7 +662,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
|
|
||||||
let penaltyDiv = document.getElementById(`recap-${tid}-round-${round}-team-${team}-penalty`)
|
let penaltyDiv = document.getElementById(`recap-${tid}-round-${round}-team-${team}-penalty`)
|
||||||
if (rejected.length > problems_count - RECOMMENDED_SOLUTIONS_COUNT) {
|
if (rejected.length > problems_count - RECOMMENDED_SOLUTIONS_COUNT) {
|
||||||
// If more than P - 5 problems were rejected, add a penalty of 25% of the coefficient of the oral reporter
|
// If more than P - 5 problems were rejected, add a penalty of 25% of the coefficient of the oral defender
|
||||||
// This is P - 6 for the ETEAM
|
// This is P - 6 for the ETEAM
|
||||||
if (penaltyDiv === null) {
|
if (penaltyDiv === null) {
|
||||||
penaltyDiv = document.createElement('div')
|
penaltyDiv = document.createElement('div')
|
||||||
|
@ -307,71 +307,71 @@
|
|||||||
<td class="text-center">{{ td.participation.team.trigram }}</td>
|
<td class="text-center">{{ td.participation.team.trigram }}</td>
|
||||||
{% if pool.size == 3 %}
|
{% if pool.size == 3 %}
|
||||||
{% if forloop.counter == 1 %}
|
{% if forloop.counter == 1 %}
|
||||||
<td class="text-center">{% trans "Rep" context "Role abbreviation" %}</td>
|
<td class="text-center">Déf</td>
|
||||||
<td class="text-center">{% trans "Rev" context "Role abbreviation" %}</td>
|
<td class="text-center">Rap</td>
|
||||||
<td class="text-center">{% trans "Opp" context "Role abbreviation" %}</td>
|
<td class="text-center">Opp</td>
|
||||||
{% elif forloop.counter == 2 %}
|
{% elif forloop.counter == 2 %}
|
||||||
<td class="text-center">{% trans "Opp" context "Role abbreviation" %}</td>
|
<td class="text-center">Opp</td>
|
||||||
<td class="text-center">{% trans "Rep" context "Role abbreviation" %}</td>
|
<td class="text-center">Déf</td>
|
||||||
<td class="text-center">{% trans "Rev" context "Role abbreviation" %}</td>
|
<td class="text-center">Rap</td>
|
||||||
{% elif forloop.counter == 3 %}
|
{% elif forloop.counter == 3 %}
|
||||||
<td class="text-center">{% trans "Rev" context "Role abbreviation" %}</td>
|
<td class="text-center">Rap</td>
|
||||||
<td class="text-center">{% trans "Opp" context "Role abbreviation" %}</td>
|
<td class="text-center">Opp</td>
|
||||||
<td class="text-center">{% trans "Rep" context "Role abbreviation" %}</td>
|
<td class="text-center">Déf</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% elif pool.size == 4 %}
|
{% elif pool.size == 4 %}
|
||||||
{% if forloop.counter == 1 %}
|
{% if forloop.counter == 1 %}
|
||||||
<td class="text-center">{% trans "Rep" context "Role abbreviation" %}</td>
|
<td class="text-center">Déf</td>
|
||||||
<td class="text-center">{% if TFJM.APP == "ETEAM" %}{% trans "Obs" context "Role abbreviation" %}{% endif %}</td>
|
<td></td>
|
||||||
<td class="text-center">{% trans "Rev" context "Role abbreviation" %}</td>
|
<td class="text-center">Rap</td>
|
||||||
<td class="text-center">{% trans "Opp" context "Role abbreviation" %}</td>
|
<td class="text-center">Opp</td>
|
||||||
{% elif forloop.counter == 2 %}
|
{% elif forloop.counter == 2 %}
|
||||||
<td class="text-center">{% trans "Opp" context "Role abbreviation" %}</td>
|
<td class="text-center">Opp</td>
|
||||||
<td class="text-center">{% trans "Rep" context "Role abbreviation" %}</td>
|
<td class="text-center">Déf</td>
|
||||||
<td class="text-center">{% if TFJM.APP == "ETEAM" %}{% trans "Obs" context "Role abbreviation" %}{% endif %}</td>
|
<td></td>
|
||||||
<td class="text-center">{% trans "Rev" context "Role abbreviation" %}</td>
|
<td class="text-center">Rap</td>
|
||||||
{% elif forloop.counter == 3 %}
|
{% elif forloop.counter == 3 %}
|
||||||
<td class="text-center">{% trans "Rev" context "Role abbreviation" %}</td>
|
<td class="text-center">Rap</td>
|
||||||
<td class="text-center">{% trans "Opp" context "Role abbreviation" %}</td>
|
<td class="text-center">Opp</td>
|
||||||
<td class="text-center">{% trans "Rep" context "Role abbreviation" %}</td>
|
<td class="text-center">Déf</td>
|
||||||
<td class="text-center">{% if TFJM.APP == "ETEAM" %}{% trans "Obs" context "Role abbreviation" %}{% endif %}</td>
|
<td></td>
|
||||||
{% elif forloop.counter == 4 %}
|
{% elif forloop.counter == 4 %}
|
||||||
<td class="text-center">{% if TFJM.APP == "ETEAM" %}{% trans "Obs" context "Role abbreviation" %}{% endif %}</td>
|
<td></td>
|
||||||
<td class="text-center">{% trans "Rev" context "Role abbreviation" %}</td>
|
<td class="text-center">Rap</td>
|
||||||
<td class="text-center">{% trans "Opp" context "Role abbreviation" %}</td>
|
<td class="text-center">Opp</td>
|
||||||
<td class="text-center">{% trans "Rep" context "Role abbreviation" %}</td>
|
<td class="text-center">Déf</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% elif pool.size == 5 %}
|
{% elif pool.size == 5 %}
|
||||||
{% if forloop.counter == 1 %}
|
{% if forloop.counter == 1 %}
|
||||||
<td class="text-center">{% trans "Rep" context "Role abbreviation" %}</td>
|
<td class="text-center">Déf</td>
|
||||||
<td class="text-center"></td>
|
<td></td>
|
||||||
<td class="text-center">{% trans "Rev" context "Role abbreviation" %}</td>
|
<td class="text-center">Rap</td>
|
||||||
<td class="text-center">{% trans "Opp" context "Role abbreviation" %}</td>
|
<td class="text-center">Opp</td>
|
||||||
<td class="text-center">{% if TFJM.APP == "ETEAM" %}{% trans "Obs" context "Role abbreviation" %}{% endif %}</td>
|
<td></td>
|
||||||
{% elif forloop.counter == 2 %}
|
{% elif forloop.counter == 2 %}
|
||||||
<td class="text-center">{% if TFJM.APP == "ETEAM" %}{% trans "Obs" context "Role abbreviation" %}{% endif %}</td>
|
<td></td>
|
||||||
<td class="text-center">{% trans "Rep" context "Role abbreviation" %}</td>
|
<td class="text-center">Déf</td>
|
||||||
<td class="text-center"></td>
|
<td></td>
|
||||||
<td class="text-center">{% trans "Rev" context "Role abbreviation" %}</td>
|
<td class="text-center">Rap</td>
|
||||||
<td class="text-center">{% trans "Opp" context "Role abbreviation" %}</td>
|
<td class="text-center">Opp</td>
|
||||||
{% elif forloop.counter == 3 %}
|
{% elif forloop.counter == 3 %}
|
||||||
<td class="text-center">{% trans "Opp" context "Role abbreviation" %}</td>
|
<td class="text-center">Opp</td>
|
||||||
<td class="text-center">{% if TFJM.APP == "ETEAM" %}{% trans "Obs" context "Role abbreviation" %}{% endif %}</td>
|
<td></td>
|
||||||
<td class="text-center">{% trans "Rep" context "Role abbreviation" %}</td>
|
<td class="text-center">Déf</td>
|
||||||
<td class="text-center"></td>
|
<td></td>
|
||||||
<td class="text-center">{% trans "Rev" context "Role abbreviation" %}</td>
|
<td class="text-center">Rap</td>
|
||||||
{% elif forloop.counter == 4 %}
|
{% elif forloop.counter == 4 %}
|
||||||
<td class="text-center">{% trans "Rev" context "Role abbreviation" %}</td>
|
<td class="text-center">Rap</td>
|
||||||
<td class="text-center">{% trans "Opp" context "Role abbreviation" %}</td>
|
<td class="text-center">Opp</td>
|
||||||
<td class="text-center">{% if TFJM.APP == "ETEAM" %}{% trans "Obs" context "Role abbreviation" %}{% endif %}</td>
|
<td></td>
|
||||||
<td class="text-center">{% trans "Rep" context "Role abbreviation" %}</td>
|
<td class="text-center">Déf</td>
|
||||||
<td class="text-center"></td>
|
<td></td>
|
||||||
{% elif forloop.counter == 5 %}
|
{% elif forloop.counter == 5 %}
|
||||||
<td class="text-center"></td>
|
<td></td>
|
||||||
<td class="text-center">{% trans "Rev" context "Role abbreviation" %}</td>
|
<td class="text-center">Rap</td>
|
||||||
<td class="text-center">{% trans "Opp" context "Role abbreviation" %}</td>
|
<td class="text-center">Opp</td>
|
||||||
<td class="text-center">{% if TFJM.APP == "ETEAM" %}{% trans "Obs" context "Role abbreviation" %}{% endif %}</td>
|
<td></td>
|
||||||
<td class="text-center">{% trans "Rep" context "Role abbreviation" %}</td>
|
<td class="text-center">Déf</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -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-06 22:07+0200\n"
|
"POT-Creation-Date: 2024-07-06 10:16+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"
|
||||||
@ -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
|
#: 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:27 participation/admin.py:79 participation/admin.py:144
|
||||||
#: participation/admin.py:176 participation/models.py:783
|
#: participation/admin.py:176 participation/models.py:783
|
||||||
#: participation/models.py:807 participation/models.py:1131
|
#: participation/models.py:807 participation/models.py:1116
|
||||||
#: 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"
|
||||||
@ -95,7 +95,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: chat/models.py:73 draw/models.py:446 draw/models.py:473
|
#: chat/models.py:73 draw/models.py:446 draw/models.py:473
|
||||||
#: participation/admin.py:140 participation/admin.py:160
|
#: participation/admin.py:140 participation/admin.py:160
|
||||||
#: participation/models.py:1666 participation/models.py:1675
|
#: participation/models.py:1651 participation/models.py:1660
|
||||||
#: participation/tables.py:84
|
#: participation/tables.py:84
|
||||||
msgid "pool"
|
msgid "pool"
|
||||||
msgstr "poule"
|
msgstr "poule"
|
||||||
@ -265,7 +265,7 @@ 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:245 draw/models.py:465
|
||||||
#: participation/models.py:1135
|
#: participation/models.py:1120
|
||||||
msgid "round"
|
msgid "round"
|
||||||
msgstr "tour"
|
msgstr "tour"
|
||||||
|
|
||||||
@ -634,7 +634,7 @@ msgstr "Le numéro du tour doit être entre 1 et {nb}."
|
|||||||
msgid "rounds"
|
msgid "rounds"
|
||||||
msgstr "tours"
|
msgstr "tours"
|
||||||
|
|
||||||
#: draw/models.py:268 participation/models.py:1143
|
#: draw/models.py:268 participation/models.py:1128
|
||||||
msgid "letter"
|
msgid "letter"
|
||||||
msgstr "lettre"
|
msgstr "lettre"
|
||||||
|
|
||||||
@ -672,12 +672,12 @@ msgstr "L'instance complète de la poule."
|
|||||||
msgid "Pool {letter}{number}"
|
msgid "Pool {letter}{number}"
|
||||||
msgstr "Poule {letter}{number}"
|
msgstr "Poule {letter}{number}"
|
||||||
|
|
||||||
#: draw/models.py:447 participation/models.py:1667
|
#: draw/models.py:447 participation/models.py:1652
|
||||||
msgid "pools"
|
msgid "pools"
|
||||||
msgstr "poules"
|
msgstr "poules"
|
||||||
|
|
||||||
#: draw/models.py:459 participation/models.py:1121 participation/models.py:1886
|
#: draw/models.py:459 participation/models.py:1106 participation/models.py:1871
|
||||||
#: participation/models.py:1920 participation/models.py:1962
|
#: participation/models.py:1901 participation/models.py:1943
|
||||||
msgid "participation"
|
msgid "participation"
|
||||||
msgstr "participation"
|
msgstr "participation"
|
||||||
|
|
||||||
@ -701,9 +701,9 @@ msgid ""
|
|||||||
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:1252
|
#: draw/models.py:496 draw/models.py:519 participation/models.py:1237
|
||||||
#: participation/models.py:1689 participation/models.py:1927
|
#: participation/models.py:1674 participation/models.py:1908
|
||||||
#: participation/views.py:1492 participation/views.py:1757
|
#: participation/views.py:1489 participation/views.py:1754
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Problem #{problem}"
|
msgid "Problem #{problem}"
|
||||||
msgstr "Problème n°{problem}"
|
msgstr "Problème n°{problem}"
|
||||||
@ -814,67 +814,6 @@ msgstr "Pb."
|
|||||||
msgid "Room"
|
msgid "Room"
|
||||||
msgstr "Salle"
|
msgstr "Salle"
|
||||||
|
|
||||||
#: draw/templates/draw/tournament_content.html:310
|
|
||||||
#: draw/templates/draw/tournament_content.html:315
|
|
||||||
#: draw/templates/draw/tournament_content.html:320
|
|
||||||
#: draw/templates/draw/tournament_content.html:324
|
|
||||||
#: draw/templates/draw/tournament_content.html:330
|
|
||||||
#: draw/templates/draw/tournament_content.html:336
|
|
||||||
#: draw/templates/draw/tournament_content.html:342
|
|
||||||
#: draw/templates/draw/tournament_content.html:346
|
|
||||||
#: draw/templates/draw/tournament_content.html:353
|
|
||||||
#: draw/templates/draw/tournament_content.html:360
|
|
||||||
#: draw/templates/draw/tournament_content.html:367
|
|
||||||
#: draw/templates/draw/tournament_content.html:374
|
|
||||||
msgctxt "Role abbreviation"
|
|
||||||
msgid "Rep"
|
|
||||||
msgstr "Déf"
|
|
||||||
|
|
||||||
#: draw/templates/draw/tournament_content.html:311
|
|
||||||
#: draw/templates/draw/tournament_content.html:316
|
|
||||||
#: draw/templates/draw/tournament_content.html:318
|
|
||||||
#: draw/templates/draw/tournament_content.html:326
|
|
||||||
#: draw/templates/draw/tournament_content.html:332
|
|
||||||
#: draw/templates/draw/tournament_content.html:334
|
|
||||||
#: draw/templates/draw/tournament_content.html:340
|
|
||||||
#: draw/templates/draw/tournament_content.html:348
|
|
||||||
#: draw/templates/draw/tournament_content.html:355
|
|
||||||
#: draw/templates/draw/tournament_content.html:362
|
|
||||||
#: draw/templates/draw/tournament_content.html:364
|
|
||||||
#: draw/templates/draw/tournament_content.html:371
|
|
||||||
msgctxt "Role abbreviation"
|
|
||||||
msgid "Rev"
|
|
||||||
msgstr "Rap"
|
|
||||||
|
|
||||||
#: draw/templates/draw/tournament_content.html:312
|
|
||||||
#: draw/templates/draw/tournament_content.html:314
|
|
||||||
#: draw/templates/draw/tournament_content.html:319
|
|
||||||
#: draw/templates/draw/tournament_content.html:327
|
|
||||||
#: draw/templates/draw/tournament_content.html:329
|
|
||||||
#: draw/templates/draw/tournament_content.html:335
|
|
||||||
#: draw/templates/draw/tournament_content.html:341
|
|
||||||
#: draw/templates/draw/tournament_content.html:349
|
|
||||||
#: draw/templates/draw/tournament_content.html:356
|
|
||||||
#: draw/templates/draw/tournament_content.html:358
|
|
||||||
#: draw/templates/draw/tournament_content.html:365
|
|
||||||
#: draw/templates/draw/tournament_content.html:372
|
|
||||||
msgctxt "Role abbreviation"
|
|
||||||
msgid "Opp"
|
|
||||||
msgstr "Opp"
|
|
||||||
|
|
||||||
#: draw/templates/draw/tournament_content.html:325
|
|
||||||
#: draw/templates/draw/tournament_content.html:331
|
|
||||||
#: draw/templates/draw/tournament_content.html:337
|
|
||||||
#: draw/templates/draw/tournament_content.html:339
|
|
||||||
#: draw/templates/draw/tournament_content.html:350
|
|
||||||
#: draw/templates/draw/tournament_content.html:352
|
|
||||||
#: draw/templates/draw/tournament_content.html:359
|
|
||||||
#: draw/templates/draw/tournament_content.html:366
|
|
||||||
#: draw/templates/draw/tournament_content.html:373
|
|
||||||
msgctxt "Role abbreviation"
|
|
||||||
msgid "Obs"
|
|
||||||
msgstr "Obs"
|
|
||||||
|
|
||||||
#: draw/templates/draw/tournament_content.html:395
|
#: draw/templates/draw/tournament_content.html:395
|
||||||
#: draw/templates/draw/tournament_content.html:414
|
#: draw/templates/draw/tournament_content.html:414
|
||||||
msgid "Abort"
|
msgid "Abort"
|
||||||
@ -980,26 +919,26 @@ 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:188
|
||||||
#: participation/models.py:1696 participation/tables.py:114
|
#: participation/models.py:1681 participation/tables.py:114
|
||||||
msgid "reporter"
|
msgid "defender"
|
||||||
msgstr "défenseur⋅se"
|
msgstr "défenseur⋅se"
|
||||||
|
|
||||||
#: participation/admin.py:128 participation/models.py:1703
|
#: participation/admin.py:128 participation/models.py:1688
|
||||||
#: participation/models.py:1974
|
#: participation/models.py:1955
|
||||||
msgid "opponent"
|
msgid "opponent"
|
||||||
msgstr "opposant⋅e"
|
msgstr "opposant⋅e"
|
||||||
|
|
||||||
#: participation/admin.py:132 participation/models.py:1710
|
#: participation/admin.py:132 participation/models.py:1695
|
||||||
#: participation/models.py:1975
|
#: participation/models.py:1956
|
||||||
msgid "reviewer"
|
msgid "reviewer"
|
||||||
msgstr "rapporteur⋅rice"
|
msgstr "rapporteur⋅rice"
|
||||||
|
|
||||||
#: participation/admin.py:136 participation/models.py:1717
|
#: participation/admin.py:136 participation/models.py:1702
|
||||||
#: participation/models.py:1976
|
#: participation/models.py:1957
|
||||||
msgid "observer"
|
msgid "observer"
|
||||||
msgstr "observateur⋅rice"
|
msgstr "observateur⋅rice"
|
||||||
|
|
||||||
#: participation/admin.py:192 participation/models.py:1925
|
#: participation/admin.py:192 participation/models.py:1906
|
||||||
msgid "problem"
|
msgid "problem"
|
||||||
msgstr "numéro de problème"
|
msgstr "numéro de problème"
|
||||||
|
|
||||||
@ -1088,12 +1027,12 @@ msgid "The following user was not found:"
|
|||||||
msgstr "L'utilisateur⋅rice suivant n'a pas été trouvé :"
|
msgstr "L'utilisateur⋅rice suivant n'a pas été trouvé :"
|
||||||
|
|
||||||
#: participation/forms.py:350
|
#: participation/forms.py:350
|
||||||
msgid "The reporter, the opponent and the reviewer must be different."
|
msgid "The defender, the opponent and the reviewer must be different."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Les équipes défenseuse, opposante et rapportrice doivent être différent⋅es."
|
"Les équipes défenseuse, opposante et rapportrice doivent être différent⋅es."
|
||||||
|
|
||||||
#: participation/forms.py:354
|
#: participation/forms.py:354
|
||||||
msgid "This reporter did not work on this problem."
|
msgid "This defender did not work on this problem."
|
||||||
msgstr "Ce⋅tte défenseur⋅se ne travaille pas sur ce problème."
|
msgstr "Ce⋅tte défenseur⋅se ne travaille pas sur ce problème."
|
||||||
|
|
||||||
#: participation/forms.py:373
|
#: participation/forms.py:373
|
||||||
@ -1300,7 +1239,7 @@ msgid "first phase date"
|
|||||||
msgstr "date du premier tour"
|
msgstr "date du premier tour"
|
||||||
|
|
||||||
#: participation/models.py:327
|
#: participation/models.py:327
|
||||||
msgid "limit date to upload the written reviews for the first phase"
|
msgid "limit date to upload the syntheses for the first phase"
|
||||||
msgstr "date limite pour envoyer les notes de synthèses pour la première phase"
|
msgstr "date limite pour envoyer les notes de synthèses pour la première phase"
|
||||||
|
|
||||||
#: participation/models.py:332
|
#: participation/models.py:332
|
||||||
@ -1313,7 +1252,7 @@ msgstr ""
|
|||||||
"cocher la case lorsque les solutions pour le second tour sont accessibles"
|
"cocher la case lorsque les solutions pour le second tour sont accessibles"
|
||||||
|
|
||||||
#: participation/models.py:342
|
#: participation/models.py:342
|
||||||
msgid "limit date to upload the written reviews for the second phase"
|
msgid "limit date to upload the syntheses for the second phase"
|
||||||
msgstr "date limite d'envoi des notes de synthèse pour la seconde phase"
|
msgstr "date limite d'envoi des notes de synthèse pour la seconde phase"
|
||||||
|
|
||||||
#: participation/models.py:347
|
#: participation/models.py:347
|
||||||
@ -1326,7 +1265,7 @@ msgstr ""
|
|||||||
"cocher la case lorsque les solutions pour le second tour sont accessibles"
|
"cocher la case lorsque les solutions pour le second tour sont accessibles"
|
||||||
|
|
||||||
#: participation/models.py:357
|
#: participation/models.py:357
|
||||||
msgid "limit date to upload the written reviews for the third phase"
|
msgid "limit date to upload the syntheses for the third phase"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"date limite pour envoyer les notes de synthèses pour la troisième phase"
|
"date limite pour envoyer les notes de synthèses pour la troisième phase"
|
||||||
|
|
||||||
@ -1355,7 +1294,7 @@ msgid "Final ranking"
|
|||||||
msgstr "Classement final"
|
msgstr "Classement final"
|
||||||
|
|
||||||
#: participation/models.py:481 participation/models.py:553
|
#: participation/models.py:481 participation/models.py:553
|
||||||
#: participation/models.py:1327 participation/views.py:1731
|
#: participation/models.py:1312 participation/views.py:1728
|
||||||
msgid "Team"
|
msgid "Team"
|
||||||
msgstr "Équipe"
|
msgstr "Équipe"
|
||||||
|
|
||||||
@ -1387,15 +1326,15 @@ msgstr "Scores jour 3"
|
|||||||
msgid "Tweaks day 3"
|
msgid "Tweaks day 3"
|
||||||
msgstr "Ajustements 3"
|
msgstr "Ajustements 3"
|
||||||
|
|
||||||
#: participation/models.py:485 participation/models.py:1327
|
#: participation/models.py:485 participation/models.py:1312
|
||||||
#: participation/views.py:1738
|
#: participation/views.py:1735
|
||||||
msgid "Total"
|
msgid "Total"
|
||||||
msgstr "Total"
|
msgstr "Total"
|
||||||
|
|
||||||
#: participation/models.py:485 participation/models.py:553
|
#: participation/models.py:485 participation/models.py:553
|
||||||
#: participation/models.py:1327
|
#: participation/models.py:1312
|
||||||
#: participation/templates/participation/tournament_harmonize.html:14
|
#: participation/templates/participation/tournament_harmonize.html:14
|
||||||
#: participation/views.py:1741
|
#: participation/views.py:1738
|
||||||
msgid "Rank"
|
msgid "Rank"
|
||||||
msgstr "Rang"
|
msgstr "Rang"
|
||||||
|
|
||||||
@ -1407,7 +1346,7 @@ msgstr "Score"
|
|||||||
msgid "Mention"
|
msgid "Mention"
|
||||||
msgstr "Mention"
|
msgstr "Mention"
|
||||||
|
|
||||||
#: participation/models.py:698 participation/models.py:1596
|
#: participation/models.py:698 participation/models.py:1581
|
||||||
msgid "Don't update the table structure for a better automated integration."
|
msgid "Don't update the table structure for a better automated integration."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Ne pas mettre à jour la structure de la table pour une meilleure intégration "
|
"Ne pas mettre à jour la structure de la table pour une meilleure intégration "
|
||||||
@ -1509,7 +1448,7 @@ msgstr "Tirage au sort des solutions"
|
|||||||
#, 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 "
|
||||||
"href='{draw_url}'>this page</a>.</p><p>For the first round, you will present "
|
"href='{draw_url}'>this page</a>.</p><p>For the first 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>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"<p>Le tirage au sort des solutions est terminé. Vous pouvez consulter les "
|
"<p>Le tirage au sort des solutions est terminé. Vous pouvez consulter les "
|
||||||
@ -1517,70 +1456,70 @@ 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:930 participation/models.py:993
|
#: participation/models.py:930 participation/models.py:988
|
||||||
#: participation/models.py:1057
|
#: participation/models.py:1047
|
||||||
#, 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 "
|
||||||
"href='{solution_url}'>problem {problem}</a>. You can upload your written "
|
"href='{solution_url}'>problem {problem}</a>. You can upload your synthesis "
|
||||||
"review on <a href='{passage_url}'>this page</a>.</p>"
|
"sheet on <a href='{passage_url}'>this page</a>.</p>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"<p>Vous opposerez la solution de l'équipe {opponent} sur le <a "
|
"<p>Vous opposerez la solution de l'équipe {opponent} sur le <a "
|
||||||
"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:939 participation/models.py:1002
|
#: participation/models.py:939 participation/models.py:997
|
||||||
#: participation/models.py:1066
|
#: participation/models.py:1056
|
||||||
#, 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 "
|
||||||
"href='{solution_url}'>problem {problem}</a>. You can upload your written "
|
"href='{solution_url}'>problem {problem}. You can upload your synthesis sheet "
|
||||||
"review on <a href='{passage_url}'>this page</a>.</p>"
|
"on <a href='{passage_url}'>this page</a>.</p>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"<p>Vous rapporterez la solution de l'équipe {reviewer} sur le <a "
|
"<p>Vous rapporterez la solution de l'équipe {reviewer} sur le <a "
|
||||||
"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:949 participation/models.py:1012
|
#: participation/models.py:949 participation/models.py:1007
|
||||||
#: participation/models.py:1076
|
#: participation/models.py:1066
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"<p>You will observe the solution of the team {observer} on the <a "
|
"<p>You will observe the solution of the team {observer} on the <a "
|
||||||
"href='{solution_url}'>problem {problem}</a>. You can upload your written "
|
"href='{solution_url}'>problem {problem}. You can upload your synthesis sheet "
|
||||||
"review on <a href='{passage_url}'>this page</a>.</p>"
|
"on <a href='{passage_url}'>this page</a>.</p>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"<p>Vous observerez la solution de l'équipe {observer} sur le <a "
|
"<p>Vous observerez la solution de l'équipe {observer} sur le <a "
|
||||||
"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:974 registration/models.py:629
|
#: participation/models.py:969 registration/models.py:629
|
||||||
msgid "First round"
|
msgid "First round"
|
||||||
msgstr "Premier tour"
|
msgstr "Premier tour"
|
||||||
|
|
||||||
#: participation/models.py:986
|
#: participation/models.py:981
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"<p>For the second round, you will present <a href='{solution_url}'>your "
|
"<p>For the second round, you will defend <a href='{solution_url}'>your "
|
||||||
"solution of the problem {problem}</a>.</p>"
|
"solution of the problem {problem}</a>.</p>"
|
||||||
msgstr ""
|
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:1037 participation/models.py:1101
|
#: participation/models.py:1027 participation/models.py:1086
|
||||||
#: registration/models.py:640
|
#: registration/models.py:640
|
||||||
msgid "Second round"
|
msgid "Second round"
|
||||||
msgstr "Second tour"
|
msgstr "Second tour"
|
||||||
|
|
||||||
#: participation/models.py:1050
|
#: participation/models.py:1040
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"<p>For the third round, you will present <a href='{solution_url}'>your "
|
"<p>For the third round, you will defend <a href='{solution_url}'>your "
|
||||||
"solution of the problem {problem}</a>.</p>"
|
"solution of the problem {problem}</a>.</p>"
|
||||||
msgstr ""
|
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:1107
|
#: participation/models.py:1092
|
||||||
#, 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 "
|
||||||
@ -1589,57 +1528,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:1112
|
#: participation/models.py:1097
|
||||||
msgid "Tournament ended"
|
msgid "Tournament ended"
|
||||||
msgstr "Tournoi terminé"
|
msgstr "Tournoi terminé"
|
||||||
|
|
||||||
#: participation/models.py:1122 participation/models.py:1165
|
#: participation/models.py:1107 participation/models.py:1150
|
||||||
msgid "participations"
|
msgid "participations"
|
||||||
msgstr "participations"
|
msgstr "participations"
|
||||||
|
|
||||||
#: participation/models.py:1137 participation/models.py:1138
|
#: participation/models.py:1122 participation/models.py:1123
|
||||||
#: participation/models.py:1139
|
#: participation/models.py:1124
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Round {round}"
|
msgid "Round {round}"
|
||||||
msgstr "Tour {round}"
|
msgstr "Tour {round}"
|
||||||
|
|
||||||
#: participation/models.py:1153
|
#: participation/models.py:1138
|
||||||
msgid "room"
|
msgid "room"
|
||||||
msgstr "salle"
|
msgstr "salle"
|
||||||
|
|
||||||
#: participation/models.py:1155
|
#: participation/models.py:1140
|
||||||
msgid "Room 1"
|
msgid "Room 1"
|
||||||
msgstr "Salle 1"
|
msgstr "Salle 1"
|
||||||
|
|
||||||
#: participation/models.py:1156
|
#: participation/models.py:1141
|
||||||
msgid "Room 2"
|
msgid "Room 2"
|
||||||
msgstr "Salle 2"
|
msgstr "Salle 2"
|
||||||
|
|
||||||
#: participation/models.py:1159
|
#: participation/models.py:1144
|
||||||
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:1171
|
#: participation/models.py:1156
|
||||||
msgid "juries"
|
msgid "juries"
|
||||||
msgstr "jurys"
|
msgstr "jurys"
|
||||||
|
|
||||||
#: participation/models.py:1180
|
#: participation/models.py:1165
|
||||||
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:1187
|
#: participation/models.py:1172
|
||||||
msgid "BigBlueButton URL"
|
msgid "BigBlueButton URL"
|
||||||
msgstr "Lien BigBlueButton"
|
msgstr "Lien BigBlueButton"
|
||||||
|
|
||||||
#: participation/models.py:1188
|
#: participation/models.py:1173
|
||||||
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:1193
|
#: participation/models.py:1178
|
||||||
msgid "results available"
|
msgid "results available"
|
||||||
msgstr "résultats disponibles"
|
msgstr "résultats disponibles"
|
||||||
|
|
||||||
#: participation/models.py:1194
|
#: participation/models.py:1179
|
||||||
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."
|
||||||
@ -1648,194 +1587,194 @@ 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:1226
|
#: participation/models.py:1211
|
||||||
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:1253 participation/models.py:1327
|
#: participation/models.py:1238 participation/models.py:1312
|
||||||
#: participation/views.py:1486 participation/views.py:1735
|
#: participation/views.py:1483 participation/views.py:1732
|
||||||
msgid "Problem"
|
msgid "Problem"
|
||||||
msgstr "Problème"
|
msgstr "Problème"
|
||||||
|
|
||||||
#: participation/models.py:1258 participation/views.py:1501
|
#: participation/models.py:1243 participation/views.py:1498
|
||||||
msgid "Role"
|
msgid "Role"
|
||||||
msgstr "Rôle"
|
msgstr "Rôle"
|
||||||
|
|
||||||
#: participation/models.py:1263 participation/views.py:1535
|
#: participation/models.py:1248 participation/views.py:1532
|
||||||
#: participation/views.py:1536
|
#: participation/views.py:1533
|
||||||
msgid "Juree"
|
msgid "Juree"
|
||||||
msgstr "Juré⋅e"
|
msgstr "Juré⋅e"
|
||||||
|
|
||||||
#: participation/models.py:1286 participation/models.py:1612
|
#: participation/models.py:1271 participation/models.py:1597
|
||||||
#: participation/models.py:1634 participation/views.py:1605
|
#: participation/models.py:1619 participation/views.py:1602
|
||||||
msgid "Average"
|
msgid "Average"
|
||||||
msgstr "Moyenne"
|
msgstr "Moyenne"
|
||||||
|
|
||||||
#: participation/models.py:1292 participation/views.py:1624
|
#: participation/models.py:1277 participation/views.py:1621
|
||||||
msgid "Coefficient"
|
msgid "Coefficient"
|
||||||
msgstr "Coefficien"
|
msgstr "Coefficien"
|
||||||
|
|
||||||
#: participation/models.py:1293 participation/views.py:1667
|
#: participation/models.py:1278 participation/views.py:1664
|
||||||
msgid "Subtotal"
|
msgid "Subtotal"
|
||||||
msgstr "Sous-total"
|
msgstr "Sous-total"
|
||||||
|
|
||||||
#: participation/models.py:1559
|
#: participation/models.py:1544
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Input must be a valid integer between {min_note} and {max_note}."
|
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}."
|
msgstr "L'entrée doit être un entier valide entre {min_note} et {max_note}."
|
||||||
|
|
||||||
#: participation/models.py:1647
|
#: participation/models.py:1632
|
||||||
#, 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:1660
|
#: participation/models.py:1645
|
||||||
#, 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:1680
|
#: participation/models.py:1665
|
||||||
msgid "position"
|
msgid "position"
|
||||||
msgstr "position"
|
msgstr "position"
|
||||||
|
|
||||||
#: participation/models.py:1687
|
#: participation/models.py:1672
|
||||||
msgid "reported solution"
|
msgid "defended solution"
|
||||||
msgstr "solution défendue"
|
msgstr "solution défendue"
|
||||||
|
|
||||||
#: participation/models.py:1725
|
#: participation/models.py:1710
|
||||||
msgid "penalties"
|
msgid "penalties"
|
||||||
msgstr "pénalités"
|
msgstr "pénalités"
|
||||||
|
|
||||||
#: participation/models.py:1727
|
#: participation/models.py:1712
|
||||||
msgid ""
|
msgid ""
|
||||||
"Number of penalties for the reporter. The reporter will loose a 0.5 "
|
"Number of penalties for the defender. The defender will loose a 0.5 "
|
||||||
"coefficient per penalty."
|
"coefficient per penalty."
|
||||||
msgstr ""
|
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:1853 participation/models.py:1856
|
#: participation/models.py:1838 participation/models.py:1841
|
||||||
#: participation/models.py:1859 participation/models.py:1862
|
#: participation/models.py:1844 participation/models.py:1847
|
||||||
#, 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:1867
|
#: participation/models.py:1852
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Passage of {reporter} for problem {problem}"
|
msgid "Passage of {defender} for problem {problem}"
|
||||||
msgstr "Passage de {reporter} pour le problème {problem}"
|
msgstr "Passage de {defender} pour le problème {problem}"
|
||||||
|
|
||||||
#: participation/models.py:1871 participation/models.py:1880
|
#: participation/models.py:1856 participation/models.py:1865
|
||||||
#: participation/models.py:1969 participation/models.py:2012
|
#: participation/models.py:1950 participation/models.py:1993
|
||||||
msgid "passage"
|
msgid "passage"
|
||||||
msgstr "passage"
|
msgstr "passage"
|
||||||
|
|
||||||
#: participation/models.py:1872
|
#: participation/models.py:1857
|
||||||
msgid "passages"
|
msgid "passages"
|
||||||
msgstr "passages"
|
msgstr "passages"
|
||||||
|
|
||||||
#: participation/models.py:1891
|
#: participation/models.py:1876
|
||||||
msgid "difference"
|
msgid "difference"
|
||||||
msgstr "différence"
|
msgstr "différence"
|
||||||
|
|
||||||
#: participation/models.py:1892
|
#: participation/models.py:1877
|
||||||
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:1899
|
#: participation/models.py:1884
|
||||||
msgid "tweak"
|
msgid "tweak"
|
||||||
msgstr "harmonisation"
|
msgstr "harmonisation"
|
||||||
|
|
||||||
#: participation/models.py:1900
|
#: participation/models.py:1885
|
||||||
msgid "tweaks"
|
msgid "tweaks"
|
||||||
msgstr "harmonisations"
|
msgstr "harmonisations"
|
||||||
|
|
||||||
#: participation/models.py:1932
|
#: participation/models.py:1913
|
||||||
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:1937 participation/models.py:1981
|
#: participation/models.py:1918 participation/models.py:1962
|
||||||
msgid "file"
|
msgid "file"
|
||||||
msgstr "fichier"
|
msgstr "fichier"
|
||||||
|
|
||||||
#: participation/models.py:1947
|
#: participation/models.py:1928
|
||||||
#, 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:1949
|
#: participation/models.py:1930
|
||||||
msgid "for final"
|
msgid "for final"
|
||||||
msgstr "pour la finale"
|
msgstr "pour la finale"
|
||||||
|
|
||||||
#: participation/models.py:1952
|
#: participation/models.py:1933
|
||||||
msgid "solution"
|
msgid "solution"
|
||||||
msgstr "solution"
|
msgstr "solution"
|
||||||
|
|
||||||
#: participation/models.py:1953
|
#: participation/models.py:1934
|
||||||
msgid "solutions"
|
msgid "solutions"
|
||||||
msgstr "solutions"
|
msgstr "solutions"
|
||||||
|
|
||||||
#: participation/models.py:1987
|
#: participation/models.py:1968
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Written review of {team} as {type} for problem {problem} of {reporter}"
|
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 {reporter}"
|
"{problem} de {defender}"
|
||||||
|
|
||||||
#: participation/models.py:1995
|
#: participation/models.py:1976
|
||||||
msgid "written review"
|
msgid "synthesis"
|
||||||
msgstr "note de synthèse"
|
msgstr "note de synthèse"
|
||||||
|
|
||||||
#: participation/models.py:1996
|
#: participation/models.py:1977
|
||||||
msgid "written reviews"
|
msgid "syntheses"
|
||||||
msgstr "notes de synthèse"
|
msgstr "notes de synthèse"
|
||||||
|
|
||||||
#: participation/models.py:2005
|
#: participation/models.py:1986
|
||||||
msgid "jury"
|
msgid "jury"
|
||||||
msgstr "jury"
|
msgstr "jury"
|
||||||
|
|
||||||
#: participation/models.py:2017
|
#: participation/models.py:1998
|
||||||
msgid "reporter writing note"
|
msgid "defender writing note"
|
||||||
msgstr "note d'écrit défenseur⋅se"
|
msgstr "note d'écrit défenseur⋅se"
|
||||||
|
|
||||||
#: participation/models.py:2023
|
#: participation/models.py:2004
|
||||||
msgid "reporter oral note"
|
msgid "defender oral note"
|
||||||
msgstr "note d'oral défenseur⋅se"
|
msgstr "note d'oral défenseur⋅se"
|
||||||
|
|
||||||
#: participation/models.py:2029
|
#: participation/models.py:2010
|
||||||
msgid "opponent writing note"
|
msgid "opponent writing note"
|
||||||
msgstr "note d'écrit opposant⋅e"
|
msgstr "note d'écrit opposant⋅e"
|
||||||
|
|
||||||
#: participation/models.py:2035
|
#: participation/models.py:2016
|
||||||
msgid "opponent oral note"
|
msgid "opponent oral note"
|
||||||
msgstr "note d'oral opposant⋅e"
|
msgstr "note d'oral opposant⋅e"
|
||||||
|
|
||||||
#: participation/models.py:2041
|
#: participation/models.py:2022
|
||||||
msgid "reviewer writing note"
|
msgid "reviewer writing note"
|
||||||
msgstr "note d'écrit rapporteur⋅rice"
|
msgstr "note d'écrit rapporteur⋅rice"
|
||||||
|
|
||||||
#: participation/models.py:2047
|
#: participation/models.py:2028
|
||||||
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:2053
|
#: participation/models.py:2034
|
||||||
msgid "observer writing note"
|
msgid "observer writing note"
|
||||||
msgstr "note d'écrit de l'observateur⋅rice"
|
msgstr "note d'écrit de l'observateur⋅rice"
|
||||||
|
|
||||||
#: participation/models.py:2059
|
#: participation/models.py:2040
|
||||||
msgid "observer oral note"
|
msgid "observer oral note"
|
||||||
msgstr "note d'oral de l'observateur⋅rice"
|
msgstr "note d'oral de l'observateur⋅rice"
|
||||||
|
|
||||||
#: participation/models.py:2124
|
#: participation/models.py:2105
|
||||||
#, 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:2127
|
#: participation/models.py:2108
|
||||||
msgid "note"
|
msgid "note"
|
||||||
msgstr "note"
|
msgstr "note"
|
||||||
|
|
||||||
#: participation/models.py:2128
|
#: participation/models.py:2109
|
||||||
msgid "notes"
|
msgid "notes"
|
||||||
msgstr "notes"
|
msgstr "notes"
|
||||||
|
|
||||||
@ -1971,7 +1910,7 @@ msgstr "Envoyer une solution"
|
|||||||
#: participation/templates/participation/upload_motivation_letter.html:13
|
#: participation/templates/participation/upload_motivation_letter.html:13
|
||||||
#: participation/templates/participation/upload_notes.html:24
|
#: participation/templates/participation/upload_notes.html:24
|
||||||
#: participation/templates/participation/upload_solution.html:11
|
#: participation/templates/participation/upload_solution.html:11
|
||||||
#: participation/templates/participation/upload_written_review.html:23
|
#: participation/templates/participation/upload_synthesis.html:18
|
||||||
#: registration/templates/registration/upload_health_sheet.html:17
|
#: registration/templates/registration/upload_health_sheet.html:17
|
||||||
#: registration/templates/registration/upload_parental_authorization.html:17
|
#: registration/templates/registration/upload_parental_authorization.html:17
|
||||||
#: registration/templates/registration/upload_photo_authorization.html:18
|
#: registration/templates/registration/upload_photo_authorization.html:18
|
||||||
@ -1994,7 +1933,7 @@ msgid "Position:"
|
|||||||
msgstr "Position :"
|
msgstr "Position :"
|
||||||
|
|
||||||
#: participation/templates/participation/passage_detail.html:28
|
#: participation/templates/participation/passage_detail.html:28
|
||||||
msgid "Reporter:"
|
msgid "Defender:"
|
||||||
msgstr "Défenseur⋅se :"
|
msgstr "Défenseur⋅se :"
|
||||||
|
|
||||||
#: participation/templates/participation/passage_detail.html:31
|
#: participation/templates/participation/passage_detail.html:31
|
||||||
@ -2010,11 +1949,11 @@ msgid "Observer:"
|
|||||||
msgstr "Observateur⋅rice :"
|
msgstr "Observateur⋅rice :"
|
||||||
|
|
||||||
#: participation/templates/participation/passage_detail.html:42
|
#: participation/templates/participation/passage_detail.html:42
|
||||||
msgid "Reported 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:45
|
||||||
msgid "Reporter 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:48
|
||||||
@ -2024,7 +1963,7 @@ msgstr "Notes de synthèse :"
|
|||||||
|
|
||||||
#: participation/templates/participation/passage_detail.html:53
|
#: participation/templates/participation/passage_detail.html:53
|
||||||
#: participation/templates/participation/pool_detail.html:68
|
#: participation/templates/participation/pool_detail.html:68
|
||||||
msgid "No review 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:61
|
||||||
@ -2034,19 +1973,19 @@ msgstr "Modifier les notes"
|
|||||||
|
|
||||||
#: participation/templates/participation/passage_detail.html:66
|
#: participation/templates/participation/passage_detail.html:66
|
||||||
#: participation/templates/participation/passage_detail.html:187
|
#: participation/templates/participation/passage_detail.html:187
|
||||||
msgid "Upload review"
|
msgid "Upload synthesis"
|
||||||
msgstr "Envoyer la note de synthèse"
|
msgstr "Envoyer une note de synthèse"
|
||||||
|
|
||||||
#: participation/templates/participation/passage_detail.html:74
|
#: participation/templates/participation/passage_detail.html:74
|
||||||
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:82
|
||||||
msgid "Average points for the reporter 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:90
|
#: participation/templates/participation/passage_detail.html:90
|
||||||
msgid "Average points for the reporter 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:98
|
#: participation/templates/participation/passage_detail.html:98
|
||||||
@ -2074,7 +2013,7 @@ msgid "Average points for the observer oral"
|
|||||||
msgstr "Moyenne de l'oral de l'équipe observatrice"
|
msgstr "Moyenne de l'oral de l'équipe observatrice"
|
||||||
|
|
||||||
#: participation/templates/participation/passage_detail.html:140
|
#: participation/templates/participation/passage_detail.html:140
|
||||||
msgid "Reporter points"
|
msgid "Defender points"
|
||||||
msgstr "Points de l'équipe défenseuse"
|
msgstr "Points de l'équipe défenseuse"
|
||||||
|
|
||||||
#: participation/templates/participation/passage_detail.html:148
|
#: participation/templates/participation/passage_detail.html:148
|
||||||
@ -2119,7 +2058,7 @@ msgid "Edit jury"
|
|||||||
msgstr "Modifier le jury"
|
msgstr "Modifier le jury"
|
||||||
|
|
||||||
#: participation/templates/participation/pool_detail.html:49
|
#: participation/templates/participation/pool_detail.html:49
|
||||||
msgid "Reported solutions:"
|
msgid "Defended solutions:"
|
||||||
msgstr "Solutions défendues :"
|
msgstr "Solutions défendues :"
|
||||||
|
|
||||||
#: participation/templates/participation/pool_detail.html:55
|
#: participation/templates/participation/pool_detail.html:55
|
||||||
@ -2435,15 +2374,15 @@ msgid "date of the random draw"
|
|||||||
msgstr "date du tirage au sort"
|
msgstr "date du tirage au sort"
|
||||||
|
|
||||||
#: participation/templates/participation/tournament_detail.html:41
|
#: participation/templates/participation/tournament_detail.html:41
|
||||||
msgid "date of maximal written reviews submission for the first round"
|
msgid "date of maximal syntheses submission for the first round"
|
||||||
msgstr "date limite de soumission des notes de synthèse pour le premier tour"
|
msgstr "date limite de soumission des notes de synthèse pour le premier tour"
|
||||||
|
|
||||||
#: participation/templates/participation/tournament_detail.html:44
|
#: participation/templates/participation/tournament_detail.html:44
|
||||||
msgid "date of maximal written reviews submission for the second round"
|
msgid "date of maximal syntheses submission for the second round"
|
||||||
msgstr "date limite de soumission des notes de synthèse pour le second tour"
|
msgstr "date limite de soumission des notes de synthèse pour le second tour"
|
||||||
|
|
||||||
#: participation/templates/participation/tournament_detail.html:48
|
#: participation/templates/participation/tournament_detail.html:48
|
||||||
msgid "date of maximal written reviews submission for the third round"
|
msgid "date of maximal syntheses submission for the third round"
|
||||||
msgstr "date limite de soumission des notes de synthèse pour le troisième tour"
|
msgstr "date limite de soumission des notes de synthèse pour le troisième tour"
|
||||||
|
|
||||||
#: participation/templates/participation/tournament_detail.html:56
|
#: participation/templates/participation/tournament_detail.html:56
|
||||||
@ -2523,42 +2462,6 @@ msgstr "Dépublier les notes pour le troisième tour"
|
|||||||
msgid "Files available for download"
|
msgid "Files available for download"
|
||||||
msgstr "Fichiers disponibles au téléchargement"
|
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
|
#: participation/templates/participation/tournament_harmonize.html:16
|
||||||
#: registration/models.py:655
|
#: registration/models.py:655
|
||||||
msgid "Note"
|
msgid "Note"
|
||||||
@ -2601,11 +2504,11 @@ msgstr ""
|
|||||||
msgid "Download empty notation sheet"
|
msgid "Download empty notation sheet"
|
||||||
msgstr "Télécharger la fiche de notation vierge"
|
msgstr "Télécharger la fiche de notation vierge"
|
||||||
|
|
||||||
#: participation/templates/participation/upload_written_review.html:9
|
#: participation/templates/participation/upload_synthesis.html:9
|
||||||
msgid "Templates:"
|
msgid "Templates:"
|
||||||
msgstr "Modèles :"
|
msgstr "Modèles :"
|
||||||
|
|
||||||
#: participation/templates/participation/upload_written_review.html:14
|
#: participation/templates/participation/upload_synthesis.html:13
|
||||||
msgid "Warning: non-free format"
|
msgid "Warning: non-free format"
|
||||||
msgstr "Attention : format non libre"
|
msgstr "Attention : format non libre"
|
||||||
|
|
||||||
@ -2753,96 +2656,96 @@ msgstr "Vous ne pouvez pas envoyer de solution après la date limite."
|
|||||||
msgid "Solutions of team {trigram}.zip"
|
msgid "Solutions of team {trigram}.zip"
|
||||||
msgstr "Solutions de l'équipe {trigram}.zip"
|
msgstr "Solutions de l'équipe {trigram}.zip"
|
||||||
|
|
||||||
#: participation/views.py:1023
|
#: participation/views.py:1022
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Written reviews of team {trigram}.zip"
|
msgid "Syntheses of team {trigram}.zip"
|
||||||
msgstr "Notes de synthèse de l'équipe {trigram}.zip"
|
msgstr "Notes de synthèse de l'équipe {trigram}.zip"
|
||||||
|
|
||||||
#: participation/views.py:1040 participation/views.py:1056
|
#: participation/views.py:1039 participation/views.py:1054
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Solutions of {tournament}.zip"
|
msgid "Solutions of {tournament}.zip"
|
||||||
msgstr "Solutions de {tournament}.zip"
|
msgstr "Solutions de {tournament}.zip"
|
||||||
|
|
||||||
#: participation/views.py:1041 participation/views.py:1057
|
#: participation/views.py:1039 participation/views.py:1054
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Written reviews of {tournament}.zip"
|
msgid "Syntheses of {tournament}.zip"
|
||||||
msgstr "Notes de synthèse de {tournament}.zip"
|
msgstr "Notes de synthèse de {tournament}.zip"
|
||||||
|
|
||||||
#: participation/views.py:1066
|
#: participation/views.py:1063
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Solutions for pool {pool} of tournament {tournament}.zip"
|
msgid "Solutions for pool {pool} of tournament {tournament}.zip"
|
||||||
msgstr "Solutions pour la poule {pool} du tournoi {tournament}.zip"
|
msgstr "Solutions pour la poule {pool} du tournoi {tournament}.zip"
|
||||||
|
|
||||||
#: participation/views.py:1067
|
#: participation/views.py:1064
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Written reviews for pool {pool} of tournament {tournament}.zip"
|
msgid "Syntheses for pool {pool} of tournament {tournament}.zip"
|
||||||
msgstr "Notes de synthèses pour la poule {pool} du tournoi {tournament}.zip"
|
msgstr "Notes de synthèses pour la poule {pool} du tournoi {tournament}.zip"
|
||||||
|
|
||||||
#: participation/views.py:1109
|
#: participation/views.py:1106
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Jury of pool {pool} for {tournament} with teams {teams}"
|
msgid "Jury of pool {pool} for {tournament} with teams {teams}"
|
||||||
msgstr "Jury de la poule {pool} pour {tournament} avec les équipes {teams}"
|
msgstr "Jury de la poule {pool} pour {tournament} avec les équipes {teams}"
|
||||||
|
|
||||||
#: participation/views.py:1125
|
#: participation/views.py:1122
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "The jury {name} is already in the pool!"
|
msgid "The jury {name} is already in the pool!"
|
||||||
msgstr "{name} est déjà dans la poule !"
|
msgstr "{name} est déjà dans la poule !"
|
||||||
|
|
||||||
#: participation/views.py:1145
|
#: participation/views.py:1142
|
||||||
msgid "New jury account"
|
msgid "New jury account"
|
||||||
msgstr "Nouveau compte de juré⋅e"
|
msgstr "Nouveau compte de juré⋅e"
|
||||||
|
|
||||||
#: participation/views.py:1166
|
#: participation/views.py:1163
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "The jury {name} has been successfully added!"
|
msgid "The jury {name} has been successfully added!"
|
||||||
msgstr "{name} a été ajouté⋅e avec succès en tant que juré⋅e !"
|
msgstr "{name} a été ajouté⋅e avec succès en tant que juré⋅e !"
|
||||||
|
|
||||||
#: participation/views.py:1202
|
#: participation/views.py:1199
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "The jury {name} has been successfully removed!"
|
msgid "The jury {name} has been successfully removed!"
|
||||||
msgstr "{name} a été retiré⋅e avec succès du jury !"
|
msgstr "{name} a été retiré⋅e avec succès du jury !"
|
||||||
|
|
||||||
#: participation/views.py:1228
|
#: participation/views.py:1225
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "The jury {name} has been successfully promoted president!"
|
msgid "The jury {name} has been successfully promoted president!"
|
||||||
msgstr "{name} a été nommé⋅e président⋅e du jury !"
|
msgstr "{name} a été nommé⋅e président⋅e du jury !"
|
||||||
|
|
||||||
#: participation/views.py:1256
|
#: participation/views.py:1253
|
||||||
msgid "The following user is not registered as a jury:"
|
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 :"
|
msgstr "L'utilisateur⋅rice suivant n'est pas inscrit⋅e en tant que juré⋅e :"
|
||||||
|
|
||||||
#: participation/views.py:1272
|
#: participation/views.py:1269
|
||||||
msgid "Notes were successfully uploaded."
|
msgid "Notes were successfully uploaded."
|
||||||
msgstr "Les notes ont bien été envoyées."
|
msgstr "Les notes ont bien été envoyées."
|
||||||
|
|
||||||
#: participation/views.py:1507
|
#: participation/views.py:1504
|
||||||
msgid "Reporter"
|
msgid "Defender"
|
||||||
msgstr "Défenseur⋅se"
|
msgstr "Défenseur⋅se"
|
||||||
|
|
||||||
#: participation/views.py:1513
|
#: participation/views.py:1510
|
||||||
msgid "Opponent"
|
msgid "Opponent"
|
||||||
msgstr "Opposant⋅e"
|
msgstr "Opposant⋅e"
|
||||||
|
|
||||||
#: participation/views.py:1520
|
#: participation/views.py:1517
|
||||||
msgid "Reviewer"
|
msgid "Reviewer"
|
||||||
msgstr "Rapporteur⋅rice"
|
msgstr "Rapporteur⋅rice"
|
||||||
|
|
||||||
#: participation/views.py:1527
|
#: participation/views.py:1524
|
||||||
msgid "Observer"
|
msgid "Observer"
|
||||||
msgstr "Observateur⋅rice"
|
msgstr "Observateur⋅rice"
|
||||||
|
|
||||||
#: participation/views.py:1898
|
#: participation/views.py:1895
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Notation sheets of pool {pool} of {tournament}.zip"
|
msgid "Notation sheets of pool {pool} of {tournament}.zip"
|
||||||
msgstr "Feuilles de notations pour la poule {pool} du tournoi {tournament}.zip"
|
msgstr "Feuilles de notations pour la poule {pool} du tournoi {tournament}.zip"
|
||||||
|
|
||||||
#: participation/views.py:1903
|
#: participation/views.py:1900
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Notation sheets of {tournament}.zip"
|
msgid "Notation sheets of {tournament}.zip"
|
||||||
msgstr "Feuilles de notation de {tournament}.zip"
|
msgstr "Feuilles de notation de {tournament}.zip"
|
||||||
|
|
||||||
#: participation/views.py:2070
|
#: participation/views.py:2067
|
||||||
msgid "You can't upload a written review 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."
|
||||||
|
|
||||||
#: registration/admin.py:53 registration/admin.py:69 registration/admin.py:85
|
#: registration/admin.py:53 registration/admin.py:69 registration/admin.py:85
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from .models import Note, Participation, Passage, Pool, Solution, Team, Tournament, Tweak, WrittenReview
|
from .models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament, Tweak
|
||||||
|
|
||||||
|
|
||||||
class ParticipationInline(admin.StackedInline):
|
class ParticipationInline(admin.StackedInline):
|
||||||
@ -32,8 +32,8 @@ class SolutionInline(admin.TabularInline):
|
|||||||
show_change_link = True
|
show_change_link = True
|
||||||
|
|
||||||
|
|
||||||
class WrittenReviewInline(admin.TabularInline):
|
class SynthesisInline(admin.TabularInline):
|
||||||
model = WrittenReview
|
model = Synthesis
|
||||||
extra = 0
|
extra = 0
|
||||||
ordering = ('passage__solution_number', 'type',)
|
ordering = ('passage__solution_number', 'type',)
|
||||||
autocomplete_fields = ('passage',)
|
autocomplete_fields = ('passage',)
|
||||||
@ -51,7 +51,7 @@ class PassageInline(admin.TabularInline):
|
|||||||
model = Passage
|
model = Passage
|
||||||
extra = 0
|
extra = 0
|
||||||
ordering = ('position',)
|
ordering = ('position',)
|
||||||
autocomplete_fields = ('reporter', 'opponent', 'reviewer', 'observer',)
|
autocomplete_fields = ('defender', 'opponent', 'reviewer', 'observer',)
|
||||||
show_change_link = True
|
show_change_link = True
|
||||||
|
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ class ParticipationAdmin(admin.ModelAdmin):
|
|||||||
search_fields = ('team__name', 'team__trigram',)
|
search_fields = ('team__name', 'team__trigram',)
|
||||||
list_filter = ('valid', 'tournament',)
|
list_filter = ('valid', 'tournament',)
|
||||||
autocomplete_fields = ('team', 'tournament',)
|
autocomplete_fields = ('team', 'tournament',)
|
||||||
inlines = (SolutionInline, WrittenReviewInline,)
|
inlines = (SolutionInline, SynthesisInline,)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Pool)
|
@admin.register(Pool)
|
||||||
@ -113,17 +113,17 @@ class PoolAdmin(admin.ModelAdmin):
|
|||||||
|
|
||||||
@admin.register(Passage)
|
@admin.register(Passage)
|
||||||
class PassageAdmin(admin.ModelAdmin):
|
class PassageAdmin(admin.ModelAdmin):
|
||||||
list_display = ('__str__', 'reporter_trigram', 'solution_number', 'opponent_trigram', 'reviewer_trigram',
|
list_display = ('__str__', 'defender_trigram', 'solution_number', 'opponent_trigram', 'reviewer_trigram',
|
||||||
'observer_trigram', 'pool_abbr', 'position', 'tournament')
|
'observer_trigram', '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', 'reporter', 'opponent', 'reviewer', 'observer',)
|
autocomplete_fields = ('pool', 'defender', 'opponent', 'reviewer', 'observer',)
|
||||||
inlines = (NoteInline,)
|
inlines = (NoteInline,)
|
||||||
|
|
||||||
@admin.display(description=_("reporter"), ordering='reporter__team__trigram')
|
@admin.display(description=_("defender"), ordering='defender__team__trigram')
|
||||||
def reporter_trigram(self, record: Passage):
|
def defender_trigram(self, record: Passage):
|
||||||
return record.reporter.team.trigram
|
return record.defender.team.trigram
|
||||||
|
|
||||||
@admin.display(description=_("opponent"), ordering='opponent__team__trigram')
|
@admin.display(description=_("opponent"), ordering='opponent__team__trigram')
|
||||||
def opponent_trigram(self, record: Passage):
|
def opponent_trigram(self, record: Passage):
|
||||||
@ -148,13 +148,13 @@ class PassageAdmin(admin.ModelAdmin):
|
|||||||
|
|
||||||
@admin.register(Note)
|
@admin.register(Note)
|
||||||
class NoteAdmin(admin.ModelAdmin):
|
class NoteAdmin(admin.ModelAdmin):
|
||||||
list_display = ('passage', 'pool', 'jury', 'reporter_writing', 'reporter_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',)
|
'observer_writing', 'observer_oral',)
|
||||||
list_filter = ('passage__pool__letter', 'passage__solution_number', 'jury',
|
list_filter = ('passage__pool__letter', 'passage__solution_number', 'jury',
|
||||||
'reporter_writing', 'reporter_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', 'observer_writing', 'observer_oral')
|
||||||
search_fields = ('jury__user__last_name', 'jury__user__first_name', 'passage__reporter__team__trigram',)
|
search_fields = ('jury__user__last_name', 'jury__user__first_name', 'passage__defender__team__trigram',)
|
||||||
autocomplete_fields = ('jury', 'passage',)
|
autocomplete_fields = ('jury', 'passage',)
|
||||||
|
|
||||||
@admin.display(description=_("pool"))
|
@admin.display(description=_("pool"))
|
||||||
@ -178,19 +178,19 @@ class SolutionAdmin(admin.ModelAdmin):
|
|||||||
return Tournament.final_tournament() if record.final_solution else record.participation.tournament
|
return Tournament.final_tournament() if record.final_solution else record.participation.tournament
|
||||||
|
|
||||||
|
|
||||||
@admin.register(WrittenReview)
|
@admin.register(Synthesis)
|
||||||
class WrittenReviewAdmin(admin.ModelAdmin):
|
class SynthesisAdmin(admin.ModelAdmin):
|
||||||
list_display = ('participation', 'type', 'reporter', 'passage',)
|
list_display = ('participation', 'type', 'defender', 'passage',)
|
||||||
list_filter = ('participation__tournament', 'type', 'passage__solution_number',)
|
list_filter = ('participation__tournament', 'type', 'passage__solution_number',)
|
||||||
search_fields = ('participation__team__name', 'participation__team__trigram',)
|
search_fields = ('participation__team__name', 'participation__team__trigram',)
|
||||||
autocomplete_fields = ('participation', 'passage',)
|
autocomplete_fields = ('participation', 'passage',)
|
||||||
|
|
||||||
@admin.display(description=_("reporter"))
|
@admin.display(description=_("defender"))
|
||||||
def reporter(self, record: WrittenReview):
|
def defender(self, record: Synthesis):
|
||||||
return record.passage.reporter
|
return record.passage.defender
|
||||||
|
|
||||||
@admin.display(description=_("problem"))
|
@admin.display(description=_("problem"))
|
||||||
def problem(self, record: WrittenReview):
|
def problem(self, record: Synthesis):
|
||||||
return record.passage.solution_number
|
return record.passage.solution_number
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from ..models import Note, Participation, Passage, Pool, Solution, Team, Tournament, WrittenReview
|
from ..models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament
|
||||||
|
|
||||||
|
|
||||||
class NoteSerializer(serializers.ModelSerializer):
|
class NoteSerializer(serializers.ModelSerializer):
|
||||||
@ -38,9 +38,9 @@ class SolutionSerializer(serializers.ModelSerializer):
|
|||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
class WrittenReviewSerializer(serializers.ModelSerializer):
|
class SynthesisSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = WrittenReview
|
model = Synthesis
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
@ -58,9 +58,9 @@ class TournamentSerializer(serializers.ModelSerializer):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = Tournament
|
model = Tournament
|
||||||
fields = ('id', 'pk', 'name', 'date_start', 'date_end', 'place', 'max_teams', 'price', 'remote',
|
fields = ('id', 'pk', 'name', 'date_start', 'date_end', 'place', 'max_teams', 'price', 'remote',
|
||||||
'inscription_limit', 'solution_limit', 'solutions_draw', 'reviews_first_phase_limit',
|
'inscription_limit', 'solution_limit', 'solutions_draw', 'syntheses_first_phase_limit',
|
||||||
'solutions_available_second_phase', 'reviews_second_phase_limit',
|
'solutions_available_second_phase', 'syntheses_second_phase_limit',
|
||||||
'solutions_available_third_phase', 'reviews_third_phase_limit',
|
'solutions_available_third_phase', 'syntheses_third_phase_limit',
|
||||||
'description', 'organizers', 'final', 'participations',)
|
'description', 'organizers', 'final', 'participations',)
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
from .views import NoteViewSet, ParticipationViewSet, PassageViewSet, PoolViewSet, \
|
from .views import NoteViewSet, ParticipationViewSet, PassageViewSet, PoolViewSet, \
|
||||||
SolutionViewSet, TeamViewSet, TournamentViewSet, TweakViewSet, WrittenReviewViewSet
|
SolutionViewSet, SynthesisViewSet, TeamViewSet, TournamentViewSet, TweakViewSet
|
||||||
|
|
||||||
|
|
||||||
def register_participation_urls(router, path):
|
def register_participation_urls(router, path):
|
||||||
@ -13,8 +13,8 @@ def register_participation_urls(router, path):
|
|||||||
router.register(path + "/participation", ParticipationViewSet)
|
router.register(path + "/participation", ParticipationViewSet)
|
||||||
router.register(path + "/passage", PassageViewSet)
|
router.register(path + "/passage", PassageViewSet)
|
||||||
router.register(path + "/pool", PoolViewSet)
|
router.register(path + "/pool", PoolViewSet)
|
||||||
router.register(path + "/review", WrittenReviewViewSet)
|
|
||||||
router.register(path + "/solution", SolutionViewSet)
|
router.register(path + "/solution", SolutionViewSet)
|
||||||
|
router.register(path + "/synthesis", SynthesisViewSet)
|
||||||
router.register(path + "/team", TeamViewSet)
|
router.register(path + "/team", TeamViewSet)
|
||||||
router.register(path + "/tournament", TournamentViewSet)
|
router.register(path + "/tournament", TournamentViewSet)
|
||||||
router.register(path + "/tweak", TweakViewSet)
|
router.register(path + "/tweak", TweakViewSet)
|
||||||
|
@ -4,15 +4,15 @@ from django_filters.rest_framework import DjangoFilterBackend
|
|||||||
from rest_framework.viewsets import ModelViewSet
|
from rest_framework.viewsets import ModelViewSet
|
||||||
|
|
||||||
from .serializers import NoteSerializer, ParticipationSerializer, PassageSerializer, PoolSerializer, \
|
from .serializers import NoteSerializer, ParticipationSerializer, PassageSerializer, PoolSerializer, \
|
||||||
SolutionSerializer, TeamSerializer, TournamentSerializer, TweakSerializer, WrittenReviewSerializer
|
SolutionSerializer, SynthesisSerializer, TeamSerializer, TournamentSerializer, TweakSerializer
|
||||||
from ..models import Note, Participation, Passage, Pool, Solution, Team, Tournament, Tweak, WrittenReview
|
from ..models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament, Tweak
|
||||||
|
|
||||||
|
|
||||||
class NoteViewSet(ModelViewSet):
|
class NoteViewSet(ModelViewSet):
|
||||||
queryset = Note.objects.all()
|
queryset = Note.objects.all()
|
||||||
serializer_class = NoteSerializer
|
serializer_class = NoteSerializer
|
||||||
filter_backends = [DjangoFilterBackend]
|
filter_backends = [DjangoFilterBackend]
|
||||||
filterset_fields = ['jury', 'passage', 'reporter_writing', 'reporter_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', 'observer_writing', 'observer_oral', ]
|
||||||
|
|
||||||
|
|
||||||
@ -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', 'reporter', 'opponent', 'reviewer', 'observer', 'pool_tournament', ]
|
filterset_fields = ['pool', 'solution_number', 'defender', 'opponent', 'reviewer', 'observer', 'pool_tournament', ]
|
||||||
|
|
||||||
|
|
||||||
class PoolViewSet(ModelViewSet):
|
class PoolViewSet(ModelViewSet):
|
||||||
@ -44,9 +44,9 @@ class SolutionViewSet(ModelViewSet):
|
|||||||
filterset_fields = ['participation', 'number', 'problem', 'final_solution', ]
|
filterset_fields = ['participation', 'number', 'problem', 'final_solution', ]
|
||||||
|
|
||||||
|
|
||||||
class WrittenReviewViewSet(ModelViewSet):
|
class SynthesisViewSet(ModelViewSet):
|
||||||
queryset = WrittenReview.objects.all()
|
queryset = Synthesis.objects.all()
|
||||||
serializer_class = WrittenReviewSerializer
|
serializer_class = SynthesisSerializer
|
||||||
filter_backends = [DjangoFilterBackend]
|
filter_backends = [DjangoFilterBackend]
|
||||||
filterset_fields = ['participation', 'number', 'passage', 'type', ]
|
filterset_fields = ['participation', 'number', 'passage', 'type', ]
|
||||||
|
|
||||||
@ -64,9 +64,9 @@ class TournamentViewSet(ModelViewSet):
|
|||||||
serializer_class = TournamentSerializer
|
serializer_class = TournamentSerializer
|
||||||
filter_backends = [DjangoFilterBackend]
|
filter_backends = [DjangoFilterBackend]
|
||||||
filterset_fields = ['name', 'date_start', 'date_end', 'place', 'max_teams', 'price', 'remote',
|
filterset_fields = ['name', 'date_start', 'date_end', 'place', 'max_teams', 'price', 'remote',
|
||||||
'inscription_limit', 'solution_limit', 'solutions_draw', 'reviews_first_phase_limit',
|
'inscription_limit', 'solution_limit', 'solutions_draw', 'syntheses_first_phase_limit',
|
||||||
'solutions_available_second_phase', 'reviews_second_phase_limit',
|
'solutions_available_second_phase', 'syntheses_second_phase_limit',
|
||||||
'solutions_available_third_phase', 'reviews_third_phase_limit',
|
'solutions_available_third_phase', 'syntheses_third_phase_limit',
|
||||||
'description', 'organizers', 'final', ]
|
'description', 'organizers', 'final', ]
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ from pypdf import PdfReader
|
|||||||
from registration.models import VolunteerRegistration
|
from registration.models import VolunteerRegistration
|
||||||
from tfjm import settings
|
from tfjm import settings
|
||||||
|
|
||||||
from .models import Note, Participation, Passage, Pool, Solution, Team, Tournament, WrittenReview
|
from .models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament
|
||||||
|
|
||||||
|
|
||||||
class TeamForm(forms.ModelForm):
|
class TeamForm(forms.ModelForm):
|
||||||
@ -137,7 +137,7 @@ class TournamentForm(forms.ModelForm):
|
|||||||
if settings.NB_ROUNDS < 3:
|
if settings.NB_ROUNDS < 3:
|
||||||
del self.fields['date_third_phase']
|
del self.fields['date_third_phase']
|
||||||
del self.fields['solutions_available_third_phase']
|
del self.fields['solutions_available_third_phase']
|
||||||
del self.fields['reviews_third_phase_limit']
|
del self.fields['syntheses_third_phase_limit']
|
||||||
if not settings.PAYMENT_MANAGEMENT:
|
if not settings.PAYMENT_MANAGEMENT:
|
||||||
del self.fields['price']
|
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'),
|
'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'),
|
'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'),
|
'date_first_phase': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
|
||||||
'reviews_first_phase_limit': forms.DateTimeInput(attrs={'type': 'datetime-local'},
|
'syntheses_first_phase_limit': forms.DateTimeInput(attrs={'type': 'datetime-local'},
|
||||||
format='%Y-%m-%d %H:%M'),
|
format='%Y-%m-%d %H:%M'),
|
||||||
'date_second_phase': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
|
'date_second_phase': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
|
||||||
'reviews_second_phase_limit': forms.DateTimeInput(attrs={'type': 'datetime-local'},
|
'syntheses_second_phase_limit': forms.DateTimeInput(attrs={'type': 'datetime-local'},
|
||||||
format='%Y-%m-%d %H:%M'),
|
format='%Y-%m-%d %H:%M'),
|
||||||
'date_third_phase': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
|
'date_third_phase': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
|
||||||
'reviews_third_phase_limit': forms.DateTimeInput(attrs={'type': 'datetime-local'},
|
'syntheses_third_phase_limit': forms.DateTimeInput(attrs={'type': 'datetime-local'},
|
||||||
format='%Y-%m-%d %H:%M'),
|
format='%Y-%m-%d %H:%M'),
|
||||||
'organizers': forms.SelectMultiple(attrs={
|
'organizers': forms.SelectMultiple(attrs={
|
||||||
'class': 'selectpicker',
|
'class': 'selectpicker',
|
||||||
'data-live-search': 'true',
|
'data-live-search': 'true',
|
||||||
@ -345,21 +345,21 @@ class UploadNotesForm(forms.Form):
|
|||||||
class PassageForm(forms.ModelForm):
|
class PassageForm(forms.ModelForm):
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = super().clean()
|
cleaned_data = super().clean()
|
||||||
if "reporter" in cleaned_data and "opponent" in cleaned_data and "reviewer" in cleaned_data \
|
if "defender" in cleaned_data and "opponent" in cleaned_data and "reviewer" in cleaned_data \
|
||||||
and len({cleaned_data["reporter"], cleaned_data["opponent"], cleaned_data["reviewer"]}) < 3:
|
and len({cleaned_data["defender"], cleaned_data["opponent"], cleaned_data["reviewer"]}) < 3:
|
||||||
self.add_error(None, _("The reporter, the opponent and the reviewer must be different."))
|
self.add_error(None, _("The defender, the opponent and the reviewer must be different."))
|
||||||
if "reporter" in self.cleaned_data and "solution_number" in self.cleaned_data \
|
if "defender" in self.cleaned_data and "solution_number" in self.cleaned_data \
|
||||||
and not Solution.objects.filter(participation=cleaned_data["reporter"],
|
and not Solution.objects.filter(participation=cleaned_data["defender"],
|
||||||
problem=cleaned_data["solution_number"]).exists():
|
problem=cleaned_data["solution_number"]).exists():
|
||||||
self.add_error("solution_number", _("This reporter did not work on this problem."))
|
self.add_error("solution_number", _("This defender did not work on this problem."))
|
||||||
return cleaned_data
|
return cleaned_data
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Passage
|
model = Passage
|
||||||
fields = ('position', 'solution_number', 'reporter', 'opponent', 'reviewer', 'opponent', 'reporter_penalties',)
|
fields = ('position', 'solution_number', 'defender', 'opponent', 'reviewer', 'opponent', 'defender_penalties',)
|
||||||
|
|
||||||
|
|
||||||
class WrittenReviewForm(forms.ModelForm):
|
class SynthesisForm(forms.ModelForm):
|
||||||
def clean_file(self):
|
def clean_file(self):
|
||||||
if "file" in self.files:
|
if "file" in self.files:
|
||||||
file = self.files["file"]
|
file = self.files["file"]
|
||||||
@ -375,16 +375,16 @@ class WrittenReviewForm(forms.ModelForm):
|
|||||||
|
|
||||||
def save(self, commit=True):
|
def save(self, commit=True):
|
||||||
"""
|
"""
|
||||||
Don't save a written review with this way. Use a view instead
|
Don't save a synthesis with this way. Use a view instead
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = WrittenReview
|
model = Synthesis
|
||||||
fields = ('file',)
|
fields = ('file',)
|
||||||
|
|
||||||
|
|
||||||
class NoteForm(forms.ModelForm):
|
class NoteForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Note
|
model = Note
|
||||||
fields = ('reporter_writing', 'reporter_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', 'observer_writing', 'observer_oral', )
|
||||||
|
@ -51,23 +51,23 @@ class Command(BaseCommand):
|
|||||||
team3, score3 = sorted_notes[2]
|
team3, score3 = sorted_notes[2]
|
||||||
|
|
||||||
pool1 = tournament.pools.filter(round=1, participations=team2).first()
|
pool1 = tournament.pools.filter(round=1, participations=team2).first()
|
||||||
reporter_passage_1 = Passage.objects.get(pool__tournament=tournament, pool__round=1, reporter=team2)
|
defender_passage_1 = Passage.objects.get(pool__tournament=tournament, pool__round=1, defender=team2)
|
||||||
opponent_passage_1 = Passage.objects.get(pool__tournament=tournament, pool__round=1, opponent=team2)
|
opponent_passage_1 = Passage.objects.get(pool__tournament=tournament, pool__round=1, opponent=team2)
|
||||||
reviewer_passage_1 = Passage.objects.get(pool__tournament=tournament, pool__round=1, reviewer=team2)
|
reviewer_passage_1 = Passage.objects.get(pool__tournament=tournament, pool__round=1, reviewer=team2)
|
||||||
pool2 = tournament.pools.filter(round=2, participations=team2).first()
|
pool2 = tournament.pools.filter(round=2, participations=team2).first()
|
||||||
reporter_passage_2 = Passage.objects.get(pool__tournament=tournament, pool__round=2, reporter=team2)
|
defender_passage_2 = Passage.objects.get(pool__tournament=tournament, pool__round=2, defender=team2)
|
||||||
opponent_passage_2 = Passage.objects.get(pool__tournament=tournament, pool__round=2, opponent=team2)
|
opponent_passage_2 = Passage.objects.get(pool__tournament=tournament, pool__round=2, opponent=team2)
|
||||||
reviewer_passage_2 = Passage.objects.get(pool__tournament=tournament, pool__round=2, reviewer=team2)
|
reviewer_passage_2 = Passage.objects.get(pool__tournament=tournament, pool__round=2, reviewer=team2)
|
||||||
|
|
||||||
line.append(team2.team.trigram)
|
line.append(team2.team.trigram)
|
||||||
line.append(str(pool1.jury_president or ""))
|
line.append(str(pool1.jury_president or ""))
|
||||||
line.append(f"Pb. {reporter_passage_1.solution_number}")
|
line.append(f"Pb. {defender_passage_1.solution_number}")
|
||||||
line.extend([reporter_passage_1.average_reporter_writing, reporter_passage_1.average_reporter_oral,
|
line.extend([defender_passage_1.average_defender_writing, defender_passage_1.average_defender_oral,
|
||||||
opponent_passage_1.average_opponent_writing, opponent_passage_1.average_opponent_oral,
|
opponent_passage_1.average_opponent_writing, opponent_passage_1.average_opponent_oral,
|
||||||
reviewer_passage_1.average_reviewer_writing, reviewer_passage_1.average_reviewer_oral])
|
reviewer_passage_1.average_reviewer_writing, reviewer_passage_1.average_reviewer_oral])
|
||||||
line.append(str(pool2.jury_president or ""))
|
line.append(str(pool2.jury_president or ""))
|
||||||
line.append(f"Pb. {reporter_passage_2.solution_number}")
|
line.append(f"Pb. {defender_passage_2.solution_number}")
|
||||||
line.extend([reporter_passage_2.average_reporter_writing, reporter_passage_2.average_reporter_oral,
|
line.extend([defender_passage_2.average_defender_writing, defender_passage_2.average_defender_oral,
|
||||||
opponent_passage_2.average_opponent_writing, opponent_passage_2.average_opponent_oral,
|
opponent_passage_2.average_opponent_writing, opponent_passage_2.average_opponent_oral,
|
||||||
reviewer_passage_2.average_reviewer_writing, reviewer_passage_2.average_reviewer_oral])
|
reviewer_passage_2.average_reviewer_writing, reviewer_passage_2.average_reviewer_oral])
|
||||||
line.extend([score2, f"{score1:.1f} ({team1.team.trigram})",
|
line.extend([score2, f"{score1:.1f} ({team1.team.trigram})",
|
||||||
|
@ -1,75 +0,0 @@
|
|||||||
# 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",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,133 +0,0 @@
|
|||||||
# Generated by Django 5.0.6 on 2024-07-06 20:00
|
|
||||||
import django
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("participation", "0020_rename_synthesis_writtenreview_and_more"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RenameField(
|
|
||||||
model_name="note",
|
|
||||||
old_name="defender_oral",
|
|
||||||
new_name="reporter_oral",
|
|
||||||
),
|
|
||||||
migrations.RenameField(
|
|
||||||
model_name="note",
|
|
||||||
old_name="defender_writing",
|
|
||||||
new_name="reporter_writing",
|
|
||||||
),
|
|
||||||
migrations.RenameField(
|
|
||||||
model_name="passage",
|
|
||||||
old_name="defender",
|
|
||||||
new_name="reporter",
|
|
||||||
),
|
|
||||||
migrations.RenameField(
|
|
||||||
model_name="passage",
|
|
||||||
old_name="defender_penalties",
|
|
||||||
new_name="reporter_penalties",
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="passage",
|
|
||||||
name="solution_number",
|
|
||||||
field=models.PositiveSmallIntegerField(
|
|
||||||
choices=[
|
|
||||||
(1, "Problem #1"),
|
|
||||||
(2, "Problem #2"),
|
|
||||||
(3, "Problem #3"),
|
|
||||||
(4, "Problem #4"),
|
|
||||||
(5, "Problem #5"),
|
|
||||||
(6, "Problem #6"),
|
|
||||||
(7, "Problem #7"),
|
|
||||||
(8, "Problem #8"),
|
|
||||||
(9, "Problem #9"),
|
|
||||||
(10, "Problem #10"),
|
|
||||||
],
|
|
||||||
verbose_name="reported solution",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="note",
|
|
||||||
name="reporter_oral",
|
|
||||||
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),
|
|
||||||
(11, 11),
|
|
||||||
(12, 12),
|
|
||||||
(13, 13),
|
|
||||||
(14, 14),
|
|
||||||
(15, 15),
|
|
||||||
(16, 16),
|
|
||||||
(17, 17),
|
|
||||||
(18, 18),
|
|
||||||
(19, 19),
|
|
||||||
(20, 20),
|
|
||||||
],
|
|
||||||
default=0,
|
|
||||||
verbose_name="reporter oral note",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="note",
|
|
||||||
name="reporter_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),
|
|
||||||
(11, 11),
|
|
||||||
(12, 12),
|
|
||||||
(13, 13),
|
|
||||||
(14, 14),
|
|
||||||
(15, 15),
|
|
||||||
(16, 16),
|
|
||||||
(17, 17),
|
|
||||||
(18, 18),
|
|
||||||
(19, 19),
|
|
||||||
(20, 20),
|
|
||||||
],
|
|
||||||
default=0,
|
|
||||||
verbose_name="reporter writing note",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="passage",
|
|
||||||
name="reporter",
|
|
||||||
field=models.ForeignKey(
|
|
||||||
on_delete=django.db.models.deletion.PROTECT,
|
|
||||||
related_name="+",
|
|
||||||
to="participation.participation",
|
|
||||||
verbose_name="reporter",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="passage",
|
|
||||||
name="reporter_penalties",
|
|
||||||
field=models.PositiveSmallIntegerField(
|
|
||||||
default=0,
|
|
||||||
help_text="Number of penalties for the reporter. The reporter will loose a 0.5 coefficient per penalty.",
|
|
||||||
verbose_name="penalties",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
@ -323,8 +323,8 @@ class Tournament(models.Model):
|
|||||||
default=date.today,
|
default=date.today,
|
||||||
)
|
)
|
||||||
|
|
||||||
reviews_first_phase_limit = models.DateTimeField(
|
syntheses_first_phase_limit = models.DateTimeField(
|
||||||
verbose_name=_("limit date to upload the written reviews for the first phase"),
|
verbose_name=_("limit date to upload the syntheses for the first phase"),
|
||||||
default=timezone.now,
|
default=timezone.now,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -338,8 +338,8 @@ class Tournament(models.Model):
|
|||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
reviews_second_phase_limit = models.DateTimeField(
|
syntheses_second_phase_limit = models.DateTimeField(
|
||||||
verbose_name=_("limit date to upload the written reviews for the second phase"),
|
verbose_name=_("limit date to upload the syntheses for the second phase"),
|
||||||
default=timezone.now,
|
default=timezone.now,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -353,8 +353,8 @@ class Tournament(models.Model):
|
|||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
reviews_third_phase_limit = models.DateTimeField(
|
syntheses_third_phase_limit = models.DateTimeField(
|
||||||
verbose_name=_("limit date to upload the written reviews for the third phase"),
|
verbose_name=_("limit date to upload the syntheses for the third phase"),
|
||||||
default=timezone.now,
|
default=timezone.now,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -442,10 +442,10 @@ class Tournament(models.Model):
|
|||||||
return Solution.objects.filter(participation__tournament=self)
|
return Solution.objects.filter(participation__tournament=self)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def written_reviews(self):
|
def syntheses(self):
|
||||||
if self.final:
|
if self.final:
|
||||||
return WrittenReview.objects.filter(final_solution=True)
|
return Synthesis.objects.filter(final_solution=True)
|
||||||
return WrittenReview.objects.filter(participation__tournament=self)
|
return Synthesis.objects.filter(participation__tournament=self)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def best_format(self):
|
def best_format(self):
|
||||||
@ -490,7 +490,7 @@ class Tournament(models.Model):
|
|||||||
line = [f"{participation.team.name} ({participation.team.trigram})"]
|
line = [f"{participation.team.name} ({participation.team.trigram})"]
|
||||||
lines.append(line)
|
lines.append(line)
|
||||||
|
|
||||||
passage1 = Passage.objects.get(pool__tournament=self, pool__round=1, reporter=participation)
|
passage1 = Passage.objects.get(pool__tournament=self, pool__round=1, defender=participation)
|
||||||
pool1 = passage1.pool
|
pool1 = passage1.pool
|
||||||
if pool1.participations.count() != 5:
|
if pool1.participations.count() != 5:
|
||||||
position1 = passage1.position
|
position1 = passage1.position
|
||||||
@ -502,8 +502,8 @@ class Tournament(models.Model):
|
|||||||
line.append(f"=SIERREUR('{_('Pool')} {pool1.short_name}'!$D{pool1.juries.count() + 10 + position1}; 0)")
|
line.append(f"=SIERREUR('{_('Pool')} {pool1.short_name}'!$D{pool1.juries.count() + 10 + position1}; 0)")
|
||||||
line.append(tweak1.diff if tweak1 else 0)
|
line.append(tweak1.diff if tweak1 else 0)
|
||||||
|
|
||||||
if Passage.objects.filter(pool__tournament=self, pool__round=2, reporter=participation).exists():
|
if Passage.objects.filter(pool__tournament=self, pool__round=2, defender=participation).exists():
|
||||||
passage2 = Passage.objects.get(pool__tournament=self, pool__round=2, reporter=participation)
|
passage2 = Passage.objects.get(pool__tournament=self, pool__round=2, defender=participation)
|
||||||
pool2 = passage2.pool
|
pool2 = passage2.pool
|
||||||
if pool2.participations.count() != 5:
|
if pool2.participations.count() != 5:
|
||||||
position2 = passage2.position
|
position2 = passage2.position
|
||||||
@ -519,8 +519,8 @@ class Tournament(models.Model):
|
|||||||
if settings.NB_ROUNDS >= 3:
|
if settings.NB_ROUNDS >= 3:
|
||||||
line.append(f"=$B{i + 2} + $C{i + 2} + $D{i + 2} + E{i + 2}")
|
line.append(f"=$B{i + 2} + $C{i + 2} + $D{i + 2} + E{i + 2}")
|
||||||
|
|
||||||
if Passage.objects.filter(pool__tournament=self, pool__round=3, reporter=participation).exists():
|
if Passage.objects.filter(pool__tournament=self, pool__round=3, defender=participation).exists():
|
||||||
passage3 = Passage.objects.get(pool__tournament=self, pool__round=3, reporter=participation)
|
passage3 = Passage.objects.get(pool__tournament=self, pool__round=3, defender=participation)
|
||||||
pool3 = passage3.pool
|
pool3 = passage3.pool
|
||||||
if pool3.participations.count() != 5:
|
if pool3.participations.count() != 5:
|
||||||
position3 = passage3.position
|
position3 = passage3.position
|
||||||
@ -911,128 +911,128 @@ class Participation(models.Model):
|
|||||||
'priority': 1,
|
'priority': 1,
|
||||||
'content': content,
|
'content': content,
|
||||||
})
|
})
|
||||||
elif timezone.now() <= tournament.reviews_first_phase_limit + timedelta(hours=2):
|
elif timezone.now() <= tournament.syntheses_first_phase_limit + timedelta(hours=2):
|
||||||
reporter_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, reporter=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 = Passage.objects.filter(pool__tournament=self.tournament, pool__round=1, observer=self)
|
||||||
observer_passage = observer_passage.get() if observer_passage.exists() else None
|
observer_passage = observer_passage.get() if observer_passage.exists() else None
|
||||||
|
|
||||||
reporter_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>"
|
||||||
"<p>For the first round, you will present "
|
"<p>For the first 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>")
|
||||||
draw_url = reverse_lazy("draw:index")
|
draw_url = reverse_lazy("draw:index")
|
||||||
solution_url = reporter_passage.reported_solution.file.url
|
solution_url = defender_passage.defended_solution.file.url
|
||||||
reporter_content = format_lazy(reporter_text, draw_url=draw_url,
|
defender_content = format_lazy(defender_text, draw_url=draw_url,
|
||||||
solution_url=solution_url, problem=reporter_passage.solution_number)
|
solution_url=solution_url, problem=defender_passage.solution_number)
|
||||||
|
|
||||||
opponent_text = _("<p>You will oppose the solution of the team {opponent} on the "
|
opponent_text = _("<p>You will oppose the solution of the team {opponent} on the "
|
||||||
"<a href='{solution_url}'>problem {problem}</a>. "
|
"<a href='{solution_url}'>problem {problem}</a>. "
|
||||||
"You can upload your written review on <a href='{passage_url}'>this page</a>.</p>")
|
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||||
solution_url = opponent_passage.reported_solution.file.url
|
solution_url = opponent_passage.defended_solution.file.url
|
||||||
passage_url = reverse_lazy("participation:passage_detail", args=(opponent_passage.pk,))
|
passage_url = reverse_lazy("participation:passage_detail", args=(opponent_passage.pk,))
|
||||||
opponent_content = format_lazy(opponent_text, opponent=opponent_passage.reporter.team.trigram,
|
opponent_content = format_lazy(opponent_text, opponent=opponent_passage.defender.team.trigram,
|
||||||
solution_url=solution_url,
|
solution_url=solution_url,
|
||||||
problem=opponent_passage.solution_number, passage_url=passage_url)
|
problem=opponent_passage.solution_number, passage_url=passage_url)
|
||||||
|
|
||||||
reviewer_text = _("<p>You will report the solution of the team {reviewer} on the "
|
reviewer_text = _("<p>You will report the solution of the team {reviewer} on the "
|
||||||
"<a href='{solution_url}'>problem {problem}</a>. "
|
"<a href='{solution_url}'>problem {problem}</a>. "
|
||||||
"You can upload your written review on <a href='{passage_url}'>this page</a>.</p>")
|
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||||
solution_url = reviewer_passage.reported_solution.file.url
|
solution_url = reviewer_passage.defended_solution.file.url
|
||||||
passage_url = reverse_lazy("participation:passage_detail", args=(reviewer_passage.pk,))
|
passage_url = reverse_lazy("participation:passage_detail", args=(reviewer_passage.pk,))
|
||||||
reviewer_content = format_lazy(reviewer_text, reviewer=reviewer_passage.reporter.team.trigram,
|
reviewer_content = format_lazy(reviewer_text, reviewer=reviewer_passage.defender.team.trigram,
|
||||||
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:
|
if observer_passage:
|
||||||
observer_text = _("<p>You will observe the solution of the team {observer} on the "
|
observer_text = _("<p>You will observe the solution of the team {observer} on the "
|
||||||
"<a href='{solution_url}'>problem {problem}</a>. "
|
"<a href='{solution_url}'>problem {problem}</a>. "
|
||||||
"You can upload your written review on <a href='{passage_url}'>this page</a>.</p>")
|
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||||
solution_url = observer_passage.reported_solution.file.url
|
solution_url = observer_passage.defended_solution.file.url
|
||||||
passage_url = reverse_lazy("participation:passage_detail", args=(observer_passage.pk,))
|
passage_url = reverse_lazy("participation:passage_detail", args=(observer_passage.pk,))
|
||||||
observer_content = format_lazy(observer_text,
|
observer_content = format_lazy(observer_text,
|
||||||
observer=observer_passage.reporter.team.trigram,
|
observer=observer_passage.defender.team.trigram,
|
||||||
solution_url=solution_url,
|
solution_url=solution_url,
|
||||||
problem=observer_passage.solution_number, passage_url=passage_url)
|
problem=observer_passage.solution_number, passage_url=passage_url)
|
||||||
else:
|
else:
|
||||||
observer_content = ""
|
observer_content = ""
|
||||||
|
|
||||||
if settings.TFJM_APP == "TFJM":
|
if settings.TFJM_APP == "TFJM":
|
||||||
reviews_template_begin = f"{settings.STATIC_URL}tfjm/Fiche_synthèse."
|
syntheses_template_begin = f"{settings.STATIC_URL}tfjm/Fiche_synthèse."
|
||||||
reviews_templates = " — ".join(f"<a href='{reviews_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"])
|
||||||
else:
|
else:
|
||||||
reviews_template_begin = f"{settings.STATIC_URL}eteam/Written_review."
|
syntheses_template_begin = f"{settings.STATIC_URL}eteam/Written_review."
|
||||||
reviews_templates = " — ".join(f"<a href='{reviews_template_begin}{ext}'>{ext.upper()}</a>"
|
syntheses_templates = " — ".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
|
||||||
for ext in ["pdf", "tex"])
|
for ext in ["pdf", "tex"])
|
||||||
reviews_templates_content = f"<p>{_('Templates:')} {reviews_templates}</p>"
|
syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>"
|
||||||
|
|
||||||
content = reporter_content + opponent_content + reviewer_content + observer_content \
|
content = defender_content + opponent_content + reviewer_content + observer_content \
|
||||||
+ reviews_templates_content
|
+ syntheses_templates_content
|
||||||
informations.append({
|
informations.append({
|
||||||
'title': _("First round"),
|
'title': _("First round"),
|
||||||
'type': "info",
|
'type': "info",
|
||||||
'priority': 1,
|
'priority': 1,
|
||||||
'content': content,
|
'content': content,
|
||||||
})
|
})
|
||||||
elif timezone.now() <= tournament.reviews_second_phase_limit + timedelta(hours=2):
|
elif timezone.now() <= tournament.syntheses_second_phase_limit + timedelta(hours=2):
|
||||||
reporter_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, reporter=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 = Passage.objects.filter(pool__tournament=self.tournament, pool__round=2, observer=self)
|
||||||
observer_passage = observer_passage.get() if observer_passage.exists() else None
|
observer_passage = observer_passage.get() if observer_passage.exists() else None
|
||||||
|
|
||||||
reporter_text = _("<p>For the second round, you will present "
|
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>")
|
||||||
draw_url = reverse_lazy("draw:index")
|
draw_url = reverse_lazy("draw:index")
|
||||||
solution_url = reporter_passage.reported_solution.file.url
|
solution_url = defender_passage.defended_solution.file.url
|
||||||
reporter_content = format_lazy(reporter_text, draw_url=draw_url,
|
defender_content = format_lazy(defender_text, draw_url=draw_url,
|
||||||
solution_url=solution_url, problem=reporter_passage.solution_number)
|
solution_url=solution_url, problem=defender_passage.solution_number)
|
||||||
|
|
||||||
opponent_text = _("<p>You will oppose the solution of the team {opponent} on the "
|
opponent_text = _("<p>You will oppose the solution of the team {opponent} on the "
|
||||||
"<a href='{solution_url}'>problem {problem}</a>. "
|
"<a href='{solution_url}'>problem {problem}</a>. "
|
||||||
"You can upload your written review on <a href='{passage_url}'>this page</a>.</p>")
|
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||||
solution_url = opponent_passage.reported_solution.file.url
|
solution_url = opponent_passage.defended_solution.file.url
|
||||||
passage_url = reverse_lazy("participation:passage_detail", args=(opponent_passage.pk,))
|
passage_url = reverse_lazy("participation:passage_detail", args=(opponent_passage.pk,))
|
||||||
opponent_content = format_lazy(opponent_text, opponent=opponent_passage.reporter.team.trigram,
|
opponent_content = format_lazy(opponent_text, opponent=opponent_passage.defender.team.trigram,
|
||||||
solution_url=solution_url,
|
solution_url=solution_url,
|
||||||
problem=opponent_passage.solution_number, passage_url=passage_url)
|
problem=opponent_passage.solution_number, passage_url=passage_url)
|
||||||
|
|
||||||
reviewer_text = _("<p>You will report the solution of the team {reviewer} on the "
|
reviewer_text = _("<p>You will report the solution of the team {reviewer} on the "
|
||||||
"<a href='{solution_url}'>problem {problem}</a>. "
|
"<a href='{solution_url}'>problem {problem}</a>. "
|
||||||
"You can upload your written review on <a href='{passage_url}'>this page</a>.</p>")
|
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||||
solution_url = reviewer_passage.reported_solution.file.url
|
solution_url = reviewer_passage.defended_solution.file.url
|
||||||
passage_url = reverse_lazy("participation:passage_detail", args=(reviewer_passage.pk,))
|
passage_url = reverse_lazy("participation:passage_detail", args=(reviewer_passage.pk,))
|
||||||
reviewer_content = format_lazy(reviewer_text, reviewer=reviewer_passage.reporter.team.trigram,
|
reviewer_content = format_lazy(reviewer_text, reviewer=reviewer_passage.defender.team.trigram,
|
||||||
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:
|
if observer_passage:
|
||||||
observer_text = _("<p>You will observe the solution of the team {observer} on the "
|
observer_text = _("<p>You will observe the solution of the team {observer} on the "
|
||||||
"<a href='{solution_url}'>problem {problem}</a>. "
|
"<a href='{solution_url}'>problem {problem}</a>. "
|
||||||
"You can upload your written review on <a href='{passage_url}'>this page</a>.</p>")
|
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||||
solution_url = observer_passage.reported_solution.file.url
|
solution_url = observer_passage.defended_solution.file.url
|
||||||
passage_url = reverse_lazy("participation:passage_detail", args=(observer_passage.pk,))
|
passage_url = reverse_lazy("participation:passage_detail", args=(observer_passage.pk,))
|
||||||
observer_content = format_lazy(observer_text,
|
observer_content = format_lazy(observer_text,
|
||||||
observer=observer_passage.reporter.team.trigram,
|
observer=observer_passage.defender.team.trigram,
|
||||||
solution_url=solution_url,
|
solution_url=solution_url,
|
||||||
problem=observer_passage.solution_number, passage_url=passage_url)
|
problem=observer_passage.solution_number, passage_url=passage_url)
|
||||||
else:
|
else:
|
||||||
observer_content = ""
|
observer_content = ""
|
||||||
|
|
||||||
if settings.TFJM_APP == "TFJM":
|
if settings.TFJM_APP == "TFJM":
|
||||||
reviews_template_begin = f"{settings.STATIC_URL}tfjm/Fiche_synthèse."
|
syntheses_template_begin = f"{settings.STATIC_URL}tfjm/Fiche_synthèse."
|
||||||
reviews_templates = " — ".join(f"<a href='{reviews_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"])
|
||||||
else:
|
else:
|
||||||
reviews_template_begin = f"{settings.STATIC_URL}eteam/Written_review."
|
syntheses_template_begin = f"{settings.STATIC_URL}eteam/Written_review."
|
||||||
reviews_templates = " — ".join(f"<a href='{reviews_template_begin}{ext}'>{ext.upper()}</a>"
|
syntheses_templates = " — ".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
|
||||||
for ext in ["pdf", "tex"])
|
for ext in ["pdf", "tex"])
|
||||||
reviews_templates_content = f"<p>{_('Templates:')} {reviews_templates}</p>"
|
syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>"
|
||||||
|
|
||||||
content = reporter_content + opponent_content + reviewer_content + observer_content \
|
content = defender_content + opponent_content + reviewer_content + observer_content \
|
||||||
+ reviews_templates_content
|
+ syntheses_templates_content
|
||||||
informations.append({
|
informations.append({
|
||||||
'title': _("Second round"),
|
'title': _("Second round"),
|
||||||
'type': "info",
|
'type': "info",
|
||||||
@ -1040,63 +1040,63 @@ class Participation(models.Model):
|
|||||||
'content': content,
|
'content': content,
|
||||||
})
|
})
|
||||||
elif settings.TFJM_APP == "ETEAM" \
|
elif settings.TFJM_APP == "ETEAM" \
|
||||||
and timezone.now() <= tournament.reviews_third_phase_limit + timedelta(hours=2):
|
and timezone.now() <= tournament.syntheses_third_phase_limit + timedelta(hours=2):
|
||||||
reporter_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, reporter=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 = Passage.objects.filter(pool__tournament=self.tournament, pool__round=3, observer=self)
|
||||||
observer_passage = observer_passage.get() if observer_passage.exists() else None
|
observer_passage = observer_passage.get() if observer_passage.exists() else None
|
||||||
|
|
||||||
reporter_text = _("<p>For the third round, you will present "
|
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>")
|
||||||
draw_url = reverse_lazy("draw:index")
|
draw_url = reverse_lazy("draw:index")
|
||||||
solution_url = reporter_passage.reported_solution.file.url
|
solution_url = defender_passage.defended_solution.file.url
|
||||||
reporter_content = format_lazy(reporter_text, draw_url=draw_url,
|
defender_content = format_lazy(defender_text, draw_url=draw_url,
|
||||||
solution_url=solution_url, problem=reporter_passage.solution_number)
|
solution_url=solution_url, problem=defender_passage.solution_number)
|
||||||
|
|
||||||
opponent_text = _("<p>You will oppose the solution of the team {opponent} on the "
|
opponent_text = _("<p>You will oppose the solution of the team {opponent} on the "
|
||||||
"<a href='{solution_url}'>problem {problem}</a>. "
|
"<a href='{solution_url}'>problem {problem}</a>. "
|
||||||
"You can upload your written review on <a href='{passage_url}'>this page</a>.</p>")
|
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||||
solution_url = opponent_passage.reported_solution.file.url
|
solution_url = opponent_passage.defended_solution.file.url
|
||||||
passage_url = reverse_lazy("participation:passage_detail", args=(opponent_passage.pk,))
|
passage_url = reverse_lazy("participation:passage_detail", args=(opponent_passage.pk,))
|
||||||
opponent_content = format_lazy(opponent_text, opponent=opponent_passage.reporter.team.trigram,
|
opponent_content = format_lazy(opponent_text, opponent=opponent_passage.defender.team.trigram,
|
||||||
solution_url=solution_url,
|
solution_url=solution_url,
|
||||||
problem=opponent_passage.solution_number, passage_url=passage_url)
|
problem=opponent_passage.solution_number, passage_url=passage_url)
|
||||||
|
|
||||||
reviewer_text = _("<p>You will report the solution of the team {reviewer} on the "
|
reviewer_text = _("<p>You will report the solution of the team {reviewer} on the "
|
||||||
"<a href='{solution_url}'>problem {problem}</a>. "
|
"<a href='{solution_url}'>problem {problem}</a>. "
|
||||||
"You can upload your written review on <a href='{passage_url}'>this page</a>.</p>")
|
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||||
solution_url = reviewer_passage.reported_solution.file.url
|
solution_url = reviewer_passage.defended_solution.file.url
|
||||||
passage_url = reverse_lazy("participation:passage_detail", args=(reviewer_passage.pk,))
|
passage_url = reverse_lazy("participation:passage_detail", args=(reviewer_passage.pk,))
|
||||||
reviewer_content = format_lazy(reviewer_text, reviewer=reviewer_passage.reporter.team.trigram,
|
reviewer_content = format_lazy(reviewer_text, reviewer=reviewer_passage.defender.team.trigram,
|
||||||
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:
|
if observer_passage:
|
||||||
observer_text = _("<p>You will observe the solution of the team {observer} on the "
|
observer_text = _("<p>You will observe the solution of the team {observer} on the "
|
||||||
"<a href='{solution_url}'>problem {problem}</a>. "
|
"<a href='{solution_url}'>problem {problem}</a>. "
|
||||||
"You can upload your written review on <a href='{passage_url}'>this page</a>.</p>")
|
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||||
solution_url = observer_passage.reported_solution.file.url
|
solution_url = observer_passage.defended_solution.file.url
|
||||||
passage_url = reverse_lazy("participation:passage_detail", args=(observer_passage.pk,))
|
passage_url = reverse_lazy("participation:passage_detail", args=(observer_passage.pk,))
|
||||||
observer_content = format_lazy(observer_text,
|
observer_content = format_lazy(observer_text,
|
||||||
observer=observer_passage.reporter.team.trigram,
|
observer=observer_passage.defender.team.trigram,
|
||||||
solution_url=solution_url,
|
solution_url=solution_url,
|
||||||
problem=observer_passage.solution_number, passage_url=passage_url)
|
problem=observer_passage.solution_number, passage_url=passage_url)
|
||||||
else:
|
else:
|
||||||
observer_content = ""
|
observer_content = ""
|
||||||
|
|
||||||
if settings.TFJM_APP == "TFJM":
|
if settings.TFJM_APP == "TFJM":
|
||||||
reviews_template_begin = f"{settings.STATIC_URL}tfjm/Fiche_synthèse."
|
syntheses_template_begin = f"{settings.STATIC_URL}tfjm/Fiche_synthèse."
|
||||||
reviews_templates = " — ".join(f"<a href='{reviews_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"])
|
||||||
else:
|
else:
|
||||||
reviews_template_begin = f"{settings.STATIC_URL}eteam/Written_review."
|
syntheses_template_begin = f"{settings.STATIC_URL}eteam/Written_review."
|
||||||
reviews_templates = " — ".join(f"<a href='{reviews_template_begin}{ext}'>{ext.upper()}</a>"
|
syntheses_templates = " — ".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
|
||||||
for ext in ["pdf", "tex"])
|
for ext in ["pdf", "tex"])
|
||||||
reviews_templates_content = f"<p>{_('Templates:')} {reviews_templates}</p>"
|
syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>"
|
||||||
|
|
||||||
content = reporter_content + opponent_content + reviewer_content + observer_content \
|
content = defender_content + opponent_content + reviewer_content + observer_content \
|
||||||
+ reviews_templates_content
|
+ syntheses_templates_content
|
||||||
informations.append({
|
informations.append({
|
||||||
'title': _("Second round"),
|
'title': _("Second round"),
|
||||||
'type': "info",
|
'type': "info",
|
||||||
@ -1204,7 +1204,7 @@ class Pool(models.Model):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def solutions(self):
|
def solutions(self):
|
||||||
return [passage.reported_solution for passage in self.passages.all()]
|
return [passage.defended_solution for passage in self.passages.all()]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def coeff(self):
|
def coeff(self):
|
||||||
@ -1251,12 +1251,12 @@ class Pool(models.Model):
|
|||||||
header = [
|
header = [
|
||||||
sum(([str(_("Problem #{problem}").format(problem=passage.solution_number))] + (passage_width - 1) * [""]
|
sum(([str(_("Problem #{problem}").format(problem=passage.solution_number))] + (passage_width - 1) * [""]
|
||||||
for passage in passages), start=[str(_("Problem")), ""]),
|
for passage in passages), start=[str(_("Problem")), ""]),
|
||||||
sum(([f"{_('Reporter')} ({passage.reporter.team.trigram})", "",
|
sum(([f"{_('Defender')} ({passage.defender.team.trigram})", "",
|
||||||
f"{_('Opponent')} ({passage.opponent.team.trigram})", "",
|
f"{_('Opponent')} ({passage.opponent.team.trigram})", "",
|
||||||
f"{_('Reviewer')} ({passage.reviewer.team.trigram})", ""]
|
f"{_('Reviewer')} ({passage.reviewer.team.trigram})", ""]
|
||||||
+ ([f"{_('Observer')} ({passage.observer.team.trigram})", ""] if has_observer else [])
|
+ ([f"{_('Observer')} ({passage.observer.team.trigram})", ""] if has_observer else [])
|
||||||
for passage in passages), start=[str(_("Role")), ""]),
|
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"{_('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)", f"{_('Writing')} (/10)", f"{_('Oral')} (/10)"]
|
||||||
+ ([f"{_('Writing')} (/10)", f"{_('Oral')} (/10)"] if has_observer else [])
|
+ ([f"{_('Writing')} (/10)", f"{_('Oral')} (/10)"] if has_observer else [])
|
||||||
@ -1268,7 +1268,7 @@ class Pool(models.Model):
|
|||||||
line = [str(jury), jury.id]
|
line = [str(jury), jury.id]
|
||||||
for passage in passages:
|
for passage in passages:
|
||||||
note = passage.notes.filter(jury=jury).first()
|
note = passage.notes.filter(jury=jury).first()
|
||||||
line.extend([note.reporter_writing, note.reporter_oral, note.opponent_writing, note.opponent_oral,
|
line.extend([note.defender_writing, note.defender_oral, note.opponent_writing, note.opponent_oral,
|
||||||
note.reviewer_writing, note.reviewer_oral])
|
note.reviewer_writing, note.reviewer_oral])
|
||||||
if has_observer:
|
if has_observer:
|
||||||
line.extend([note.observer_writing, note.observer_oral])
|
line.extend([note.observer_writing, note.observer_oral])
|
||||||
@ -1284,7 +1284,7 @@ class Pool(models.Model):
|
|||||||
return getcol((number - 1) // 26) + chr(65 + (number - 1) % 26)
|
return getcol((number - 1) // 26) + chr(65 + (number - 1) % 26)
|
||||||
|
|
||||||
average = [str(_("Average")), ""]
|
average = [str(_("Average")), ""]
|
||||||
coeffs = sum(([passage.coeff_reporter_writing, passage.coeff_reporter_oral,
|
coeffs = sum(([passage.coeff_defender_writing, passage.coeff_defender_oral,
|
||||||
passage.coeff_opponent_writing, passage.coeff_opponent_oral,
|
passage.coeff_opponent_writing, passage.coeff_opponent_oral,
|
||||||
passage.coeff_reviewer_writing, passage.coeff_reviewer_oral]
|
passage.coeff_reviewer_writing, passage.coeff_reviewer_oral]
|
||||||
+ ([passage.coeff_observer_writing, passage.coeff_observer_oral] if has_observer else [])
|
+ ([passage.coeff_observer_writing, passage.coeff_observer_oral] if has_observer else [])
|
||||||
@ -1330,11 +1330,11 @@ class Pool(models.Model):
|
|||||||
pool__round=self.round,
|
pool__round=self.round,
|
||||||
pool__letter=self.letter).order_by('position', 'pool__room')
|
pool__letter=self.letter).order_by('position', 'pool__room')
|
||||||
for i, passage in enumerate(all_passages):
|
for i, passage in enumerate(all_passages):
|
||||||
participation = passage.reporter
|
participation = passage.defender
|
||||||
reporter_passage = Passage.objects.get(reporter=participation,
|
defender_passage = Passage.objects.get(defender=participation,
|
||||||
pool__tournament=self.tournament, pool__round=self.round)
|
pool__tournament=self.tournament, pool__round=self.round)
|
||||||
reporter_row = 5 + reporter_passage.pool.juries.count()
|
defender_row = 5 + defender_passage.pool.juries.count()
|
||||||
reporter_col = reporter_passage.position - 1
|
defender_col = defender_passage.position - 1
|
||||||
|
|
||||||
opponent_passage = Passage.objects.get(opponent=participation,
|
opponent_passage = Passage.objects.get(opponent=participation,
|
||||||
pool__tournament=self.tournament, pool__round=self.round)
|
pool__tournament=self.tournament, pool__round=self.round)
|
||||||
@ -1347,8 +1347,8 @@ class Pool(models.Model):
|
|||||||
reviewer_col = reviewer_passage.position - 1
|
reviewer_col = reviewer_passage.position - 1
|
||||||
|
|
||||||
formula = "="
|
formula = "="
|
||||||
formula += (f"'{_('Pool')} {reporter_passage.pool.short_name}'"
|
formula += (f"'{_('Pool')} {defender_passage.pool.short_name}'"
|
||||||
f"!{getcol(min_column + reporter_col * passage_width)}{reporter_row + 3}") # Reporter
|
f"!{getcol(min_column + defender_col * passage_width)}{defender_row + 3}") # Defender
|
||||||
formula += (f" + '{_('Pool')} {opponent_passage.pool.short_name}'"
|
formula += (f" + '{_('Pool')} {opponent_passage.pool.short_name}'"
|
||||||
f"!{getcol(min_column + opponent_col * passage_width + 2)}{opponent_row + 3}") # Opponent
|
f"!{getcol(min_column + opponent_col * passage_width + 2)}{opponent_row + 3}") # Opponent
|
||||||
formula += (f" + '{_('Pool')} {reviewer_passage.pool.short_name}'"
|
formula += (f" + '{_('Pool')} {reviewer_passage.pool.short_name}'"
|
||||||
@ -1362,8 +1362,8 @@ class Pool(models.Model):
|
|||||||
f"!{getcol(min_column + observer_col * passage_width + 6)}{observer_row + 3}")
|
f"!{getcol(min_column + observer_col * passage_width + 6)}{observer_row + 3}")
|
||||||
|
|
||||||
ranking.append([f"{participation.team.name} ({participation.team.trigram})", "",
|
ranking.append([f"{participation.team.name} ({participation.team.trigram})", "",
|
||||||
f"='{_('Pool')} {reporter_passage.pool.short_name}'"
|
f"='{_('Pool')} {defender_passage.pool.short_name}'"
|
||||||
f"!${getcol(3 + reporter_col * passage_width)}$1",
|
f"!${getcol(3 + defender_col * passage_width)}$1",
|
||||||
formula,
|
formula,
|
||||||
f"=RANG(D{max_row + 6 + i}; "
|
f"=RANG(D{max_row + 6 + i}; "
|
||||||
f"D${max_row + 6}:D${max_row + 5 + pool_size})"])
|
f"D${max_row + 6}:D${max_row + 5 + pool_size})"])
|
||||||
@ -1430,7 +1430,7 @@ class Pool(models.Model):
|
|||||||
(f"A{max_row + 6}:E{max_row + 5 + pool_size}", (0.9, 0.9, 0.9)),]
|
(f"A{max_row + 6}:E{max_row + 5 + pool_size}", (0.9, 0.9, 0.9)),]
|
||||||
# Display penalties in red
|
# Display penalties in red
|
||||||
bg_colors += [(f"{getcol(2 + (passage.position - 1) * passage_width + 2)}{max_row + 2}", (1.0, 0.7, 0.7))
|
bg_colors += [(f"{getcol(2 + (passage.position - 1) * passage_width + 2)}{max_row + 2}", (1.0, 0.7, 0.7))
|
||||||
for passage in self.passages.filter(reporter_penalties__gte=1).all()]
|
for passage in self.passages.filter(defender_penalties__gte=1).all()]
|
||||||
for bg_range, bg_color in bg_colors:
|
for bg_range, bg_color in bg_colors:
|
||||||
r, g, b = bg_color
|
r, g, b = bg_color
|
||||||
format_requests.append({
|
format_requests.append({
|
||||||
@ -1684,16 +1684,16 @@ class Passage(models.Model):
|
|||||||
)
|
)
|
||||||
|
|
||||||
solution_number = models.PositiveSmallIntegerField(
|
solution_number = models.PositiveSmallIntegerField(
|
||||||
verbose_name=_("reported solution"),
|
verbose_name=_("defended solution"),
|
||||||
choices=[
|
choices=[
|
||||||
(i, format_lazy(_("Problem #{problem}"), problem=i)) for i in range(1, len(settings.PROBLEMS) + 1)
|
(i, format_lazy(_("Problem #{problem}"), problem=i)) for i in range(1, len(settings.PROBLEMS) + 1)
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
reporter = models.ForeignKey(
|
defender = models.ForeignKey(
|
||||||
Participation,
|
Participation,
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
verbose_name=_("reporter"),
|
verbose_name=_("defender"),
|
||||||
related_name="+",
|
related_name="+",
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1721,17 +1721,17 @@ class Passage(models.Model):
|
|||||||
default=None,
|
default=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
reporter_penalties = models.PositiveSmallIntegerField(
|
defender_penalties = models.PositiveSmallIntegerField(
|
||||||
verbose_name=_("penalties"),
|
verbose_name=_("penalties"),
|
||||||
default=0,
|
default=0,
|
||||||
help_text=_("Number of penalties for the reporter. "
|
help_text=_("Number of penalties for the defender. "
|
||||||
"The reporter will loose a 0.5 coefficient per penalty."),
|
"The defender will loose a 0.5 coefficient per penalty."),
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def reported_solution(self) -> "Solution":
|
def defended_solution(self) -> "Solution":
|
||||||
return Solution.objects.get(
|
return Solution.objects.get(
|
||||||
participation=self.reporter,
|
participation=self.defender,
|
||||||
problem=self.solution_number,
|
problem=self.solution_number,
|
||||||
final_solution=self.pool.tournament.final)
|
final_solution=self.pool.tournament.final)
|
||||||
|
|
||||||
@ -1740,27 +1740,27 @@ class Passage(models.Model):
|
|||||||
return sum(items) / len(items) if items else 0
|
return sum(items) / len(items) if items else 0
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def average_reporter_writing(self) -> float:
|
def average_defender_writing(self) -> float:
|
||||||
return self.avg(note.reporter_writing for note in self.notes.all())
|
return self.avg(note.defender_writing for note in self.notes.all())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def coeff_reporter_writing(self) -> float:
|
def coeff_defender_writing(self) -> float:
|
||||||
return 1 if settings.TFJM_APP == "TFJM" else 2
|
return 1 if settings.TFJM_APP == "TFJM" else 2
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def average_reporter_oral(self) -> float:
|
def average_defender_oral(self) -> float:
|
||||||
return self.avg(note.reporter_oral for note in self.notes.all())
|
return self.avg(note.defender_oral for note in self.notes.all())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def coeff_reporter_oral(self) -> float:
|
def coeff_defender_oral(self) -> float:
|
||||||
coeff = 1.6 if settings.TFJM_APP == "TFJM" else 3
|
coeff = 1.6 if settings.TFJM_APP == "TFJM" else 3
|
||||||
coeff *= 1 - 0.25 * self.reporter_penalties
|
coeff *= 1 - 0.25 * self.defender_penalties
|
||||||
return coeff
|
return coeff
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def average_reporter(self) -> float:
|
def average_defender(self) -> float:
|
||||||
return (self.coeff_reporter_writing * self.average_reporter_writing
|
return (self.coeff_defender_writing * self.average_defender_writing
|
||||||
+ self.coeff_reporter_oral * self.average_reporter_oral)
|
+ self.coeff_defender_oral * self.average_defender_oral)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def average_opponent_writing(self) -> float:
|
def average_opponent_writing(self) -> float:
|
||||||
@ -1827,8 +1827,8 @@ class Passage(models.Model):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def averages(self):
|
def averages(self):
|
||||||
yield self.average_reporter_writing
|
yield self.average_defender_writing
|
||||||
yield self.average_reporter_oral
|
yield self.average_defender_oral
|
||||||
yield self.average_opponent_writing
|
yield self.average_opponent_writing
|
||||||
yield self.average_opponent_oral
|
yield self.average_opponent_oral
|
||||||
yield self.average_reviewer_writing
|
yield self.average_reviewer_writing
|
||||||
@ -1838,7 +1838,7 @@ class Passage(models.Model):
|
|||||||
yield self.average_observer_oral
|
yield self.average_observer_oral
|
||||||
|
|
||||||
def average(self, participation):
|
def average(self, participation):
|
||||||
avg = self.average_reporter if participation == self.reporter else self.average_opponent \
|
avg = 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 self.average_observer if participation == self.observer else 0
|
else self.average_observer if participation == self.observer else 0
|
||||||
avg *= self.pool.coeff
|
avg *= self.pool.coeff
|
||||||
@ -1849,9 +1849,9 @@ class Passage(models.Model):
|
|||||||
return reverse_lazy("participation:passage_detail", args=(self.pk,))
|
return reverse_lazy("participation:passage_detail", args=(self.pk,))
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
if self.reporter not in self.pool.participations.all():
|
if self.defender 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.reporter.team.trigram))
|
.format(trigram=self.defender.team.trigram))
|
||||||
if self.opponent not in self.pool.participations.all():
|
if self.opponent 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.opponent.team.trigram))
|
.format(trigram=self.opponent.team.trigram))
|
||||||
@ -1864,8 +1864,8 @@ class Passage(models.Model):
|
|||||||
return super().clean()
|
return super().clean()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return _("Passage of {reporter} for problem {problem}")\
|
return _("Passage of {defender} for problem {problem}")\
|
||||||
.format(reporter=self.reporter.team, problem=self.solution_number)
|
.format(defender=self.defender.team, problem=self.solution_number)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("passage")
|
verbose_name = _("passage")
|
||||||
@ -1905,12 +1905,8 @@ def get_solution_filename(instance, filename):
|
|||||||
+ ("_final" if instance.final_solution else "")
|
+ ("_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):
|
def get_synthesis_filename(instance, filename):
|
||||||
return get_review_filename(instance, filename)
|
return f"syntheses/{instance.participation.team.trigram}_{instance.type}_{instance.passage.pk}"
|
||||||
|
|
||||||
|
|
||||||
class Solution(models.Model):
|
class Solution(models.Model):
|
||||||
@ -1955,7 +1951,7 @@ class Solution(models.Model):
|
|||||||
ordering = ('participation__team__trigram', 'final_solution', 'problem',)
|
ordering = ('participation__team__trigram', 'final_solution', 'problem',)
|
||||||
|
|
||||||
|
|
||||||
class WrittenReview(models.Model):
|
class Synthesis(models.Model):
|
||||||
participation = models.ForeignKey(
|
participation = models.ForeignKey(
|
||||||
Participation,
|
Participation,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
@ -1965,7 +1961,7 @@ class WrittenReview(models.Model):
|
|||||||
passage = models.ForeignKey(
|
passage = models.ForeignKey(
|
||||||
Passage,
|
Passage,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
related_name="written_reviews",
|
related_name="syntheses",
|
||||||
verbose_name=_("passage"),
|
verbose_name=_("passage"),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1984,16 +1980,16 @@ class WrittenReview(models.Model):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return _("Written review of {team} as {type} for problem {problem} of {reporter}").format(
|
return _("Synthesis of {team} as {type} for problem {problem} of {defender}").format(
|
||||||
team=self.participation.team.trigram,
|
team=self.participation.team.trigram,
|
||||||
type=self.get_type_display(),
|
type=self.get_type_display(),
|
||||||
problem=self.passage.solution_number,
|
problem=self.passage.solution_number,
|
||||||
reporter=self.passage.reporter.team.trigram,
|
defender=self.passage.defender.team.trigram,
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("written review")
|
verbose_name = _("synthesis")
|
||||||
verbose_name_plural = _("written reviews")
|
verbose_name_plural = _("syntheses")
|
||||||
unique_together = (('participation', 'passage', 'type', ), )
|
unique_together = (('participation', 'passage', 'type', ), )
|
||||||
ordering = ('passage__pool__round', 'type',)
|
ordering = ('passage__pool__round', 'type',)
|
||||||
|
|
||||||
@ -2013,14 +2009,14 @@ class Note(models.Model):
|
|||||||
related_name="notes",
|
related_name="notes",
|
||||||
)
|
)
|
||||||
|
|
||||||
reporter_writing = models.PositiveSmallIntegerField(
|
defender_writing = models.PositiveSmallIntegerField(
|
||||||
verbose_name=_("reporter writing note"),
|
verbose_name=_("defender writing note"),
|
||||||
choices=[(i, i) for i in range(0, 21)],
|
choices=[(i, i) for i in range(0, 21)],
|
||||||
default=0,
|
default=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
reporter_oral = models.PositiveSmallIntegerField(
|
defender_oral = models.PositiveSmallIntegerField(
|
||||||
verbose_name=_("reporter oral note"),
|
verbose_name=_("defender oral note"),
|
||||||
choices=[(i, i) for i in range(0, 21)],
|
choices=[(i, i) for i in range(0, 21)],
|
||||||
default=0,
|
default=0,
|
||||||
)
|
)
|
||||||
@ -2062,8 +2058,8 @@ class Note(models.Model):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def get_all(self):
|
def get_all(self):
|
||||||
yield self.reporter_writing
|
yield self.defender_writing
|
||||||
yield self.reporter_oral
|
yield self.defender_oral
|
||||||
yield self.opponent_writing
|
yield self.opponent_writing
|
||||||
yield self.opponent_oral
|
yield self.opponent_oral
|
||||||
yield self.reviewer_writing
|
yield self.reviewer_writing
|
||||||
@ -2072,10 +2068,10 @@ class Note(models.Model):
|
|||||||
yield self.observer_writing
|
yield self.observer_writing
|
||||||
yield self.observer_oral
|
yield self.observer_oral
|
||||||
|
|
||||||
def set_all(self, reporter_writing: int, reporter_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, observer_writing: int = 0, observer_oral: int = 0):
|
||||||
self.reporter_writing = reporter_writing
|
self.defender_writing = defender_writing
|
||||||
self.reporter_oral = reporter_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
|
||||||
|
@ -108,13 +108,13 @@ class PoolTable(tables.Table):
|
|||||||
class PassageTable(tables.Table):
|
class PassageTable(tables.Table):
|
||||||
# FIXME Ne pas afficher l'équipe observatrice si non nécessaire
|
# FIXME Ne pas afficher l'équipe observatrice si non nécessaire
|
||||||
|
|
||||||
reporter = tables.LinkColumn(
|
defender = tables.LinkColumn(
|
||||||
"participation:passage_detail",
|
"participation:passage_detail",
|
||||||
args=[tables.A("id")],
|
args=[tables.A("id")],
|
||||||
verbose_name=_("reporter").capitalize,
|
verbose_name=_("defender").capitalize,
|
||||||
)
|
)
|
||||||
|
|
||||||
def render_reporter(self, value):
|
def render_defender(self, value):
|
||||||
return value.team.trigram
|
return value.team.trigram
|
||||||
|
|
||||||
def render_opponent(self, value):
|
def render_opponent(self, value):
|
||||||
@ -131,7 +131,7 @@ class PassageTable(tables.Table):
|
|||||||
'class': 'table table-condensed table-striped text-center',
|
'class': 'table table-condensed table-striped text-center',
|
||||||
}
|
}
|
||||||
model = Passage
|
model = Passage
|
||||||
fields = ('reporter', 'opponent', 'reviewer', 'observer', 'solution_number', )
|
fields = ('defender', 'opponent', 'reviewer', 'observer', 'solution_number', )
|
||||||
|
|
||||||
|
|
||||||
class NoteTable(tables.Table):
|
class NoteTable(tables.Table):
|
||||||
@ -159,5 +159,5 @@ class NoteTable(tables.Table):
|
|||||||
'class': 'table table-condensed table-striped text-center',
|
'class': 'table table-condensed table-striped text-center',
|
||||||
}
|
}
|
||||||
model = Note
|
model = Note
|
||||||
fields = ('jury', 'reporter_writing', 'reporter_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', 'observer_writing', 'observer_oral', 'update',)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<form method="post">
|
<form method="post">
|
||||||
<div id="form-content">
|
<div id="form-content">
|
||||||
<h4>{% trans "Notes of" %} {{ note.jury }}</h4>
|
<h4>{% trans "Notes of" %} {{ note.jury }}</h4>
|
||||||
<h5>{% trans "Defense of" %} {{ note.passage.reporter.team.trigram }}, {% trans "Pb." %} {{ note.passage.solution_number }}</h5>
|
<h5>{% trans "Defense of" %} {{ note.passage.defender.team.trigram }}, {% trans "Pb." %} {{ note.passage.solution_number }}</h5>
|
||||||
<hr>
|
<hr>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form|crispy }}
|
{{ form|crispy }}
|
||||||
|
@ -25,8 +25,8 @@
|
|||||||
<dt class="col-sm-3">{% trans "Position:" %}</dt>
|
<dt class="col-sm-3">{% trans "Position:" %}</dt>
|
||||||
<dd class="col-sm-9">{{ passage.position }}</dd>
|
<dd class="col-sm-9">{{ passage.position }}</dd>
|
||||||
|
|
||||||
<dt class="col-sm-3">{% trans "Reporter:" %}</dt>
|
<dt class="col-sm-3">{% trans "Defender:" %}</dt>
|
||||||
<dd class="col-sm-9"><a href="{{ passage.reporter.get_absolute_url }}">{{ passage.reporter.team }}</a></dd>
|
<dd class="col-sm-9"><a href="{{ passage.defender.get_absolute_url }}">{{ passage.defender.team }}</a></dd>
|
||||||
|
|
||||||
<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>
|
||||||
@ -39,18 +39,18 @@
|
|||||||
<dd class="col-sm-9"><a href="{{ passage.observer.get_absolute_url }}">{{ passage.observer.team }}</a></dd>
|
<dd class="col-sm-9"><a href="{{ passage.observer.get_absolute_url }}">{{ passage.observer.team }}</a></dd>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<dt class="col-sm-3">{% trans "Reported solution:" %}</dt>
|
<dt class="col-sm-3">{% trans "Defended solution:" %}</dt>
|
||||||
<dd class="col-sm-9"><a href="{{ passage.reported_solution.file.url }}">{{ passage.reported_solution }}</a></dd>
|
<dd class="col-sm-9"><a href="{{ passage.defended_solution.file.url }}">{{ passage.defended_solution }}</a></dd>
|
||||||
|
|
||||||
<dt class="col-sm-3">{% trans "Reporter penalties count:" %}</dt>
|
<dt class="col-sm-3">{% trans "Defender penalties count:" %}</dt>
|
||||||
<dd class="col-sm-9">{{ passage.reporter_penalties }}</dd>
|
<dd class="col-sm-9">{{ passage.defender_penalties }}</dd>
|
||||||
|
|
||||||
<dt class="col-sm-3">{% trans "Syntheses:" %}</dt>
|
<dt class="col-sm-3">{% trans "Syntheses:" %}</dt>
|
||||||
<dd class="col-sm-9">
|
<dd class="col-sm-9">
|
||||||
{% for review in passage.written_reviews.all %}
|
{% for synthesis in passage.syntheses.all %}
|
||||||
<a href="{{ review.file.url }}">{{ review }}{% if not forloop.last %}, {% endif %}</a>
|
<a href="{{ synthesis.file.url }}">{{ synthesis }}{% if not forloop.last %}, {% endif %}</a>
|
||||||
{% empty %}
|
{% empty %}
|
||||||
{% trans "No review was uploaded yet." %}
|
{% trans "No synthesis was uploaded yet." %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
@ -63,7 +63,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{% elif user.registration.participates %}
|
{% elif user.registration.participates %}
|
||||||
<div class="card-footer text-center">
|
<div class="card-footer text-center">
|
||||||
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#uploadWrittenReviewModal">{% trans "Upload review" %}</button>
|
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#uploadSynthesisModal">{% trans "Upload synthesis" %}</button>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
@ -79,19 +79,19 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<dl class="row">
|
<dl class="row">
|
||||||
<dt class="col-sm-8">
|
<dt class="col-sm-8">
|
||||||
{% trans "Average points for the reporter writing" %}
|
{% trans "Average points for the defender writing" %}
|
||||||
({{ passage.reporter.team.trigram }}) :
|
({{ passage.defender.team.trigram }}) :
|
||||||
</dt>
|
</dt>
|
||||||
<dd class="col-sm-4">
|
<dd class="col-sm-4">
|
||||||
{{ passage.average_reporter_writing|floatformat }}/{% if TFJM_APP == "TFJM" %}20{% else %}10{% endif %}
|
{{ passage.average_defender_writing|floatformat }}/{% if TFJM_APP == "TFJM" %}20{% else %}10{% endif %}
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt class="col-sm-8">
|
<dt class="col-sm-8">
|
||||||
{% trans "Average points for the reporter oral" %}
|
{% trans "Average points for the defender oral" %}
|
||||||
({{ passage.reporter.team.trigram }}) :
|
({{ passage.defender.team.trigram }}) :
|
||||||
</dt>
|
</dt>
|
||||||
<dd class="col-sm-4">
|
<dd class="col-sm-4">
|
||||||
{{ passage.average_reporter_oral|floatformat }}/{% if TFJM_APP == "TFJM" %}20{% else %}10{% endif %}
|
{{ passage.average_defender_oral|floatformat }}/{% if TFJM_APP == "TFJM" %}20{% else %}10{% endif %}
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt class="col-sm-8">
|
<dt class="col-sm-8">
|
||||||
@ -137,11 +137,11 @@
|
|||||||
|
|
||||||
<dl class="row">
|
<dl class="row">
|
||||||
<dt class="col-sm-8">
|
<dt class="col-sm-8">
|
||||||
{% trans "Reporter points" %}
|
{% trans "Defender points" %}
|
||||||
({{ passage.reporter.team.trigram }}) :
|
({{ passage.defender.team.trigram }}) :
|
||||||
</dt>
|
</dt>
|
||||||
<dd class="col-sm-4">
|
<dd class="col-sm-4">
|
||||||
{{ passage.average_reporter|floatformat }}/{% if TFJM_APP == "TFJM" %}52{% else %}50{% endif %}
|
{{ passage.average_defender|floatformat }}/{% if TFJM_APP == "TFJM" %}52{% else %}50{% endif %}
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt class="col-sm-8">
|
<dt class="col-sm-8">
|
||||||
@ -184,10 +184,10 @@
|
|||||||
{% include "base_modal.html" with modal_id=note.modal_name %}
|
{% include "base_modal.html" with modal_id=note.modal_name %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% elif user.registration.participates %}
|
{% elif user.registration.participates %}
|
||||||
{% trans "Upload review" as modal_title %}
|
{% trans "Upload synthesis" as modal_title %}
|
||||||
{% trans "Upload" as modal_button %}
|
{% trans "Upload" as modal_button %}
|
||||||
{% url "participation:upload_review" pk=passage.pk as modal_action %}
|
{% url "participation:upload_synthesis" pk=passage.pk as modal_action %}
|
||||||
{% include "base_modal.html" with modal_id="uploadWrittenReview" modal_enctype="multipart/form-data" %}
|
{% include "base_modal.html" with modal_id="uploadSynthesis" modal_enctype="multipart/form-data" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
@ -201,8 +201,8 @@
|
|||||||
initModal("{{ note.modal_name }}", "{% url "participation:update_notes" pk=note.pk %}")
|
initModal("{{ note.modal_name }}", "{% url "participation:update_notes" pk=note.pk %}")
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% elif user.registration.participates %}
|
{% elif user.registration.participates %}
|
||||||
initModal("uploadWrittenReview", "{% url "participation:upload_review" pk=passage.pk %}")
|
initModal("uploadSynthesis", "{% url "participation:upload_synthesis" pk=passage.pk %}")
|
||||||
{% endif %}
|
{% endif %}
|
||||||
})
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -46,10 +46,10 @@
|
|||||||
</a>
|
</a>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt class="col-sm-3">{% trans "Reported solutions:" %}</dt>
|
<dt class="col-sm-3">{% trans "Defended solutions:" %}</dt>
|
||||||
<dd class="col-sm-9">
|
<dd class="col-sm-9">
|
||||||
{% for passage in pool.passages.all %}
|
{% for passage in pool.passages.all %}
|
||||||
<a href="{{ passage.reported_solution.file.url }}">{{ passage.reporter.team.trigram }} — {{ passage.get_solution_number_display }}</a>{% if not forloop.last %}, {% endif %}
|
<a href="{{ passage.defended_solution.file.url }}">{{ passage.defender.team.trigram }} — {{ passage.get_solution_number_display }}</a>{% if not forloop.last %}, {% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<a href="{% url 'participation:pool_download_solutions' pool_id=pool.id %}" class="badge rounded-pill text-bg-secondary">
|
<a href="{% url 'participation:pool_download_solutions' pool_id=pool.id %}" class="badge rounded-pill text-bg-secondary">
|
||||||
<i class="fas fa-download"></i> {% trans "Download all" %}
|
<i class="fas fa-download"></i> {% trans "Download all" %}
|
||||||
@ -61,16 +61,16 @@
|
|||||||
<ul class="list-group list-group-flush">
|
<ul class="list-group list-group-flush">
|
||||||
{% for passage in pool.passages.all %}
|
{% for passage in pool.passages.all %}
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
{{ passage.reporter.team.trigram }} — {{ passage.get_solution_number_display }} :
|
{{ passage.defender.team.trigram }} — {{ passage.get_solution_number_display }} :
|
||||||
{% for review in passage.written_reviews.all %}
|
{% for synthesis in passage.syntheses.all %}
|
||||||
<a href="{{ review.file.url }}">{{ review.participation.team.trigram }} ({{ review.get_type_display }})</a>{% if not forloop.last %}, {% endif %}
|
<a href="{{ synthesis.file.url }}">{{ synthesis.participation.team.trigram }} ({{ synthesis.get_type_display }})</a>{% if not forloop.last %}, {% endif %}
|
||||||
{% empty %}
|
{% empty %}
|
||||||
{% trans "No review was uploaded yet." %}
|
{% trans "No synthesis was uploaded yet." %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
<a href="{% url 'participation:pool_download_written_reviews' pool_id=pool.id %}" class="badge rounded-pill text-bg-secondary">
|
<a href="{% url 'participation:pool_download_syntheses' pool_id=pool.id %}" class="badge rounded-pill text-bg-secondary">
|
||||||
<i class="fas fa-download"></i> {% trans "Download all" %}
|
<i class="fas fa-download"></i> {% trans "Download all" %}
|
||||||
</a>
|
</a>
|
||||||
</dd>
|
</dd>
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
{% for passage in passages.all %}
|
{% for passage in passages.all %}
|
||||||
\item D\'efenseur\textperiodcentered{}se au passage {{ forloop.counter }} : \underline{\texttt{~{{ passage.reporter.team.trigram }}~}} $\qquad$ probl\`eme \underline{~{{ passage.solution_number }}~}
|
\item D\'efenseur\textperiodcentered{}se au passage {{ forloop.counter }} : \underline{\texttt{~{{ passage.defender.team.trigram }}~}} $\qquad$ probl\`eme \underline{~{{ passage.solution_number }}~}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
\end{center}
|
\end{center}
|
||||||
@ -50,7 +50,7 @@
|
|||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%DEFENSEUR
|
%%%%%%%%%%%%%%%%%%%%%DEFENSEUR
|
||||||
\begin{tabular}{|c|p{24mm}|p{11cm}|c|{% for passage in passages.all %}p{2cm}|{% endfor %}}\hline
|
\begin{tabular}{|c|p{24mm}|p{11cm}|c|{% for passage in passages.all %}p{2cm}|{% endfor %}}\hline
|
||||||
\multicolumn{4}{|l|}{Læ {\bf D\'efenseur\textperiodcentered{}se} \normalsize pr\'esente les id\'ees et r\'esultats principaux pour la solution du probl\`eme.} {% for passage in passages.all %}& P.{{ forloop.counter }} - {{ passage.reporter.team.trigram }} {% endfor %}\\ \hline \hline
|
\multicolumn{4}{|l|}{Læ {\bf D\'efenseur\textperiodcentered{}se} \normalsize pr\'esente les id\'ees et r\'esultats principaux pour la solution du probl\`eme.} {% for passage in passages.all %}& P.{{ forloop.counter }} - {{ passage.defender.team.trigram }} {% endfor %}\\ \hline \hline
|
||||||
|
|
||||||
%ECRIT
|
%ECRIT
|
||||||
\multirow{6}{3mm}{\centering \bf\'E\\ C\\ R\\ I\\ T} & \multirow{3}{20mm}{Partie scientifique} & Profondeur et difficulté des éléments présentés & [0,6] {{ esp|safe }}\\ \cline{3-{{ passages.count|add:4 }}}
|
\multirow{6}{3mm}{\centering \bf\'E\\ C\\ R\\ I\\ T} & \multirow{3}{20mm}{Partie scientifique} & Profondeur et difficulté des éléments présentés & [0,6] {{ esp|safe }}\\ \cline{3-{{ passages.count|add:4 }}}
|
||||||
|
@ -46,7 +46,7 @@ Tour {{ pool.round }} \;-- Poule {{ pool.get_letter_display }}{% if pool.partici
|
|||||||
\begin{tabular}{|p{40mm}{% for passage in passages.all %}{% if passages.count == 3 %}|p{3cm}|p{3cm}{% else %}|p{2.5cm}|p{2.5cm}{% endif %}{% endfor %}|}\hline
|
\begin{tabular}{|p{40mm}{% for passage in passages.all %}{% if passages.count == 3 %}|p{3cm}|p{3cm}{% else %}|p{2.5cm}|p{2.5cm}{% endif %}{% endfor %}|}\hline
|
||||||
\multirow{2}{40mm}{\LARGE R\^ole} {% for passage in passages.all %}& \multicolumn{2}{c|}{ \Large Probl\`eme {{ passage.solution_number }}}{% endfor %} \\ \cline{2-{{ passages.count|add:passages.count|add:1 }}}
|
\multirow{2}{40mm}{\LARGE R\^ole} {% for passage in passages.all %}& \multicolumn{2}{c|}{ \Large Probl\`eme {{ passage.solution_number }}}{% endfor %} \\ \cline{2-{{ passages.count|add:passages.count|add:1 }}}
|
||||||
{% for passage in passages.all %}& \hspace{4mm} {\Large \'ECRIT} & \hspace{4mm} {\Large ORAL}{% endfor %} \\ \hline
|
{% for passage in passages.all %}& \hspace{4mm} {\Large \'ECRIT} & \hspace{4mm} {\Large ORAL}{% endfor %} \\ \hline
|
||||||
\multirow{2}{35mm}{\LARGE D\'efenseur\textperiodcentered{}se} {% for passage in passages.all %}& \multicolumn{2}{c|}{\Large {{ passage.reporter.team.trigram }}}{% endfor %} \\ \cline{2-{{ passages.count|add:passages.count|add:1 }}}
|
\multirow{2}{35mm}{\LARGE D\'efenseur\textperiodcentered{}se} {% for passage in passages.all %}& \multicolumn{2}{c|}{\Large {{ passage.defender.team.trigram }}}{% endfor %} \\ \cline{2-{{ passages.count|add:passages.count|add:1 }}}
|
||||||
{% for passage in passages.all %}
|
{% for passage in passages.all %}
|
||||||
& \phantom{asd asd} \phantom{asd asd} \centering \normalsize$0\leq x\leq 20$
|
& \phantom{asd asd} \phantom{asd asd} \centering \normalsize$0\leq x\leq 20$
|
||||||
& \phantom{asd asd} \phantom{asd asd} \centering \normalsize$0\leq x\leq 20$
|
& \phantom{asd asd} \phantom{asd asd} \centering \normalsize$0\leq x\leq 20$
|
||||||
|
@ -38,15 +38,15 @@
|
|||||||
<dt class="col-sm-6 text-sm-end">{% trans 'date of the random draw'|capfirst %}</dt>
|
<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>
|
<dd class="col-sm-6">{{ tournament.solutions_draw }}</dd>
|
||||||
|
|
||||||
<dt class="col-sm-6 text-sm-end">{% trans 'date of maximal written reviews submission for the first round'|capfirst %}</dt>
|
<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.reviews_first_phase_limit }}</dd>
|
<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 second round'|capfirst %}</dt>
|
<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.reviews_second_phase_limit }}</dd>
|
<dd class="col-sm-6">{{ tournament.syntheses_second_phase_limit }}</dd>
|
||||||
|
|
||||||
{% if TFJM.APP == "ETEAM" %}
|
{% if TFJM.APP == "ETEAM" %}
|
||||||
<dt class="col-sm-6 text-sm-end">{% trans 'date of maximal written reviews submission for the third round'|capfirst %}</dt>
|
<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.reviews_third_phase_limit }}</dd>
|
<dd class="col-sm-6">{{ tournament.syntheses_third_phase_limit }}</dd>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<dt class="col-sm-6 text-sm-end">{% trans 'description'|capfirst %}</dt>
|
<dt class="col-sm-6 text-sm-end">{% trans 'description'|capfirst %}</dt>
|
||||||
@ -233,48 +233,48 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url "participation:tournament_csv" pk=tournament.pk %}">
|
<a href="{% url "participation:tournament_csv" pk=tournament.pk %}">
|
||||||
{% trans "Validated team participant data spreadsheet" %}
|
Validated team participant data spreadsheet
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url "participation:tournament_csv" pk=tournament.pk %}?all">
|
<a href="{% url "participation:tournament_csv" pk=tournament.pk %}?all">
|
||||||
{% trans "All teams participant data spreadsheet" %}
|
All teams participant data spreadsheet
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url "participation:tournament_authorizations" tournament_id=tournament.id %}">
|
<a href="{% url "participation:tournament_authorizations" tournament_id=tournament.id %}">
|
||||||
{% trans "Archive of all authorisations sorted by team and person" %}
|
Archive of all authorisations sorted by team and person
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url "participation:tournament_solutions" tournament_id=tournament.id %}">
|
<a href="{% url "participation:tournament_solutions" tournament_id=tournament.id %}">
|
||||||
{% trans "Archive of all submitted solutions sorted by team" %}
|
Archive of all submitted solutions sorted by team
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url "participation:tournament_solutions" tournament_id=tournament.id %}?sort_by=problem">
|
<a href="{% url "participation:tournament_solutions" tournament_id=tournament.id %}?sort_by=problem">
|
||||||
{% trans "Archive of all sent solutions sorted by problem" %}
|
Archive of all sent solutions sorted by problem
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url "participation:tournament_solutions" tournament_id=tournament.id %}?sort_by=pool">
|
<a href="{% url "participation:tournament_solutions" tournament_id=tournament.id %}?sort_by=pool">
|
||||||
{% trans "Archive of all sent solutions sorted by pool" %}
|
Archive of all sent solutions sorted by pool
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url "participation:tournament_written_reviews" tournament_id=tournament.id %}?sort_by=pool">
|
<a href="{% url "participation:tournament_syntheses" tournament_id=tournament.id %}?sort_by=pool">
|
||||||
{% trans "Archive of all summary notes sorted by pool and passage" %}
|
Archive of all summary notes sorted by pool and passage
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="https://docs.google.com/spreadsheets/d/{{ tournament.notes_sheet_id }}/edit">
|
<a href="https://docs.google.com/spreadsheets/d/{{ tournament.notes_sheet_id }}/edit">
|
||||||
<i class="fas fa-table"></i>
|
<i class="fas fa-table"></i>
|
||||||
{% trans "Note spreadsheet on Google Sheets" %}
|
Note spreadsheet on Google Sheets
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url "participation:tournament_notation_sheets" tournament_id=tournament.id %}">
|
<a href="{% url "participation:tournament_notation_sheets" tournament_id=tournament.id %}">
|
||||||
{% trans "Archive of all printable note sheets sorted by pool" %}
|
Archive of all printable note sheets sorted by pool
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -8,11 +8,11 @@ from .views import CreateTeamView, FinalNotationSheetTemplateView, GSheetNotific
|
|||||||
PassageDetailView, PassageUpdateView, PoolCreateView, PoolDetailView, PoolJuryView, PoolNotesTemplateView, \
|
PassageDetailView, PassageUpdateView, PoolCreateView, PoolDetailView, PoolJuryView, PoolNotesTemplateView, \
|
||||||
PoolPresideJuryView, PoolRemoveJuryView, PoolUpdateView, PoolUploadNotesView, \
|
PoolPresideJuryView, PoolRemoveJuryView, PoolUpdateView, PoolUploadNotesView, \
|
||||||
ScaleNotationSheetTemplateView, SelectTeamFinalView, \
|
ScaleNotationSheetTemplateView, SelectTeamFinalView, \
|
||||||
SolutionsDownloadView, SolutionUploadView, \
|
SolutionsDownloadView, SolutionUploadView, SynthesisUploadView, \
|
||||||
TeamAuthorizationsView, TeamDetailView, TeamLeaveView, TeamListView, TeamUpdateView, \
|
TeamAuthorizationsView, TeamDetailView, TeamLeaveView, TeamListView, TeamUpdateView, \
|
||||||
TeamUploadMotivationLetterView, TournamentCreateView, TournamentDetailView, TournamentExportCSVView, \
|
TeamUploadMotivationLetterView, TournamentCreateView, TournamentDetailView, TournamentExportCSVView, \
|
||||||
TournamentHarmonizeNoteView, TournamentHarmonizeView, TournamentListView, TournamentPaymentsView, \
|
TournamentHarmonizeNoteView, TournamentHarmonizeView, TournamentListView, TournamentPaymentsView, \
|
||||||
TournamentPublishNotesView, TournamentUpdateView, WrittenReviewUploadView
|
TournamentPublishNotesView, TournamentUpdateView
|
||||||
|
|
||||||
|
|
||||||
app_name = "participation"
|
app_name = "participation"
|
||||||
@ -42,8 +42,8 @@ urlpatterns = [
|
|||||||
name="tournament_authorizations"),
|
name="tournament_authorizations"),
|
||||||
path("tournament/<int:tournament_id>/solutions/", SolutionsDownloadView.as_view(),
|
path("tournament/<int:tournament_id>/solutions/", SolutionsDownloadView.as_view(),
|
||||||
name="tournament_solutions"),
|
name="tournament_solutions"),
|
||||||
path("tournament/<int:tournament_id>/written_reviews/", SolutionsDownloadView.as_view(),
|
path("tournament/<int:tournament_id>/syntheses/", SolutionsDownloadView.as_view(),
|
||||||
name="tournament_written_reviews"),
|
name="tournament_syntheses"),
|
||||||
path("tournament/<int:tournament_id>/notation/sheets/", NotationSheetsArchiveView.as_view(),
|
path("tournament/<int:tournament_id>/notation/sheets/", NotationSheetsArchiveView.as_view(),
|
||||||
name="tournament_notation_sheets"),
|
name="tournament_notation_sheets"),
|
||||||
path("tournament/<int:pk>/notation/notifications/", GSheetNotificationsView.as_view(),
|
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>/", PoolDetailView.as_view(), name="pool_detail"),
|
||||||
path("pools/<int:pk>/update/", PoolUpdateView.as_view(), name="pool_update"),
|
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>/solutions/", SolutionsDownloadView.as_view(), name="pool_download_solutions"),
|
||||||
path("pools/<int:pool_id>/written_reviews/", SolutionsDownloadView.as_view(), name="pool_download_written_reviews"),
|
path("pools/<int:pool_id>/syntheses/", SolutionsDownloadView.as_view(), name="pool_download_syntheses"),
|
||||||
path("pools/<int:pk>/notation/scale/", ScaleNotationSheetTemplateView.as_view(), name="pool_scale_note_sheet"),
|
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: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"),
|
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/<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>/", PassageDetailView.as_view(), name="passage_detail"),
|
||||||
path("pools/passages/<int:pk>/update/", PassageUpdateView.as_view(), name="passage_update"),
|
path("pools/passages/<int:pk>/update/", PassageUpdateView.as_view(), name="passage_update"),
|
||||||
path("pools/passages/<int:pk>/written_review/", WrittenReviewUploadView.as_view(), name="upload_written_review"),
|
path("pools/passages/<int:pk>/solution/", SynthesisUploadView.as_view(), name="upload_synthesis"),
|
||||||
path("pools/passages/notes/<int:pk>/", NoteUpdateView.as_view(), name="update_notes"),
|
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 tfjm.views import AdminMixin, VolunteerMixin
|
||||||
|
|
||||||
from .forms import AddJuryForm, JoinTeamForm, MotivationLetterForm, NoteForm, ParticipationForm, PassageForm, \
|
from .forms import AddJuryForm, JoinTeamForm, MotivationLetterForm, NoteForm, ParticipationForm, PassageForm, \
|
||||||
PoolForm, RequestValidationForm, SolutionForm, TeamForm, TournamentForm, UploadNotesForm, \
|
PoolForm, RequestValidationForm, SolutionForm, SynthesisForm, TeamForm, TournamentForm, \
|
||||||
ValidateParticipationForm, WrittenReviewForm
|
UploadNotesForm, ValidateParticipationForm
|
||||||
from .models import Note, Participation, Passage, Pool, Solution, Team, Tournament, Tweak, WrittenReview
|
from .models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament, Tweak
|
||||||
from .tables import NoteTable, ParticipationTable, PassageTable, PoolTable, TeamTable, TournamentTable
|
from .tables import NoteTable, ParticipationTable, PassageTable, PoolTable, TeamTable, TournamentTable
|
||||||
|
|
||||||
|
|
||||||
@ -977,7 +977,7 @@ class PoolUpdateView(VolunteerMixin, UpdateView):
|
|||||||
|
|
||||||
class SolutionsDownloadView(VolunteerMixin, View):
|
class SolutionsDownloadView(VolunteerMixin, View):
|
||||||
"""
|
"""
|
||||||
Download all solutions or written reviews as a ZIP archive.
|
Download all solutions or syntheses as a ZIP archive.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
@ -1018,12 +1018,11 @@ class SolutionsDownloadView(VolunteerMixin, View):
|
|||||||
if 'team_id' in kwargs:
|
if 'team_id' in kwargs:
|
||||||
team = Team.objects.get(pk=kwargs["team_id"])
|
team = Team.objects.get(pk=kwargs["team_id"])
|
||||||
solutions = Solution.objects.filter(participation=team.participation).all()
|
solutions = Solution.objects.filter(participation=team.participation).all()
|
||||||
written_reviews = WrittenReview.objects.filter(participation=team.participation).all()
|
syntheses = Synthesis.objects.filter(participation=team.participation).all()
|
||||||
filename = _("Solutions of team {trigram}.zip") if is_solution \
|
filename = _("Solutions of team {trigram}.zip") if is_solution else _("Syntheses of team {trigram}.zip")
|
||||||
else _("Written reviews of team {trigram}.zip")
|
|
||||||
filename = filename.format(trigram=team.trigram)
|
filename = filename.format(trigram=team.trigram)
|
||||||
|
|
||||||
def prefix(s: Solution | WrittenReview) -> str:
|
def prefix(s: Solution | Synthesis) -> str:
|
||||||
return ""
|
return ""
|
||||||
elif 'tournament_id' in kwargs:
|
elif 'tournament_id' in kwargs:
|
||||||
tournament = Tournament.objects.get(pk=kwargs["tournament_id"])
|
tournament = Tournament.objects.get(pk=kwargs["tournament_id"])
|
||||||
@ -1036,12 +1035,11 @@ class SolutionsDownloadView(VolunteerMixin, View):
|
|||||||
for sol in pool.solutions:
|
for sol in pool.solutions:
|
||||||
sol.pool = pool
|
sol.pool = pool
|
||||||
solutions.append(sol)
|
solutions.append(sol)
|
||||||
written_reviews = WrittenReview.objects.filter(passage__pool__tournament=tournament).all()
|
syntheses = Synthesis.objects.filter(passage__pool__tournament=tournament).all()
|
||||||
filename = _("Solutions of {tournament}.zip") if is_solution \
|
filename = _("Solutions of {tournament}.zip") if is_solution else _("Syntheses of {tournament}.zip")
|
||||||
else _("Written reviews of {tournament}.zip")
|
|
||||||
filename = filename.format(tournament=tournament.name)
|
filename = filename.format(tournament=tournament.name)
|
||||||
|
|
||||||
def prefix(s: Solution | WrittenReview) -> str:
|
def prefix(s: Solution | Synthesis) -> str:
|
||||||
pool = s.pool if is_solution else s.passage.pool
|
pool = s.pool if is_solution else s.passage.pool
|
||||||
p = f"Poule {pool.short_name}/"
|
p = f"Poule {pool.short_name}/"
|
||||||
if not is_solution:
|
if not is_solution:
|
||||||
@ -1052,28 +1050,27 @@ class SolutionsDownloadView(VolunteerMixin, View):
|
|||||||
solutions = Solution.objects.filter(participation__tournament=tournament).all()
|
solutions = Solution.objects.filter(participation__tournament=tournament).all()
|
||||||
else:
|
else:
|
||||||
solutions = Solution.objects.filter(final_solution=True).all()
|
solutions = Solution.objects.filter(final_solution=True).all()
|
||||||
written_reviews = WrittenReview.objects.filter(passage__pool__tournament=tournament).all()
|
syntheses = Synthesis.objects.filter(passage__pool__tournament=tournament).all()
|
||||||
filename = _("Solutions of {tournament}.zip") if is_solution \
|
filename = _("Solutions of {tournament}.zip") if is_solution else _("Syntheses of {tournament}.zip")
|
||||||
else _("Written reviews of {tournament}.zip")
|
|
||||||
filename = filename.format(tournament=tournament.name)
|
filename = filename.format(tournament=tournament.name)
|
||||||
|
|
||||||
def prefix(s: Solution | WrittenReview) -> str:
|
def prefix(s: Solution | Synthesis) -> str:
|
||||||
return f"{s.participation.team.trigram}/" if sort_by == "team" else f"Problème {s.problem}/"
|
return f"{s.participation.team.trigram}/" if sort_by == "team" else f"Problème {s.problem}/"
|
||||||
else:
|
else:
|
||||||
pool = Pool.objects.get(pk=kwargs["pool_id"])
|
pool = Pool.objects.get(pk=kwargs["pool_id"])
|
||||||
solutions = pool.solutions
|
solutions = pool.solutions
|
||||||
written_reviews = WrittenReview.objects.filter(passage__pool=pool).all()
|
syntheses = Synthesis.objects.filter(passage__pool=pool).all()
|
||||||
filename = _("Solutions for pool {pool} of tournament {tournament}.zip") \
|
filename = _("Solutions for pool {pool} of tournament {tournament}.zip") \
|
||||||
if is_solution else _("Written reviews for pool {pool} of tournament {tournament}.zip")
|
if is_solution else _("Syntheses for pool {pool} of tournament {tournament}.zip")
|
||||||
filename = filename.format(pool=pool.short_name,
|
filename = filename.format(pool=pool.short_name,
|
||||||
tournament=pool.tournament.name)
|
tournament=pool.tournament.name)
|
||||||
|
|
||||||
def prefix(s: Solution | WrittenReview) -> str:
|
def prefix(s: Solution | Synthesis) -> str:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
output = BytesIO()
|
output = BytesIO()
|
||||||
zf = ZipFile(output, "w")
|
zf = ZipFile(output, "w")
|
||||||
for s in (solutions if is_solution else written_reviews):
|
for s in (solutions if is_solution else syntheses):
|
||||||
if s.file.storage.exists(s.file.path):
|
if s.file.storage.exists(s.file.path):
|
||||||
zf.write("media/" + s.file.name, prefix(s) + f"{s}.pdf")
|
zf.write("media/" + s.file.name, prefix(s) + f"{s}.pdf")
|
||||||
|
|
||||||
@ -1503,10 +1500,10 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
header_role.addElement(role_tc)
|
header_role.addElement(role_tc)
|
||||||
header_role.addElement(CoveredTableCell())
|
header_role.addElement(CoveredTableCell())
|
||||||
for i in range(pool_size):
|
for i in range(pool_size):
|
||||||
reporter_tc = TableCell(valuetype="string", stylename=title_style_left)
|
defender_tc = TableCell(valuetype="string", stylename=title_style_left)
|
||||||
reporter_tc.addElement(P(text=_("Reporter")))
|
defender_tc.addElement(P(text=_("Defender")))
|
||||||
reporter_tc.setAttribute('numbercolumnsspanned', "2")
|
defender_tc.setAttribute('numbercolumnsspanned', "2")
|
||||||
header_role.addElement(reporter_tc)
|
header_role.addElement(defender_tc)
|
||||||
header_role.addElement(CoveredTableCell())
|
header_role.addElement(CoveredTableCell())
|
||||||
|
|
||||||
opponent_tc = TableCell(valuetype="string", stylename=title_style)
|
opponent_tc = TableCell(valuetype="string", stylename=title_style)
|
||||||
@ -1539,13 +1536,13 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
header_notes.addElement(CoveredTableCell())
|
header_notes.addElement(CoveredTableCell())
|
||||||
|
|
||||||
for i in range(pool_size):
|
for i in range(pool_size):
|
||||||
reporter_w_tc = TableCell(valuetype="string", stylename=title_style_botleft)
|
defender_w_tc = TableCell(valuetype="string", stylename=title_style_botleft)
|
||||||
reporter_w_tc.addElement(P(text=f"{_('Writing')} (/{20 if settings.TFJM_APP == 'TFJM' else 10})"))
|
defender_w_tc.addElement(P(text=f"{_('Writing')} (/{20 if settings.TFJM_APP == 'TFJM' else 10})"))
|
||||||
header_notes.addElement(reporter_w_tc)
|
header_notes.addElement(defender_w_tc)
|
||||||
|
|
||||||
reporter_o_tc = TableCell(valuetype="string", stylename=title_style_bot)
|
defender_o_tc = TableCell(valuetype="string", stylename=title_style_bot)
|
||||||
reporter_o_tc.addElement(P(text=f"{_('Oral')} (/{20 if settings.TFJM_APP == 'TFJM' else 10})"))
|
defender_o_tc.addElement(P(text=f"{_('Oral')} (/{20 if settings.TFJM_APP == 'TFJM' else 10})"))
|
||||||
header_notes.addElement(reporter_o_tc)
|
header_notes.addElement(defender_o_tc)
|
||||||
|
|
||||||
opponent_w_tc = TableCell(valuetype="string", stylename=title_style_bot)
|
opponent_w_tc = TableCell(valuetype="string", stylename=title_style_bot)
|
||||||
opponent_w_tc.addElement(P(text=f"{_('Writing')} (/10)"))
|
opponent_w_tc.addElement(P(text=f"{_('Writing')} (/10)"))
|
||||||
@ -1626,13 +1623,13 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
coeff_row.addElement(coeff_tc)
|
coeff_row.addElement(coeff_tc)
|
||||||
coeff_row.addElement(CoveredTableCell())
|
coeff_row.addElement(CoveredTableCell())
|
||||||
for passage in self.object.passages.all():
|
for passage in self.object.passages.all():
|
||||||
reporter_w_tc = TableCell(valuetype="float", value=passage.coeff_reporter_writing, stylename=style_left)
|
defender_w_tc = TableCell(valuetype="float", value=passage.coeff_defender_writing, stylename=style_left)
|
||||||
reporter_w_tc.addElement(P(text=str(passage.coeff_reporter_writing)))
|
defender_w_tc.addElement(P(text=str(passage.coeff_defender_writing)))
|
||||||
coeff_row.addElement(reporter_w_tc)
|
coeff_row.addElement(defender_w_tc)
|
||||||
|
|
||||||
reporter_o_tc = TableCell(valuetype="float", value=passage.coeff_reporter_oral, stylename=style)
|
defender_o_tc = TableCell(valuetype="float", value=passage.coeff_defender_oral, stylename=style)
|
||||||
reporter_o_tc.addElement(P(text=str(passage.coeff_reporter_oral)))
|
defender_o_tc.addElement(P(text=str(passage.coeff_defender_oral)))
|
||||||
coeff_row.addElement(reporter_o_tc)
|
coeff_row.addElement(defender_o_tc)
|
||||||
|
|
||||||
opponent_w_tc = TableCell(valuetype="float", value=passage.coeff_opponent_writing, stylename=style)
|
opponent_w_tc = TableCell(valuetype="float", value=passage.coeff_opponent_writing, stylename=style)
|
||||||
opponent_w_tc.addElement(P(text=str(passage.coeff_opponent_writing)))
|
opponent_w_tc.addElement(P(text=str(passage.coeff_opponent_writing)))
|
||||||
@ -1671,12 +1668,12 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
for i, passage in enumerate(self.object.passages.all()):
|
for i, passage in enumerate(self.object.passages.all()):
|
||||||
def_w_col = getcol(min_column + passage_width * i)
|
def_w_col = getcol(min_column + passage_width * i)
|
||||||
def_o_col = getcol(min_column + passage_width * i + 1)
|
def_o_col = getcol(min_column + passage_width * i + 1)
|
||||||
reporter_tc = TableCell(valuetype="float", value=passage.average_reporter, stylename=style_botleft)
|
defender_tc = TableCell(valuetype="float", value=passage.average_defender, stylename=style_botleft)
|
||||||
reporter_tc.addElement(P(text=str(passage.average_reporter)))
|
defender_tc.addElement(P(text=str(passage.average_defender)))
|
||||||
reporter_tc.setAttribute('numbercolumnsspanned', "2")
|
defender_tc.setAttribute('numbercolumnsspanned', "2")
|
||||||
reporter_tc.setAttribute("formula", f"of:=[.{def_w_col}{max_row + 1}] * [.{def_w_col}{max_row + 2}]"
|
defender_tc.setAttribute("formula", f"of:=[.{def_w_col}{max_row + 1}] * [.{def_w_col}{max_row + 2}]"
|
||||||
f" + [.{def_o_col}{max_row + 1}] * [.{def_o_col}{max_row + 2}]")
|
f" + [.{def_o_col}{max_row + 1}] * [.{def_o_col}{max_row + 2}]")
|
||||||
subtotal_row.addElement(reporter_tc)
|
subtotal_row.addElement(defender_tc)
|
||||||
subtotal_row.addElement(CoveredTableCell())
|
subtotal_row.addElement(CoveredTableCell())
|
||||||
|
|
||||||
opp_w_col = getcol(min_column + passage_width * i + 2)
|
opp_w_col = getcol(min_column + passage_width * i + 2)
|
||||||
@ -1748,7 +1745,7 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
|
|
||||||
team_tc = TableCell(valuetype="string",
|
team_tc = TableCell(valuetype="string",
|
||||||
stylename=style_botleft if passage.position == pool_size else style_left)
|
stylename=style_botleft if passage.position == pool_size else style_left)
|
||||||
team_tc.addElement(P(text=f"{passage.reporter.team.name} ({passage.reporter.team.trigram})"))
|
team_tc.addElement(P(text=f"{passage.defender.team.name} ({passage.defender.team.trigram})"))
|
||||||
team_tc.setAttribute('numbercolumnsspanned', "2")
|
team_tc.setAttribute('numbercolumnsspanned', "2")
|
||||||
team_row.addElement(team_tc)
|
team_row.addElement(team_tc)
|
||||||
|
|
||||||
@ -1758,17 +1755,17 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
problem_tc.setAttribute("formula", f"of:=[.B{3 + passage_width * (passage.position - 1)}]")
|
problem_tc.setAttribute("formula", f"of:=[.B{3 + passage_width * (passage.position - 1)}]")
|
||||||
team_row.addElement(problem_tc)
|
team_row.addElement(problem_tc)
|
||||||
|
|
||||||
reporter_pos = passage.position - 1
|
defender_pos = passage.position - 1
|
||||||
opponent_pos = self.object.passages.get(opponent=passage.reporter).position - 1
|
opponent_pos = self.object.passages.get(opponent=passage.defender).position - 1
|
||||||
reviewer_pos = self.object.passages.get(reviewer=passage.reporter).position - 1
|
reviewer_pos = self.object.passages.get(reviewer=passage.defender).position - 1
|
||||||
observer_pos = self.object.passages.get(observer=passage.reporter).position - 1 \
|
observer_pos = self.object.passages.get(observer=passage.defender).position - 1 \
|
||||||
if has_observer else None
|
if has_observer else None
|
||||||
|
|
||||||
score_tc = TableCell(valuetype="float", value=self.object.average(passage.reporter),
|
score_tc = TableCell(valuetype="float", value=self.object.average(passage.defender),
|
||||||
stylename=style_bot if passage.position == pool_size else style)
|
stylename=style_bot if passage.position == pool_size else style)
|
||||||
score_tc.addElement(P(text=self.object.average(passage.reporter)))
|
score_tc.addElement(P(text=self.object.average(passage.defender)))
|
||||||
formula = "of:="
|
formula = "of:="
|
||||||
formula += getcol(min_column + reporter_pos * passage_width) + str(max_row + 3) # Reporter
|
formula += getcol(min_column + defender_pos * passage_width) + str(max_row + 3) # Defender
|
||||||
formula += " + " + getcol(min_column + opponent_pos * passage_width + 2) + str(max_row + 3) # Opponent
|
formula += " + " + getcol(min_column + opponent_pos * passage_width + 2) + str(max_row + 3) # Opponent
|
||||||
formula += " + " + getcol(min_column + reviewer_pos * passage_width + 4) + str(max_row + 3) # Reviewer
|
formula += " + " + getcol(min_column + reviewer_pos * passage_width + 4) + str(max_row + 3) # Reviewer
|
||||||
if has_observer:
|
if has_observer:
|
||||||
@ -1778,9 +1775,9 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
team_row.addElement(score_tc)
|
team_row.addElement(score_tc)
|
||||||
|
|
||||||
score_col = 'C'
|
score_col = 'C'
|
||||||
rank_tc = TableCell(valuetype="float", value=sorted_participations.index(passage.reporter) + 1,
|
rank_tc = TableCell(valuetype="float", value=sorted_participations.index(passage.defender) + 1,
|
||||||
stylename=style_botright if passage.position == pool_size else style_right)
|
stylename=style_botright if passage.position == pool_size else style_right)
|
||||||
rank_tc.addElement(P(text=str(sorted_participations.index(passage.reporter) + 1)))
|
rank_tc.addElement(P(text=str(sorted_participations.index(passage.defender) + 1)))
|
||||||
rank_tc.setAttribute("formula", f"of:=RANK([.{score_col}{max_row + 5 + passage.position}]; "
|
rank_tc.setAttribute("formula", f"of:=RANK([.{score_col}{max_row + 5 + passage.position}]; "
|
||||||
f"[.{score_col}${max_row + 6}]:"
|
f"[.{score_col}${max_row + 6}]:"
|
||||||
f"[.{score_col}${max_row + 5 + pool_size}])")
|
f"[.{score_col}${max_row + 5 + pool_size}])")
|
||||||
@ -1984,7 +1981,7 @@ class PassageDetailView(LoginRequiredMixin, DetailView):
|
|||||||
or reg in passage.pool.juries.all()
|
or reg in passage.pool.juries.all()
|
||||||
or reg.pools_presided.filter(tournament=passage.pool.tournament).exists()) \
|
or reg.pools_presided.filter(tournament=passage.pool.tournament).exists()) \
|
||||||
or reg.participates and reg.team \
|
or reg.participates and reg.team \
|
||||||
and reg.team.participation in [passage.reporter, passage.opponent, passage.reviewer, passage.observer]:
|
and reg.team.participation in [passage.defender, passage.opponent, passage.reviewer, passage.observer]:
|
||||||
return super().dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
return self.handle_no_permission()
|
return self.handle_no_permission()
|
||||||
|
|
||||||
@ -2005,8 +2002,8 @@ class PassageDetailView(LoginRequiredMixin, DetailView):
|
|||||||
if 'notes' in context and not self.request.user.registration.is_admin:
|
if 'notes' in context and not self.request.user.registration.is_admin:
|
||||||
context['notes']._sequence.remove('update')
|
context['notes']._sequence.remove('update')
|
||||||
|
|
||||||
context['notes'].columns['reporter_writing'].column.verbose_name += f" ({passage.reporter.team.trigram})"
|
context['notes'].columns['defender_writing'].column.verbose_name += f" ({passage.defender.team.trigram})"
|
||||||
context['notes'].columns['reporter_oral'].column.verbose_name += f" ({passage.reporter.team.trigram})"
|
context['notes'].columns['defender_oral'].column.verbose_name += f" ({passage.defender.team.trigram})"
|
||||||
context['notes'].columns['opponent_writing'].column.verbose_name += f" ({passage.opponent.team.trigram})"
|
context['notes'].columns['opponent_writing'].column.verbose_name += f" ({passage.opponent.team.trigram})"
|
||||||
context['notes'].columns['opponent_oral'].column.verbose_name += f" ({passage.opponent.team.trigram})"
|
context['notes'].columns['opponent_oral'].column.verbose_name += f" ({passage.opponent.team.trigram})"
|
||||||
context['notes'].columns['reviewer_writing'].column.verbose_name += f" ({passage.reviewer.team.trigram})"
|
context['notes'].columns['reviewer_writing'].column.verbose_name += f" ({passage.reviewer.team.trigram})"
|
||||||
@ -2031,9 +2028,9 @@ class PassageUpdateView(VolunteerMixin, UpdateView):
|
|||||||
return self.handle_no_permission()
|
return self.handle_no_permission()
|
||||||
|
|
||||||
|
|
||||||
class WrittenReviewUploadView(LoginRequiredMixin, FormView):
|
class SynthesisUploadView(LoginRequiredMixin, FormView):
|
||||||
template_name = "participation/upload_written_review.html"
|
template_name = "participation/upload_synthesis.html"
|
||||||
form_class = WrittenReviewForm
|
form_class = SynthesisForm
|
||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
if not request.user.is_authenticated or not request.user.registration.participates:
|
if not request.user.is_authenticated or not request.user.registration.participates:
|
||||||
@ -2060,14 +2057,14 @@ class WrittenReviewUploadView(LoginRequiredMixin, FormView):
|
|||||||
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 if self.participation == self.passage.reviewer else 3
|
else 2 if self.participation == self.passage.reviewer else 3
|
||||||
syn_qs = WrittenReview.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()
|
||||||
|
|
||||||
deadline = self.passage.pool.tournament.reviews_first_phase_limit if self.passage.pool.round == 1 \
|
deadline = self.passage.pool.tournament.syntheses_first_phase_limit if self.passage.pool.round == 1 \
|
||||||
else self.passage.pool.tournament.reviews_second_phase_limit
|
else self.passage.pool.tournament.syntheses_second_phase_limit
|
||||||
if syn_qs.exists() and timezone.now() > deadline:
|
if syn_qs.exists() and timezone.now() > deadline:
|
||||||
form.add_error(None, _("You can't upload a written review after the deadline."))
|
form.add_error(None, _("You can't upload a synthesis after the deadline."))
|
||||||
return self.form_invalid(form)
|
return self.form_invalid(form)
|
||||||
|
|
||||||
# Drop previous solution if existing
|
# Drop previous solution if existing
|
||||||
@ -2101,8 +2098,8 @@ class NoteUpdateView(VolunteerMixin, UpdateView):
|
|||||||
|
|
||||||
def get_form(self, form_class=None):
|
def get_form(self, form_class=None):
|
||||||
form = super().get_form(form_class)
|
form = super().get_form(form_class)
|
||||||
form.fields['reporter_writing'].label += f" ({self.object.passage.reporter.team.trigram})"
|
form.fields['defender_writing'].label += f" ({self.object.passage.defender.team.trigram})"
|
||||||
form.fields['reporter_oral'].label += f" ({self.object.passage.reporter.team.trigram})"
|
form.fields['defender_oral'].label += f" ({self.object.passage.defender.team.trigram})"
|
||||||
form.fields['opponent_writing'].label += f" ({self.object.passage.opponent.team.trigram})"
|
form.fields['opponent_writing'].label += f" ({self.object.passage.opponent.team.trigram})"
|
||||||
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})"
|
||||||
|
@ -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.views.generic import CreateView, DetailView, RedirectView, TemplateView, UpdateView, View
|
||||||
from django_tables2 import SingleTableView
|
from django_tables2 import SingleTableView
|
||||||
from magic import Magic
|
from magic import Magic
|
||||||
from participation.models import Passage, Solution, Tournament, WrittenReview
|
from participation.models import Passage, Solution, Synthesis, Tournament
|
||||||
from tfjm.tokens import email_validation_token
|
from tfjm.tokens import email_validation_token
|
||||||
from tfjm.views import UserMixin, UserRegistrationMixin, VolunteerMixin
|
from tfjm.views import UserMixin, UserRegistrationMixin, VolunteerMixin
|
||||||
|
|
||||||
@ -837,11 +837,11 @@ class SolutionView(LoginRequiredMixin, View):
|
|||||||
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 and user.registration.team.participation:
|
||||||
passage_participant_qs = Passage.objects.filter(Q(reporter=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),
|
| Q(observer=user.registration.team.participation),
|
||||||
reporter=solution.participation,
|
defender=solution.participation,
|
||||||
solution_number=solution.problem)
|
solution_number=solution.problem)
|
||||||
else:
|
else:
|
||||||
passage_participant_qs = Passage.objects.none()
|
passage_participant_qs = Passage.objects.none()
|
||||||
@ -853,7 +853,7 @@ class SolutionView(LoginRequiredMixin, View):
|
|||||||
or user.registration.is_volunteer
|
or user.registration.is_volunteer
|
||||||
and Passage.objects.filter(Q(pool__juries=user.registration)
|
and Passage.objects.filter(Q(pool__juries=user.registration)
|
||||||
| Q(pool__tournament__in=user.registration.organized_tournaments.all()),
|
| Q(pool__tournament__in=user.registration.organized_tournaments.all()),
|
||||||
reporter=solution.participation,
|
defender=solution.participation,
|
||||||
solution_number=solution.problem).exists()
|
solution_number=solution.problem).exists()
|
||||||
or user.registration.participates and user.registration.team
|
or user.registration.participates and user.registration.team
|
||||||
and (solution.participation.team == user.registration.team or
|
and (solution.participation.team == user.registration.team or
|
||||||
@ -871,30 +871,30 @@ class SolutionView(LoginRequiredMixin, View):
|
|||||||
return FileResponse(open(path, "rb"), content_type=mime_type, filename=true_file_name)
|
return FileResponse(open(path, "rb"), content_type=mime_type, filename=true_file_name)
|
||||||
|
|
||||||
|
|
||||||
class WrittenReviewView(LoginRequiredMixin, View):
|
class SynthesisView(LoginRequiredMixin, View):
|
||||||
"""
|
"""
|
||||||
Display the sent written reviews.
|
Display the sent synthesis.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
filename = kwargs["filename"]
|
filename = kwargs["filename"]
|
||||||
path = f"media/reviews/{filename}"
|
path = f"media/syntheses/{filename}"
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
raise Http404
|
raise Http404
|
||||||
review = WrittenReview.objects.get(file__endswith=filename)
|
synthesis = Synthesis.objects.get(file__endswith=filename)
|
||||||
user = request.user
|
user = request.user
|
||||||
if not (user.registration.is_admin or user.registration.is_volunteer
|
if not (user.registration.is_admin or user.registration.is_volunteer
|
||||||
and (user.registration in review.passage.pool.juries.all()
|
and (user.registration in synthesis.passage.pool.juries.all()
|
||||||
or user.registration in review.passage.pool.tournament.organizers.all()
|
or user.registration in synthesis.passage.pool.tournament.organizers.all()
|
||||||
or user.registration.pools_presided.filter(tournament=review.passage.pool.tournament).exists())
|
or user.registration.pools_presided.filter(tournament=synthesis.passage.pool.tournament).exists())
|
||||||
or user.registration.participates and user.registration.team == review.participation.team):
|
or user.registration.participates and user.registration.team == synthesis.participation.team):
|
||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
# Guess mime type of the file
|
# Guess mime type of the file
|
||||||
mime = Magic(mime=True)
|
mime = Magic(mime=True)
|
||||||
mime_type = mime.from_file(path)
|
mime_type = mime.from_file(path)
|
||||||
ext = mime_type.split("/")[1].replace("jpeg", "jpg")
|
ext = mime_type.split("/")[1].replace("jpeg", "jpg")
|
||||||
# Replace file name
|
# Replace file name
|
||||||
true_file_name = str(review) + f".{ext}"
|
true_file_name = str(synthesis) + f".{ext}"
|
||||||
return FileResponse(open(path, "rb"), content_type=mime_type, filename=true_file_name)
|
return FileResponse(open(path, "rb"), content_type=mime_type, filename=true_file_name)
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ Round \underline{~~~~} pool \underline{~~~~}
|
|||||||
|
|
||||||
\medskip
|
\medskip
|
||||||
|
|
||||||
Problem \underline{~~~~} reported by team \underline{~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
|
Problem \underline{~~~~} defended by team \underline{~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
|
||||||
|
|
||||||
\medskip
|
\medskip
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ from django.views.defaults import bad_request, page_not_found, permission_denied
|
|||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
from participation.views import MotivationLetterView
|
from participation.views import MotivationLetterView
|
||||||
from registration.views import HealthSheetView, ParentalAuthorizationView, PhotoAuthorizationView, \
|
from registration.views import HealthSheetView, ParentalAuthorizationView, PhotoAuthorizationView, \
|
||||||
ReceiptView, SolutionView, VaccineSheetView, WrittenReviewView
|
ReceiptView, SolutionView, SynthesisView, VaccineSheetView
|
||||||
|
|
||||||
from .views import AdminSearchView
|
from .views import AdminSearchView
|
||||||
|
|
||||||
@ -61,8 +61,8 @@ urlpatterns = [
|
|||||||
|
|
||||||
path('media/solutions/<str:filename>/', SolutionView.as_view(),
|
path('media/solutions/<str:filename>/', SolutionView.as_view(),
|
||||||
name='solution'),
|
name='solution'),
|
||||||
path('media/reviews/<str:filename>/', WrittenReviewView.as_view(),
|
path('media/syntheses/<str:filename>/', SynthesisView.as_view(),
|
||||||
name='reviews'),
|
name='synthesis'),
|
||||||
]
|
]
|
||||||
|
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
|
Loading…
Reference in New Issue
Block a user