From b6d54d27cd25b3aebb9fb9f084095ec53659d4e4 Mon Sep 17 00:00:00 2001 From: Emmy D'Anello Date: Sun, 24 Mar 2024 20:05:07 +0100 Subject: [PATCH] Update ODS note sheets Signed-off-by: Emmy D'Anello --- participation/forms.py | 20 ++++++++------------ participation/models.py | 6 +++--- participation/views.py | 38 ++++++++++++++++++++++++++++++-------- 3 files changed, 41 insertions(+), 23 deletions(-) diff --git a/participation/forms.py b/participation/forms.py index b6c5bd0..41667ad 100644 --- a/participation/forms.py +++ b/participation/forms.py @@ -17,6 +17,7 @@ from django.db.models.functions import Concat from django.utils.translation import gettext_lazy as _ from pypdf import PdfReader +from registration.models import VolunteerRegistration from .models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament @@ -291,7 +292,7 @@ class UploadNotesForm(forms.Form): def process(self, csvfile: Iterable[str], cleaned_data: dict): parsed_notes = {} - valid_lengths = [1 + 6 * 3, 1 + 7 * 4, 1 + 6 * 5] # Per pool sizes + valid_lengths = [2 + 6 * 3, 2 + 7 * 4, 2 + 6 * 5] # Per pool sizes pool_size = 0 line_length = 0 for line in csvfile: @@ -310,29 +311,24 @@ class UploadNotesForm(forms.Form): name = line[0] if name.lower() in ["rôle", "juré", "moyenne", "coefficient", "sous-total", "équipe", "equipe"]: continue - notes = line[1:line_length] + notes = line[2:line_length] if not all(s.isnumeric() or s[0] == '-' and s[1:].isnumeric() for s in notes): continue notes = list(map(int, notes)) - max_notes = pool_size * ([20, 16, 9, 10, 9, 10] + ([4] if pool_size == 4 else [])) + max_notes = pool_size * ([20, 20, 10, 10, 10, 10] + ([4] if pool_size == 4 else [])) for n, max_n in zip(notes, max_notes): if n > max_n: self.add_error('file', _("The following note is higher of the maximum expected value:") + str(n) + " > " + str(max_n)) - # Search by "{first_name} {last_name}" - jury = User.objects.annotate(full_name=Concat('first_name', Value(' '), 'last_name', - output_field=CharField())) \ - .filter(full_name=name.replace('’', '\''), registration__volunteerregistration__isnull=False) + # Search by volunteer id + jury = VolunteerRegistration.objects.filter(pk=line[1]) if jury.count() != 1: - self.add_error('file', _("The following user was not found:") + " " + name) - continue + raise ValidationError({'file': _("The following user was not found:") + " " + name}) jury = jury.get() - - vr = jury.registration - parsed_notes[vr] = notes + parsed_notes[jury] = notes cleaned_data['parsed_notes'] = parsed_notes diff --git a/participation/models.py b/participation/models.py index 8a69cbd..558d5a6 100644 --- a/participation/models.py +++ b/participation/models.py @@ -680,7 +680,7 @@ class Passage(models.Model): @property def average_defender(self) -> float: - return self.average_defender_writing + (2 - 0.5 * self.defender_penalties) * self.average_defender_oral + return self.average_defender_writing + (1.6 - 0.4 * self.defender_penalties) * self.average_defender_oral @property def average_opponent_writing(self) -> float: @@ -692,7 +692,7 @@ class Passage(models.Model): @property def average_opponent(self) -> float: - return self.average_opponent_writing + 2 * self.average_opponent_oral + return 0.9 * self.average_opponent_writing + 2 * self.average_opponent_oral @property def average_reporter_writing(self) -> float: @@ -704,7 +704,7 @@ class Passage(models.Model): @property def average_reporter(self) -> float: - return self.average_reporter_writing + self.average_reporter_oral + return 0.9 * self.average_reporter_writing + self.average_reporter_oral @property def average_observer(self) -> float: diff --git a/participation/views.py b/participation/views.py index 949ebfe..5eb8497 100644 --- a/participation/views.py +++ b/participation/views.py @@ -1176,6 +1176,10 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView): first_col_style.addElement(TableColumnProperties(columnwidth="9cm", breakbefore="auto")) doc.automaticstyles.addElement(first_col_style) + jury_id_style = Style(name="co_jury_id", family="table-column") + jury_id_style.addElement(TableColumnProperties(columnwidth="1cm", breakbefore="auto")) + doc.automaticstyles.addElement(jury_id_style) + col_style = Style(name="co2", family="table-column") col_style.addElement(TableColumnProperties(columnwidth="2.6cm", breakbefore="auto")) doc.automaticstyles.addElement(col_style) @@ -1188,6 +1192,7 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView): doc.spreadsheet.addElement(table) table.addElement(TableColumn(stylename=first_col_style)) + table.addElement(TableColumn(stylename=jury_id_style)) for i in range(line_length): table.addElement(TableColumn(stylename=obs_col_style if pool_size == 4 @@ -1198,7 +1203,9 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView): table.addElement(header_pb) problems_tc = TableCell(valuetype="string", stylename=title_style_topleft) problems_tc.addElement(P(text="Problème")) + problems_tc.setAttribute('numbercolumnsspanned', "2") header_pb.addElement(problems_tc) + header_pb.addElement(CoveredTableCell()) for passage in self.object.passages.all(): tc = TableCell(valuetype="string", stylename=title_style_topleftright) tc.addElement(P(text=f"Problème {passage.solution_number}")) @@ -1212,7 +1219,9 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView): table.addElement(header_role) role_tc = TableCell(valuetype="string", stylename=title_style_left) role_tc.addElement(P(text="Rôle")) + role_tc.setAttribute('numbercolumnsspanned', "2") header_role.addElement(role_tc) + header_role.addElement(CoveredTableCell()) for i in range(pool_size): defender_tc = TableCell(valuetype="string", stylename=title_style_left) defender_tc.addElement(P(text="Défenseur⋅se")) @@ -1243,7 +1252,9 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView): table.addElement(header_notes) jury_tc = TableCell(valuetype="string", value="Juré⋅e", stylename=title_style_botleft) jury_tc.addElement(P(text="Juré⋅e")) + jury_tc.setAttribute('numbercolumnsspanned', "2") header_notes.addElement(jury_tc) + header_notes.addElement(CoveredTableCell()) for i in range(pool_size): defender_w_tc = TableCell(valuetype="string", stylename=title_style_botleft) @@ -1251,11 +1262,11 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView): header_notes.addElement(defender_w_tc) defender_o_tc = TableCell(valuetype="string", stylename=title_style_bot) - defender_o_tc.addElement(P(text="Oral (/16)")) + defender_o_tc.addElement(P(text="Oral (/20)")) header_notes.addElement(defender_o_tc) opponent_w_tc = TableCell(valuetype="string", stylename=title_style_bot) - opponent_w_tc.addElement(P(text="Écrit (/9)")) + opponent_w_tc.addElement(P(text="Écrit (/10)")) header_notes.addElement(opponent_w_tc) opponent_o_tc = TableCell(valuetype="string", stylename=title_style_bot) @@ -1263,7 +1274,7 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView): header_notes.addElement(opponent_o_tc) reporter_w_tc = TableCell(valuetype="string", stylename=title_style_bot) - reporter_w_tc.addElement(P(text="Écrit (/9)")) + reporter_w_tc.addElement(P(text="Écrit (/10)")) header_notes.addElement(reporter_w_tc) reporter_o_tc = TableCell(valuetype="string", @@ -1285,6 +1296,9 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView): name_tc = TableCell(valuetype="string", stylename=style_leftright) name_tc.addElement(P(text=f"{jury.user.first_name} {jury.user.last_name}")) jury_row.addElement(name_tc) + jury_id_tc = TableCell(valuetype="float", value=jury.pk, stylename=style_leftright) + jury_id_tc.addElement(P(text=str(jury.pk))) + jury_row.addElement(jury_id_tc) for passage in self.object.passages.all(): notes = Note.objects.get(jury=jury, passage=passage) @@ -1297,14 +1311,16 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView): jury_size = self.object.juries.count() min_row = 4 max_row = 4 + jury_size - 1 - min_column = 2 + min_column = 3 # Add line for averages average_row = TableRow() table.addElement(average_row) average_tc = TableCell(valuetype="string", stylename=title_style_topleftright) average_tc.addElement(P(text="Moyenne")) + average_tc.setAttribute('numbercolumnsspanned', "2") average_row.addElement(average_tc) + average_row.addElement(CoveredTableCell()) for i, passage in enumerate(self.object.passages.all()): for j, note in enumerate(passage.averages): tc = TableCell(valuetype="float", value=note, @@ -1321,17 +1337,19 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView): table.addElement(coeff_row) coeff_tc = TableCell(valuetype="string", stylename=title_style_leftright) coeff_tc.addElement(P(text="Coefficient")) + coeff_tc.setAttribute('numbercolumnsspanned', "2") coeff_row.addElement(coeff_tc) + coeff_row.addElement(CoveredTableCell()) for passage in self.object.passages.all(): defender_w_tc = TableCell(valuetype="float", value=1, stylename=style_left) defender_w_tc.addElement(P(text="1")) coeff_row.addElement(defender_w_tc) - defender_o_tc = TableCell(valuetype="float", value=2 - 0.5 * passage.defender_penalties, stylename=style) - defender_o_tc.addElement(P(text=str(2 - 0.5 * passage.defender_penalties))) + defender_o_tc = TableCell(valuetype="float", value=1.6 - 0.4 * passage.defender_penalties, stylename=style) + defender_o_tc.addElement(P(text=str(2 - 0.4 * passage.defender_penalties))) coeff_row.addElement(defender_o_tc) - opponent_w_tc = TableCell(valuetype="float", value=1, stylename=style) + opponent_w_tc = TableCell(valuetype="float", value=0.9, stylename=style) opponent_w_tc.addElement(P(text="1")) coeff_row.addElement(opponent_w_tc) @@ -1339,7 +1357,7 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView): opponent_o_tc.addElement(P(text="2")) coeff_row.addElement(opponent_o_tc) - reporter_w_tc = TableCell(valuetype="float", value=1, stylename=style) + reporter_w_tc = TableCell(valuetype="float", value=0.9, stylename=style) reporter_w_tc.addElement(P(text="1")) coeff_row.addElement(reporter_w_tc) @@ -1358,7 +1376,9 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView): table.addElement(subtotal_row) subtotal_tc = TableCell(valuetype="string", stylename=title_style_botleft) subtotal_tc.addElement(P(text="Sous-total")) + subtotal_tc.setAttribute('numbercolumnsspanned', "2") subtotal_row.addElement(subtotal_tc) + subtotal_row.addElement(CoveredTableCell()) for i, passage in enumerate(self.object.passages.all()): def_w_col = getcol(min_column + passage_width * i) def_o_col = getcol(min_column + passage_width * i + 1) @@ -1406,6 +1426,7 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView): table.addElement(scores_header) team_tc = TableCell(valuetype="string", stylename=title_style_topbotleft) team_tc.addElement(P(text="Équipe")) + team_tc.setAttribute('numbercolumnsspanned', "2") scores_header.addElement(team_tc) problem_tc = TableCell(valuetype="string", stylename=title_style_topbot) problem_tc.addElement(P(text="Problème")) @@ -1452,6 +1473,7 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView): team_tc = TableCell(valuetype="string", stylename=style_botleft if passage.position == pool_size else style_left) team_tc.addElement(P(text=f"{passage.defender.team.name} ({passage.defender.team.trigram})")) + team_tc.setAttribute('numbercolumnsspanned', "2") team_row.addElement(team_tc) problem_tc = TableCell(valuetype="string",