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

Reporter -> reviewer

Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
Emmy D'Anello 2024-07-05 11:00:11 +02:00
parent 05c6333c5e
commit 2a298a3ee4
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
15 changed files with 247 additions and 155 deletions

View File

@ -148,7 +148,7 @@ class Draw(models.Model):
# The problem can be rejected
s += _("It can decide to accept or refuse this problem.") + " "
if len(td.rejected) >= len(settings.PROBLEMS) - settings.RECOMMENDED_SOLUTIONS_COUNT:
s += _("Refusing this problem will add a new penalty of 25% "
s += _("Refusing this problem will add a new 25% penalty "
"on the coefficient of the oral defense.")
else:
s += _("There are still {remaining} refusals without penalty.").format(
@ -415,7 +415,7 @@ class Pool(models.Model):
solution_number=tds[line[0]].accepted,
defender=tds[line[0]].participation,
opponent=tds[line[1]].participation,
reporter=tds[line[2]].participation,
reviewer=tds[line[2]].participation,
defender_penalties=tds[line[0]].penalty_int,
)

View File

@ -529,37 +529,37 @@ document.addEventListener('DOMContentLoaded', () => {
opponentTd.classList.add('text-center')
opponentTd.innerText = 'Opp'
let reporterTd = document.createElement('td')
reporterTd.classList.add('text-center')
reporterTd.innerText = 'Rap'
let reviewerTd = document.createElement('td')
reviewerTd.classList.add('text-center')
reviewerTd.innerText = 'Rap'
// Put the cells in their right places, according to the pool size and the row number.
if (poule.teams.length === 3) {
switch (i) {
case 0:
teamTr.append(defenderTd, reporterTd, opponentTd)
teamTr.append(defenderTd, reviewerTd, opponentTd)
break
case 1:
teamTr.append(opponentTd, defenderTd, reporterTd)
teamTr.append(opponentTd, defenderTd, reviewerTd)
break
case 2:
teamTr.append(reporterTd, opponentTd, defenderTd)
teamTr.append(reviewerTd, opponentTd, defenderTd)
break
}
} else if (poule.teams.length === 4) {
let emptyTd = document.createElement('td')
switch (i) {
case 0:
teamTr.append(defenderTd, emptyTd, reporterTd, opponentTd)
teamTr.append(defenderTd, emptyTd, reviewerTd, opponentTd)
break
case 1:
teamTr.append(opponentTd, defenderTd, emptyTd, reporterTd)
teamTr.append(opponentTd, defenderTd, emptyTd, reviewerTd)
break
case 2:
teamTr.append(reporterTd, opponentTd, defenderTd, emptyTd)
teamTr.append(reviewerTd, opponentTd, defenderTd, emptyTd)
break
case 3:
teamTr.append(emptyTd, reporterTd, opponentTd, defenderTd)
teamTr.append(emptyTd, reviewerTd, opponentTd, defenderTd)
break
}
} else if (poule.teams.length === 5) {
@ -567,19 +567,19 @@ document.addEventListener('DOMContentLoaded', () => {
let emptyTd2 = document.createElement('td')
switch (i) {
case 0:
teamTr.append(defenderTd, emptyTd, opponentTd, reporterTd, emptyTd2)
teamTr.append(defenderTd, emptyTd, opponentTd, reviewerTd, emptyTd2)
break
case 1:
teamTr.append(emptyTd, defenderTd, reporterTd, emptyTd2, opponentTd)
teamTr.append(emptyTd, defenderTd, reviewerTd, emptyTd2, opponentTd)
break
case 2:
teamTr.append(opponentTd, emptyTd, defenderTd, emptyTd2, reporterTd)
teamTr.append(opponentTd, emptyTd, defenderTd, emptyTd2, reviewerTd)
break
case 3:
teamTr.append(reporterTd, opponentTd, emptyTd, defenderTd, emptyTd2)
teamTr.append(reviewerTd, opponentTd, emptyTd, defenderTd, emptyTd2)
break
case 4:
teamTr.append(emptyTd, reporterTd, emptyTd2, opponentTd, defenderTd)
teamTr.append(emptyTd, reviewerTd, emptyTd2, opponentTd, defenderTd)
break
}
}

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: TFJM\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-05 10:38+0200\n"
"POT-Creation-Date: 2024-07-05 10:48+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Emmy D'Anello <emmy.danello@animath.fr>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -510,10 +510,11 @@ msgid ""
"sided dice by clicking on the big dice button to determine the order of "
"draw. The team with the highest score will draw first."
msgstr ""
"Nous allons commencer le tirage des problèmes pour la poule <strong>{pool}"
"</strong>, entre les équipes <strong>{teams}</strong>. Les capitaines peuvent "
"lancer un dé à 100 faces en cliquant sur le gros bouton de dé pour déterminer "
"l'ordre de tirage. L'équipe avec le score le plus élevé tirera en premier."
"Nous allons commencer le tirage des problèmes pour la poule <strong>{pool}</"
"strong>, entre les équipes <strong>{teams}</strong>. Les capitaines peuvent "
"lancer un dé à 100 faces en cliquant sur le gros bouton de dé pour "
"déterminer l'ordre de tirage. L'équipe avec le score le plus élevé tirera en "
"premier."
#: draw/models.py:133
#, python-brace-format
@ -547,11 +548,11 @@ msgstr "Elle peut décider d'accepter ou de refuser ce problème."
#: draw/models.py:151
msgid ""
"Refusing this problem will add a new penalty of 25% on the coefficient of "
"Refusing this problem will add a new 25% penalty on the coefficient of "
"the oral defense."
msgstr ""
"Refuser ce problème ajoutera une nouvelle pénalité de 25 % sur le coefficient "
"de l'oral de la défense."
"Refuser ce problème ajoutera une nouvelle pénalité de 25nbsp;% sur le "
"coefficient de l'oral de la défense."
#: draw/models.py:154
#, python-brace-format
@ -571,8 +572,8 @@ msgid ""
"The draw is ended. The solutions of the other teams can be found in the tab "
"\"My participation\"."
msgstr ""
"Le tirage est terminé. Les solutions des autres équipes peuvent être trouvées "
"dans l'onglet « Ma participation »."
"Le tirage est terminé. Les solutions des autres équipes peuvent être "
"trouvées dans l'onglet « Ma participation »."
#: draw/models.py:166
#, python-brace-format
@ -580,8 +581,8 @@ msgid ""
"For more details on the draw, the rules are available on <a class=\"alert-"
"link\" href=\"{link}\">{link}</a>."
msgstr ""
"Pour plus de détails sur le tirage, les règles sont disponibles sur <a class="
"\"alert-link\" href=\"{link}\">{link}</a>."
"Pour plus de détails sur le tirage, les règles sont disponibles sur <a "
"class=\"alert-link\" href=\"{link}\">{link}</a>."
#: draw/models.py:177
#, python-brace-format
@ -923,7 +924,7 @@ msgstr "opposant⋅e"
#: participation/admin.py:132 participation/models.py:1559
#: participation/models.py:1750
msgid "reporter"
msgid "reviewer"
msgstr "rapporteur⋅rice"
#: participation/admin.py:187 participation/models.py:1700
@ -1015,7 +1016,7 @@ msgid "The following user was not found:"
msgstr "L'utilisateur⋅rice suivant n'a pas été trouvé :"
#: participation/forms.py:349
msgid "The defender, the opponent and the reporter must be different."
msgid "The defender, the opponent and the reviewer must be different."
msgstr ""
"Les équipes défenseuse, opposante et rapportrice doivent être différent⋅es."
@ -1396,11 +1397,11 @@ msgstr ""
#: participation/models.py:966
#, python-brace-format
msgid ""
"<p>You will report the solution of the team {reporter} on the <a "
"<p>You will report the solution of the team {reviewer} on the <a "
"href='{solution_url}'>problem {problem}. You can upload your synthesis sheet "
"on <a href='{passage_url}'>this page</a>.</p>"
msgstr ""
"<p>Vous rapporterez la solution de l'équipe {reporter} 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 "
"de synthèse sur <a href='{passage_url}'>cette page</a>.</p>"
@ -1630,11 +1631,11 @@ msgid "opponent oral note"
msgstr "note d'oral opposant⋅e"
#: participation/models.py:1815
msgid "reporter writing note"
msgid "reviewer writing note"
msgstr "note d'écrit rapporteur⋅rice"
#: participation/models.py:1821
msgid "reporter oral note"
msgid "reviewer oral note"
msgstr "note d'oral du rapporteur⋅rice"
#: participation/models.py:1881
@ -1813,7 +1814,7 @@ msgid "Opponent:"
msgstr "Opposant⋅e :"
#: participation/templates/participation/passage_detail.html:34
msgid "Reporter:"
msgid "reviewer:"
msgstr "Rapporteur⋅rice :"
#: participation/templates/participation/passage_detail.html:37
@ -1865,11 +1866,11 @@ msgid "Average points for the opponent oral"
msgstr "Moyenne de l'oral de l'équipe opposante"
#: participation/templates/participation/passage_detail.html:101
msgid "Average points for the reporter writing"
msgid "Average points for the reviewer writing"
msgstr "Moyenne de l'écrit de l'équipe rapportrice"
#: participation/templates/participation/passage_detail.html:107
msgid "Average points for the reporter oral"
msgid "Average points for the reviewer oral"
msgstr "Moyenne de l'oral de l'équipe rapportrice"
#: participation/templates/participation/passage_detail.html:117
@ -1881,7 +1882,7 @@ msgid "Opponent points"
msgstr "Points de l'équipe opposante"
#: participation/templates/participation/passage_detail.html:129
msgid "Reporter points"
msgid "reviewer points"
msgstr "Points de l'équipe rapportrice"
#: participation/templates/participation/passage_detail.html:139

View File

@ -51,7 +51,7 @@ class PassageInline(admin.TabularInline):
model = Passage
extra = 0
ordering = ('position',)
autocomplete_fields = ('defender', 'opponent', 'reporter',)
autocomplete_fields = ('defender', 'opponent', 'reviewer',)
show_change_link = True
@ -113,12 +113,12 @@ class PoolAdmin(admin.ModelAdmin):
@admin.register(Passage)
class PassageAdmin(admin.ModelAdmin):
list_display = ('__str__', 'defender_trigram', 'solution_number', 'opponent_trigram', 'reporter_trigram',
list_display = ('__str__', 'defender_trigram', 'solution_number', 'opponent_trigram', 'reviewer_trigram',
'pool_abbr', 'position', 'tournament')
list_filter = ('pool__tournament', 'pool__round', 'pool__letter', 'solution_number',)
search_fields = ('pool__participations__team__name', 'pool__participations__team__trigram',)
ordering = ('pool__tournament', 'pool__round', 'pool__letter', 'position',)
autocomplete_fields = ('pool', 'defender', 'opponent', 'reporter',)
autocomplete_fields = ('pool', 'defender', 'opponent', 'reviewer',)
inlines = (NoteInline,)
@admin.display(description=_("defender"), ordering='defender__team__trigram')
@ -129,9 +129,9 @@ class PassageAdmin(admin.ModelAdmin):
def opponent_trigram(self, record: Passage):
return record.opponent.team.trigram
@admin.display(description=_("reporter"), ordering='reporter__team__trigram')
def reporter_trigram(self, record: Passage):
return record.reporter.team.trigram
@admin.display(description=_("reviewer"), ordering='reviewer__team__trigram')
def reviewer_trigram(self, record: Passage):
return record.reviewer.team.trigram
@admin.display(description=_("pool"), ordering='pool__letter')
def pool_abbr(self, record):
@ -145,10 +145,10 @@ class PassageAdmin(admin.ModelAdmin):
@admin.register(Note)
class NoteAdmin(admin.ModelAdmin):
list_display = ('passage', 'pool', 'jury', 'defender_writing', 'defender_oral',
'opponent_writing', 'opponent_oral', 'reporter_writing', 'reporter_oral',)
'opponent_writing', 'opponent_oral', 'reviewer_writing', 'reviewer_oral',)
list_filter = ('passage__pool__letter', 'passage__solution_number', 'jury',
'defender_writing', 'defender_oral', 'opponent_writing', 'opponent_oral',
'reporter_writing', 'reporter_oral')
'reviewer_writing', 'reviewer_oral')
search_fields = ('jury__user__last_name', 'jury__user__first_name', 'passage__defender__team__trigram',)
autocomplete_fields = ('jury', 'passage',)

View File

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

View File

@ -344,9 +344,9 @@ class UploadNotesForm(forms.Form):
class PassageForm(forms.ModelForm):
def clean(self):
cleaned_data = super().clean()
if "defender" in cleaned_data and "opponent" in cleaned_data and "reporter" in cleaned_data \
and len({cleaned_data["defender"], cleaned_data["opponent"], cleaned_data["reporter"]}) < 3:
self.add_error(None, _("The defender, the opponent and the reporter must be different."))
if "defender" in cleaned_data and "opponent" in cleaned_data and "reviewer" in cleaned_data \
and len({cleaned_data["defender"], cleaned_data["opponent"], cleaned_data["reviewer"]}) < 3:
self.add_error(None, _("The defender, the opponent and the reviewer must be different."))
if "defender" in self.cleaned_data and "solution_number" in self.cleaned_data \
and not Solution.objects.filter(participation=cleaned_data["defender"],
problem=cleaned_data["solution_number"]).exists():
@ -355,7 +355,7 @@ class PassageForm(forms.ModelForm):
class Meta:
model = Passage
fields = ('position', 'solution_number', 'defender', 'opponent', 'reporter', 'defender_penalties',)
fields = ('position', 'solution_number', 'defender', 'opponent', 'reviewer', 'defender_penalties',)
class SynthesisForm(forms.ModelForm):
@ -386,4 +386,4 @@ class NoteForm(forms.ModelForm):
class Meta:
model = Note
fields = ('defender_writing', 'defender_oral', 'opponent_writing',
'opponent_oral', 'reporter_writing', 'reporter_oral', )
'opponent_oral', 'reviewer_writing', 'reviewer_oral', )

View File

@ -53,23 +53,23 @@ class Command(BaseCommand):
pool1 = tournament.pools.filter(round=1, participations=team2).first()
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)
reporter_passage_1 = Passage.objects.get(pool__tournament=tournament, pool__round=1, reporter=team2)
reviewer_passage_1 = Passage.objects.get(pool__tournament=tournament, pool__round=1, reviewer=team2)
pool2 = tournament.pools.filter(round=2, participations=team2).first()
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)
reporter_passage_2 = Passage.objects.get(pool__tournament=tournament, pool__round=2, reporter=team2)
reviewer_passage_2 = Passage.objects.get(pool__tournament=tournament, pool__round=2, reviewer=team2)
line.append(team2.team.trigram)
line.append(str(pool1.jury_president or ""))
line.append(f"Pb. {defender_passage_1.solution_number}")
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,
reporter_passage_1.average_reporter_writing, reporter_passage_1.average_reporter_oral])
reviewer_passage_1.average_reviewer_writing, reviewer_passage_1.average_reviewer_oral])
line.append(str(pool2.jury_president or ""))
line.append(f"Pb. {defender_passage_2.solution_number}")
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,
reporter_passage_2.average_reporter_writing, reporter_passage_2.average_reporter_oral])
reviewer_passage_2.average_reviewer_writing, reviewer_passage_2.average_reviewer_oral])
line.extend([score2, f"{score1:.1f} ({team1.team.trigram})",
f"{score3:.1f} ({team3.team.trigram})"])

