Update ODS note sheets
Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
parent
3465da4c36
commit
b6d54d27cd
|
@ -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
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in New Issue