View File

@ -0,0 +1,91 @@
# Generated by Django 5.0.6 on 2024-07-05 08:53
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
(
"participation",
"0017_alter_passage_solution_number_alter_pool_round_and_more",
),
]
operations = [
migrations.RenameField(
model_name="note",
old_name="reporter_oral",
new_name="reviewer_oral",
),
migrations.RenameField(
model_name="note",
old_name="reporter_writing",
new_name="reviewer_writing",
),
migrations.RenameField(
model_name="passage",
old_name="reporter",
new_name="reviewer",
),
migrations.AlterField(
model_name="note",
name="reviewer_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),
],
default=0,
verbose_name="reviewer oral note",
),
),
migrations.AlterField(
model_name="note",
name="reviewer_writing",
field=models.PositiveSmallIntegerField(
choices=[
(0, 0),
(1, 1),
(2, 2),
(3, 3),
(4, 4),
(5, 5),
(6, 6),
(7, 7),
(8, 8),
(9, 9),
(10, 10),
],
default=0,
verbose_name="reviewer writing note",
),
),
migrations.AlterField(
model_name="passage",
name="reviewer",
field=models.ForeignKey(
on_delete=django.db.models.deletion.PROTECT,
related_name="+",
to="participation.participation",
verbose_name="reviewer",
),
),
migrations.AlterField(
model_name="synthesis",
name="type",
field=models.PositiveSmallIntegerField(
choices=[(1, "opponent"), (2, "reviewer")]
),
),
]

View File

@ -858,7 +858,7 @@ class Participation(models.Model):
elif timezone.now() <= tournament.syntheses_first_phase_limit + timedelta(hours=2):
defender_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, defender=self)
opponent_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, opponent=self)
reporter_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, reporter=self)
reviewer_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, reviewer=self)
defender_text = _("<p>The solutions draw is ended. You can check the result on "
"<a href='{draw_url}'>this page</a>.</p>"
@ -878,21 +878,21 @@ class Participation(models.Model):
solution_url=solution_url,
problem=opponent_passage.solution_number, passage_url=passage_url)
reporter_text = _("<p>You will report the solution of the team {reporter} on the "
reviewer_text = _("<p>You will report the solution of the team {reviewer} on the "
"<a href='{solution_url}'>problem {problem}. "
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
solution_url = reporter_passage.defended_solution.file.url
passage_url = reverse_lazy("participation:passage_detail", args=(reporter_passage.pk,))
reporter_content = format_lazy(reporter_text, reporter=reporter_passage.defender.team.trigram,
solution_url = reviewer_passage.defended_solution.file.url
passage_url = reverse_lazy("participation:passage_detail", args=(reviewer_passage.pk,))
reviewer_content = format_lazy(reviewer_text, reviewer=reviewer_passage.defender.team.trigram,
solution_url=solution_url,
problem=reporter_passage.solution_number, passage_url=passage_url)
problem=reviewer_passage.solution_number, passage_url=passage_url)
syntheses_template_begin = f"{settings.STATIC_URL}Fiche_synthèse."
syntheses_templates = "".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
for ext in ["pdf", "tex", "odt", "docx"])
syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>"
content = defender_content + opponent_content + reporter_content + syntheses_templates_content
content = defender_content + opponent_content + reviewer_content + syntheses_templates_content
informations.append({
'title': _("First round"),
'type': "info",
@ -902,7 +902,7 @@ class Participation(models.Model):
elif timezone.now() <= tournament.syntheses_second_phase_limit + timedelta(hours=2):
defender_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, defender=self)
opponent_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, opponent=self)
reporter_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, reporter=self)
reviewer_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, reviewer=self)
defender_text = _("<p>For the second round, you will defend "
"<a href='{solution_url}'>your solution of the problem {problem}</a>.</p>")
@ -920,21 +920,21 @@ class Participation(models.Model):
solution_url=solution_url,
problem=opponent_passage.solution_number, passage_url=passage_url)
reporter_text = _("<p>You will report the solution of the team {reporter} on the "
reviewer_text = _("<p>You will report the solution of the team {reviewer} on the "
"<a href='{solution_url}'>problem {problem}. "
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
solution_url = reporter_passage.defended_solution.file.url
passage_url = reverse_lazy("participation:passage_detail", args=(reporter_passage.pk,))
reporter_content = format_lazy(reporter_text, reporter=reporter_passage.defender.team.trigram,
solution_url = reviewer_passage.defended_solution.file.url
passage_url = reverse_lazy("participation:passage_detail", args=(reviewer_passage.pk,))
reviewer_content = format_lazy(reviewer_text, reviewer=reviewer_passage.defender.team.trigram,
solution_url=solution_url,
problem=reporter_passage.solution_number, passage_url=passage_url)
problem=reviewer_passage.solution_number, passage_url=passage_url)
syntheses_template_begin = f"{settings.STATIC_URL}Fiche_synthèse."
syntheses_templates = "".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
for ext in ["pdf", "tex", "odt", "docx"])
syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>"
content = defender_content + opponent_content + reporter_content + syntheses_templates_content
content = defender_content + opponent_content + reviewer_content + syntheses_templates_content
informations.append({
'title': _("Second round"),
'type': "info",
@ -945,7 +945,7 @@ class Participation(models.Model):
and timezone.now() <= tournament.syntheses_third_phase_limit + timedelta(hours=2):
defender_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, defender=self)
opponent_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, opponent=self)
reporter_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, reporter=self)
reviewer_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, reviewer=self)
defender_text = _("<p>For the third round, you will defend "
"<a href='{solution_url}'>your solution of the problem {problem}</a>.</p>")
@ -963,21 +963,21 @@ class Participation(models.Model):
solution_url=solution_url,
problem=opponent_passage.solution_number, passage_url=passage_url)
reporter_text = _("<p>You will report the solution of the team {reporter} on the "
reviewer_text = _("<p>You will report the solution of the team {reviewer} on the "
"<a href='{solution_url}'>problem {problem}. "
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
solution_url = reporter_passage.defended_solution.file.url
passage_url = reverse_lazy("participation:passage_detail", args=(reporter_passage.pk,))
reporter_content = format_lazy(reporter_text, reporter=reporter_passage.defender.team.trigram,
solution_url = reviewer_passage.defended_solution.file.url
passage_url = reverse_lazy("participation:passage_detail", args=(reviewer_passage.pk,))
reviewer_content = format_lazy(reviewer_text, reviewer=reviewer_passage.defender.team.trigram,
solution_url=solution_url,
problem=reporter_passage.solution_number, passage_url=passage_url)
problem=reviewer_passage.solution_number, passage_url=passage_url)
syntheses_template_begin = f"{settings.STATIC_URL}Fiche_synthèse."
syntheses_templates = "".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
for ext in ["pdf", "tex", "odt", "docx"])
syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>"
content = defender_content + opponent_content + reporter_content + syntheses_templates_content
content = defender_content + opponent_content + reviewer_content + syntheses_templates_content
informations.append({
'title': _("Second round"),
'type': "info",
@ -1132,7 +1132,7 @@ class Pool(models.Model):
for passage in passages), start=["Problème", ""]),
sum(([f"Défenseur⋅se ({passage.defender.team.trigram})", "",
f"Opposant⋅e ({passage.opponent.team.trigram})", "",
f"Rapporteur⋅rice ({passage.reporter.team.trigram})", ""]
f"Rapporteur⋅rice ({passage.reviewer.team.trigram})", ""]
for passage in passages), start=["Rôle", ""]),
sum((["Écrit (/20)", "Oral (/20)", "Écrit (/10)", "Oral (/10)", "Écrit (/10)", "Oral (/10)"]
for _passage in passages), start=["Juré⋅e", ""]),
@ -1144,7 +1144,7 @@ class Pool(models.Model):
for passage in passages:
note = passage.notes.filter(jury=jury).first()
line.extend([note.defender_writing, note.defender_oral, note.opponent_writing, note.opponent_oral,
note.reporter_writing, note.reporter_oral])
note.reviewer_writing, note.reviewer_oral])
notes.append(line)
notes.append([]) # Add empty line to ensure pretty design
@ -1204,18 +1204,18 @@ class Pool(models.Model):
opponent_row = 5 + opponent_passage.pool.juries.count()
opponent_col = opponent_passage.position - 1
reporter_passage = Passage.objects.get(reporter=participation,
reviewer_passage = Passage.objects.get(reviewer=participation,
pool__tournament=self.tournament, pool__round=self.round)
reporter_row = 5 + reporter_passage.pool.juries.count()
reporter_col = reporter_passage.position - 1
reviewer_row = 5 + reviewer_passage.pool.juries.count()
reviewer_col = reviewer_passage.position - 1
formula = "="
formula += (f"'Poule {defender_passage.pool.short_name}'"
f"!{getcol(min_column + defender_col * passage_width)}{defender_row + 3}") # Defender
formula += (f" + 'Poule {opponent_passage.pool.short_name}'"
f"!{getcol(min_column + opponent_col * passage_width + 2)}{opponent_row + 3}") # Opponent
formula += (f" + 'Poule {reporter_passage.pool.short_name}'"
f"!{getcol(min_column + reporter_col * passage_width + 4)}{reporter_row + 3}") # Reporter
formula += (f" + 'Poule {reviewer_passage.pool.short_name}'"
f"!{getcol(min_column + reviewer_col * passage_width + 4)}{reviewer_row + 3}") # reviewer
ranking.append([f"{participation.team.name} ({participation.team.trigram})", "",
f"='Poule {defender_passage.pool.short_name}'"
f"!${getcol(3 + defender_col * passage_width)}$1",
@ -1553,10 +1553,10 @@ class Passage(models.Model):
related_name="+",
)
reporter = models.ForeignKey(
reviewer = models.ForeignKey(
Participation,
on_delete=models.PROTECT,
verbose_name=_("reporter"),
verbose_name=_("reviewer"),
related_name="+",
)
@ -1603,16 +1603,16 @@ class Passage(models.Model):
return 0.9 * self.average_opponent_writing + 2 * self.average_opponent_oral
@property
def average_reporter_writing(self) -> float:
return self.avg(note.reporter_writing for note in self.notes.all())
def average_reviewer_writing(self) -> float:
return self.avg(note.reviewer_writing for note in self.notes.all())
@property
def average_reporter_oral(self) -> float:
return self.avg(note.reporter_oral for note in self.notes.all())
def average_reviewer_oral(self) -> float:
return self.avg(note.reviewer_oral for note in self.notes.all())
@property
def average_reporter(self) -> float:
return 0.9 * self.average_reporter_writing + self.average_reporter_oral
def average_reviewer(self) -> float:
return 0.9 * self.average_reviewer_writing + self.average_reviewer_oral
@property
def averages(self):
@ -1620,12 +1620,12 @@ class Passage(models.Model):
yield self.average_defender_oral
yield self.average_opponent_writing
yield self.average_opponent_oral
yield self.average_reporter_writing
yield self.average_reporter_oral
yield self.average_reviewer_writing
yield self.average_reviewer_oral
def average(self, participation):
return self.average_defender if participation == self.defender else self.average_opponent \
if participation == self.opponent else self.average_reporter if participation == self.reporter else 0
if participation == self.opponent else self.average_reviewer if participation == self.reviewer else 0
def get_absolute_url(self):
return reverse_lazy("participation:passage_detail", args=(self.pk,))
@ -1637,9 +1637,9 @@ class Passage(models.Model):
if self.opponent not in self.pool.participations.all():
raise ValidationError(_("Team {trigram} is not registered in the pool.")
.format(trigram=self.opponent.team.trigram))
if self.reporter not in self.pool.participations.all():
if self.reviewer not in self.pool.participations.all():
raise ValidationError(_("Team {trigram} is not registered in the pool.")
.format(trigram=self.reporter.team.trigram))
.format(trigram=self.reviewer.team.trigram))
return super().clean()
def __str__(self):
@ -1747,7 +1747,7 @@ class Synthesis(models.Model):
type = models.PositiveSmallIntegerField(
choices=[
(1, _("opponent"), ),
(2, _("reporter"), ),
(2, _("reviewer"), ),
]
)
@ -1811,14 +1811,14 @@ class Note(models.Model):
default=0,
)
reporter_writing = models.PositiveSmallIntegerField(
verbose_name=_("reporter writing note"),
reviewer_writing = models.PositiveSmallIntegerField(
verbose_name=_("reviewer writing note"),
choices=[(i, i) for i in range(0, 11)],
default=0,
)
reporter_oral = models.PositiveSmallIntegerField(
verbose_name=_("reporter oral note"),
reviewer_oral = models.PositiveSmallIntegerField(
verbose_name=_("reviewer oral note"),
choices=[(i, i) for i in range(0, 11)],
default=0,
)
@ -1828,17 +1828,17 @@ class Note(models.Model):
yield self.defender_oral
yield self.opponent_writing
yield self.opponent_oral
yield self.reporter_writing
yield self.reporter_oral
yield self.reviewer_writing
yield self.reviewer_oral
def set_all(self, defender_writing: int, defender_oral: int, opponent_writing: int, opponent_oral: int,
reporter_writing: int, reporter_oral: int):
reviewer_writing: int, reviewer_oral: int):
self.defender_writing = defender_writing
self.defender_oral = defender_oral
self.opponent_writing = opponent_writing
self.opponent_oral = opponent_oral
self.reporter_writing = reporter_writing
self.reporter_oral = reporter_oral
self.reviewer_writing = reviewer_writing
self.reviewer_oral = reviewer_oral
def update_spreadsheet(self):
if not self.has_any_note():

View File

@ -118,7 +118,7 @@ class PassageTable(tables.Table):
def render_opponent(self, value):
return value.team.trigram
def render_reporter(self, value):
def render_reviewer(self, value):
return value.team.trigram
class Meta:
@ -126,7 +126,7 @@ class PassageTable(tables.Table):
'class': 'table table-condensed table-striped text-center',
}
model = Passage
fields = ('defender', 'opponent', 'reporter', 'solution_number', )
fields = ('defender', 'opponent', 'reviewer', 'solution_number', )
class NoteTable(tables.Table):
@ -155,4 +155,4 @@ class NoteTable(tables.Table):
}
model = Note
fields = ('jury', 'defender_writing', 'defender_oral', 'opponent_writing', 'opponent_oral',
'reporter_writing', 'reporter_oral', 'update',)
'reviewer_writing', 'reviewer_oral', 'update',)

View File

@ -31,8 +31,8 @@
<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>
<dt class="col-sm-3">{% trans "Reporter:" %}</dt>
<dd class="col-sm-9"><a href="{{ passage.reporter.get_absolute_url }}">{{ passage.reporter.team }}</a></dd>
<dt class="col-sm-3">{% trans "reviewer:" %}</dt>
<dd class="col-sm-9"><a href="{{ passage.reviewer.get_absolute_url }}">{{ passage.reviewer.team }}</a></dd>
<dt class="col-sm-3">{% trans "Defended solution:" %}</dt>
<dd class="col-sm-9"><a href="{{ passage.defended_solution.file.url }}">{{ passage.defended_solution }}</a></dd>
@ -98,16 +98,16 @@
<dd class="col-sm-4">{{ passage.average_opponent_oral|floatformat }}/10</dd>
<dt class="col-sm-8">
{% trans "Average points for the reporter writing" %}
({{ passage.reporter.team.trigram }}) :
{% trans "Average points for the reviewer writing" %}
({{ passage.reviewer.team.trigram }}) :
</dt>
<dd class="col-sm-4">{{ passage.average_reporter_writing|floatformat }}/10</dd>
<dd class="col-sm-4">{{ passage.average_reviewer_writing|floatformat }}/10</dd>
<dt class="col-sm-8">
{% trans "Average points for the reporter oral" %}
({{ passage.reporter.team.trigram }}) :
{% trans "Average points for the reviewer oral" %}
({{ passage.reviewer.team.trigram }}) :
</dt>
<dd class="col-sm-4">{{ passage.average_reporter_oral|floatformat }}/10</dd>
<dd class="col-sm-4">{{ passage.average_reviewer_oral|floatformat }}/10</dd>
</dl>
<hr>
@ -126,10 +126,10 @@
<dd class="col-sm-4">{{ passage.average_opponent|floatformat }}/29</dd>
<dt class="col-sm-8">
{% trans "Reporter points" %}
({{ passage.reporter.team.trigram }}) :
{% trans "reviewer points" %}
({{ passage.reviewer.team.trigram }}) :
</dt>
<dd class="col-sm-4">{{ passage.average_reporter|floatformat }}/19</dd>
<dd class="col-sm-4">{{ passage.average_reviewer|floatformat }}/19</dd>
</dl>
</div>
</div>

View File

@ -100,7 +100,7 @@
%%%%%%%%%%%%%%%%%%%%%%RAPPORTEUR.RICE
\begin{tabular}{|c|p{24mm}|p{11cm}|c{% for passage in passages.all %}|p{2cm}{% endfor %}|}\hline
\multicolumn{4}{|l|}{{\bf Rapporteur\textperiodcentered{}rice} \normalsize \'evalue le d\'ebat entre læ D\'efenseur\textperiodcentered{}se et l'Opposant\textperiodcentered{}e.} {% for passage in passages.all %}& P.{{ forloop.counter }} - {{ passage.reporter.team.trigram }} {% endfor %}\\ \hline \hline
\multicolumn{4}{|l|}{{\bf Rapporteur\textperiodcentered{}rice} \normalsize \'evalue le d\'ebat entre læ D\'efenseur\textperiodcentered{}se et l'Opposant\textperiodcentered{}e.} {% for passage in passages.all %}& P.{{ forloop.counter }} - {{ passage.reviewer.team.trigram }} {% endfor %}\\ \hline \hline
%ECRIT
\multirow{4}{3mm}{\centering\bf\'E\\ C\\ R\\ I\\ T} &\multirow{3}{20mm}{Partie scientifique} & Recul et esprit critique par rapport à la solution proposée & [0,3] {{ esp|safe }}\\ \cline{3-{{ passages.count|add:4 }}}

View File

@ -56,7 +56,7 @@ Tour {{ pool.round }} \;-- Poule {{ pool.get_letter_display }}{% if pool.partici
& \phantom{asd asd} \phantom{asd asd} \centering \normalsize$0\leq x\leq 10$
& \phantom{asd asd} \phantom{asd asd} \centering \normalsize$0\leq x\leq 10$
{% endfor %} & \hline
\multirow{2}{35mm}{\LARGE Rapporteur\textperiodcentered{}rice} {% 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 Rapporteur\textperiodcentered{}rice} {% for passage in passages.all %}& \multicolumn{2}{c|}{\Large {{ passage.reviewer.team.trigram }}}{% endfor %} \\ \cline{2-{{ passages.count|add:passages.count|add:1 }}}
{% for passage in passages.all %}
& \phantom{asd asd} \phantom{asd asd} \centering \normalsize$0\leq x\leq 10$
& \phantom{asd asd} \phantom{asd asd} \centering \normalsize$0\leq x\leq 10$

View File

@ -1507,11 +1507,11 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
header_role.addElement(opponent_tc)
header_role.addElement(CoveredTableCell())
reporter_tc = TableCell(valuetype="string",
reviewer_tc = TableCell(valuetype="string",
stylename=title_style_right)
reporter_tc.addElement(P(text="Rapporteur⋅rice"))
reporter_tc.setAttribute('numbercolumnsspanned', "2")
header_role.addElement(reporter_tc)
reviewer_tc.addElement(P(text="Rapporteur⋅rice"))
reviewer_tc.setAttribute('numbercolumnsspanned', "2")
header_role.addElement(reviewer_tc)
header_role.addElement(CoveredTableCell())
# Add maximum notes on the third line
@ -1540,13 +1540,13 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
opponent_o_tc.addElement(P(text="Oral (/10)"))
header_notes.addElement(opponent_o_tc)
reporter_w_tc = TableCell(valuetype="string", stylename=title_style_bot)
reporter_w_tc.addElement(P(text="Écrit (/10)"))
header_notes.addElement(reporter_w_tc)
reviewer_w_tc = TableCell(valuetype="string", stylename=title_style_bot)
reviewer_w_tc.addElement(P(text="Écrit (/10)"))
header_notes.addElement(reviewer_w_tc)
reporter_o_tc = TableCell(valuetype="string", stylename=title_style_botright)
reporter_o_tc.addElement(P(text="Oral (/10)"))
header_notes.addElement(reporter_o_tc)
reviewer_o_tc = TableCell(valuetype="string", stylename=title_style_botright)
reviewer_o_tc.addElement(P(text="Oral (/10)"))
header_notes.addElement(reviewer_o_tc)
# Add a notation line for each jury
for jury in self.object.juries.all():
@ -1617,13 +1617,13 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
opponent_o_tc.addElement(P(text="2"))
coeff_row.addElement(opponent_o_tc)
reporter_w_tc = TableCell(valuetype="float", value=0.9, stylename=style)
reporter_w_tc.addElement(P(text="1"))
coeff_row.addElement(reporter_w_tc)
reviewer_w_tc = TableCell(valuetype="float", value=0.9, stylename=style)
reviewer_w_tc.addElement(P(text="1"))
coeff_row.addElement(reviewer_w_tc)
reporter_o_tc = TableCell(valuetype="float", value=1, stylename=style_right)
reporter_o_tc.addElement(P(text="1"))
coeff_row.addElement(reporter_o_tc)
reviewer_o_tc = TableCell(valuetype="float", value=1, stylename=style_right)
reviewer_o_tc.addElement(P(text="1"))
coeff_row.addElement(reviewer_o_tc)
# Add the subtotal on the next line
subtotal_row = TableRow()
@ -1656,12 +1656,12 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
rep_w_col = getcol(min_column + passage_width * i + 4)
rep_o_col = getcol(min_column + passage_width * i + 5)
reporter_tc = TableCell(valuetype="float", value=passage.average_reporter, stylename=style_botright)
reporter_tc.addElement(P(text=str(passage.average_reporter)))
reporter_tc.setAttribute('numbercolumnsspanned', "2")
reporter_tc.setAttribute("formula", f"of:=[.{rep_w_col}{max_row + 1}] * [.{rep_w_col}{max_row + 2}]"
reviewer_tc = TableCell(valuetype="float", value=passage.average_reviewer, stylename=style_botright)
reviewer_tc.addElement(P(text=str(passage.average_reviewer)))
reviewer_tc.setAttribute('numbercolumnsspanned', "2")
reviewer_tc.setAttribute("formula", f"of:=[.{rep_w_col}{max_row + 1}] * [.{rep_w_col}{max_row + 2}]"
f" + [.{rep_o_col}{max_row + 1}] * [.{rep_o_col}{max_row + 2}]")
subtotal_row.addElement(reporter_tc)
subtotal_row.addElement(reviewer_tc)
subtotal_row.addElement(CoveredTableCell())
table.addElement(TableRow())
@ -1713,7 +1713,7 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
defender_pos = passage.position - 1
opponent_pos = self.object.passages.get(opponent=passage.defender).position - 1
reporter_pos = self.object.passages.get(reporter=passage.defender).position - 1
reviewer_pos = self.object.passages.get(reviewer=passage.defender).position - 1
score_tc = TableCell(valuetype="float", value=self.object.average(passage.defender),
stylename=style_bot if passage.position == pool_size else style)
@ -1721,7 +1721,7 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
formula = "of:="
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 + reporter_pos * passage_width + 4) + str(max_row + 3) # Reporter
formula += " + " + getcol(min_column + reviewer_pos * passage_width + 4) + str(max_row + 3) # reviewer
score_tc.setAttribute("formula", formula)
team_row.addElement(score_tc)
@ -1931,7 +1931,7 @@ class PassageDetailView(LoginRequiredMixin, DetailView):
or reg in passage.pool.juries.all()
or reg.pools_presided.filter(tournament=passage.pool.tournament).exists()) \
or reg.participates and reg.team \
and reg.team.participation in [passage.defender, passage.opponent, passage.reporter]:
and reg.team.participation in [passage.defender, passage.opponent, passage.reviewer]:
return super().dispatch(request, *args, **kwargs)
return self.handle_no_permission()
@ -1956,8 +1956,8 @@ class PassageDetailView(LoginRequiredMixin, DetailView):
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_oral'].column.verbose_name += f" ({passage.opponent.team.trigram})"
context['notes'].columns['reporter_writing'].column.verbose_name += f" ({passage.reporter.team.trigram})"
context['notes'].columns['reporter_oral'].column.verbose_name += f" ({passage.reporter.team.trigram})"
context['notes'].columns['reviewer_writing'].column.verbose_name += f" ({passage.reviewer.team.trigram})"
context['notes'].columns['reviewer_oral'].column.verbose_name += f" ({passage.reviewer.team.trigram})"
return context
@ -1992,7 +1992,7 @@ class SynthesisUploadView(LoginRequiredMixin, FormView):
self.participation = self.request.user.registration.team.participation
self.passage = qs.get()
if self.participation not in [self.passage.opponent, self.passage.reporter]:
if self.participation not in [self.passage.opponent, self.passage.reviewer]:
return self.handle_no_permission()
return super().dispatch(request, *args, **kwargs)
@ -2050,8 +2050,8 @@ class NoteUpdateView(VolunteerMixin, UpdateView):
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_oral'].label += f" ({self.object.passage.opponent.team.trigram})"
form.fields['reporter_writing'].label += f" ({self.object.passage.reporter.team.trigram})"
form.fields['reporter_oral'].label += f" ({self.object.passage.reporter.team.trigram})"
form.fields['reviewer_writing'].label += f" ({self.object.passage.reviewer.team.trigram})"
form.fields['reviewer_oral'].label += f" ({self.object.passage.reviewer.team.trigram})"
return form
def form_valid(self, form):

View File

@ -839,7 +839,7 @@ class SolutionView(LoginRequiredMixin, View):
if user.registration.participates:
passage_participant_qs = Passage.objects.filter(Q(defender=user.registration.team.participation)
| Q(opponent=user.registration.team.participation)
| Q(reporter=user.registration.team.participation),
| Q(reviewer=user.registration.team.participation),
defender=solution.participation,
solution_number=solution.problem)
else: