mirror of
https://gitlab.com/animath/si/plateforme.git
synced 2024-12-25 06:22:22 +00:00
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 django.utils.translation import gettext_lazy as _
|
||||||
from pypdf import PdfReader
|
from pypdf import PdfReader
|
||||||
|
|
||||||
|
from registration.models import VolunteerRegistration
|
||||||
from .models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament
|
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):
|
def process(self, csvfile: Iterable[str], cleaned_data: dict):
|
||||||
parsed_notes = {}
|
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
|
pool_size = 0
|
||||||
line_length = 0
|
line_length = 0
|
||||||
for line in csvfile:
|
for line in csvfile:
|
||||||
@ -310,29 +311,24 @@ class UploadNotesForm(forms.Form):
|
|||||||
name = line[0]
|
name = line[0]
|
||||||
if name.lower() in ["rôle", "juré", "moyenne", "coefficient", "sous-total", "équipe", "equipe"]:
|
if name.lower() in ["rôle", "juré", "moyenne", "coefficient", "sous-total", "équipe", "equipe"]:
|
||||||
continue
|
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):
|
if not all(s.isnumeric() or s[0] == '-' and s[1:].isnumeric() for s in notes):
|
||||||
continue
|
continue
|
||||||
notes = list(map(int, notes))
|
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):
|
for n, max_n in zip(notes, max_notes):
|
||||||
if n > max_n:
|
if n > max_n:
|
||||||
self.add_error('file',
|
self.add_error('file',
|
||||||
_("The following note is higher of the maximum expected value:")
|
_("The following note is higher of the maximum expected value:")
|
||||||
+ str(n) + " > " + str(max_n))
|
+ str(n) + " > " + str(max_n))
|
||||||
|
|
||||||
# Search by "{first_name} {last_name}"
|
# Search by volunteer id
|
||||||
jury = User.objects.annotate(full_name=Concat('first_name', Value(' '), 'last_name',
|
jury = VolunteerRegistration.objects.filter(pk=line[1])
|
||||||
output_field=CharField())) \
|
|
||||||
.filter(full_name=name.replace('’', '\''), registration__volunteerregistration__isnull=False)
|
|
||||||
if jury.count() != 1:
|
if jury.count() != 1:
|
||||||
self.add_error('file', _("The following user was not found:") + " " + name)
|
raise ValidationError({'file': _("The following user was not found:") + " " + name})
|
||||||
continue
|
|
||||||
jury = jury.get()
|
jury = jury.get()
|
||||||
|
parsed_notes[jury] = notes
|
||||||
vr = jury.registration
|
|
||||||
parsed_notes[vr] = notes
|
|
||||||
|
|
||||||
cleaned_data['parsed_notes'] = parsed_notes
|
cleaned_data['parsed_notes'] = parsed_notes
|
||||||
|
|
||||||
|
@ -680,7 +680,7 @@ class Passage(models.Model):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def average_defender(self) -> float:
|
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
|
@property
|
||||||
def average_opponent_writing(self) -> float:
|
def average_opponent_writing(self) -> float:
|
||||||
@ -692,7 +692,7 @@ class Passage(models.Model):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def average_opponent(self) -> float:
|
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
|
@property
|
||||||
def average_reporter_writing(self) -> float:
|
def average_reporter_writing(self) -> float:
|
||||||
@ -704,7 +704,7 @@ class Passage(models.Model):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def average_reporter(self) -> float:
|
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
|
@property
|
||||||
def average_observer(self) -> float:
|
def average_observer(self) -> float:
|
||||||
|
@ -1176,6 +1176,10 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
first_col_style.addElement(TableColumnProperties(columnwidth="9cm", breakbefore="auto"))
|
first_col_style.addElement(TableColumnProperties(columnwidth="9cm", breakbefore="auto"))
|
||||||
doc.automaticstyles.addElement(first_col_style)
|
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 = Style(name="co2", family="table-column")
|
||||||
col_style.addElement(TableColumnProperties(columnwidth="2.6cm", breakbefore="auto"))
|
col_style.addElement(TableColumnProperties(columnwidth="2.6cm", breakbefore="auto"))
|
||||||
doc.automaticstyles.addElement(col_style)
|
doc.automaticstyles.addElement(col_style)
|
||||||
@ -1188,6 +1192,7 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
doc.spreadsheet.addElement(table)
|
doc.spreadsheet.addElement(table)
|
||||||
|
|
||||||
table.addElement(TableColumn(stylename=first_col_style))
|
table.addElement(TableColumn(stylename=first_col_style))
|
||||||
|
table.addElement(TableColumn(stylename=jury_id_style))
|
||||||
|
|
||||||
for i in range(line_length):
|
for i in range(line_length):
|
||||||
table.addElement(TableColumn(stylename=obs_col_style if pool_size == 4
|
table.addElement(TableColumn(stylename=obs_col_style if pool_size == 4
|
||||||
@ -1198,7 +1203,9 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
table.addElement(header_pb)
|
table.addElement(header_pb)
|
||||||
problems_tc = TableCell(valuetype="string", stylename=title_style_topleft)
|
problems_tc = TableCell(valuetype="string", stylename=title_style_topleft)
|
||||||
problems_tc.addElement(P(text="Problème"))
|
problems_tc.addElement(P(text="Problème"))
|
||||||
|
problems_tc.setAttribute('numbercolumnsspanned', "2")
|
||||||
header_pb.addElement(problems_tc)
|
header_pb.addElement(problems_tc)
|
||||||
|
header_pb.addElement(CoveredTableCell())
|
||||||
for passage in self.object.passages.all():
|
for passage in self.object.passages.all():
|
||||||
tc = TableCell(valuetype="string", stylename=title_style_topleftright)
|
tc = TableCell(valuetype="string", stylename=title_style_topleftright)
|
||||||
tc.addElement(P(text=f"Problème {passage.solution_number}"))
|
tc.addElement(P(text=f"Problème {passage.solution_number}"))
|
||||||
@ -1212,7 +1219,9 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
table.addElement(header_role)
|
table.addElement(header_role)
|
||||||
role_tc = TableCell(valuetype="string", stylename=title_style_left)
|
role_tc = TableCell(valuetype="string", stylename=title_style_left)
|
||||||
role_tc.addElement(P(text="Rôle"))
|
role_tc.addElement(P(text="Rôle"))
|
||||||
|
role_tc.setAttribute('numbercolumnsspanned', "2")
|
||||||
header_role.addElement(role_tc)
|
header_role.addElement(role_tc)
|
||||||
|
header_role.addElement(CoveredTableCell())
|
||||||
for i in range(pool_size):
|
for i in range(pool_size):
|
||||||
defender_tc = TableCell(valuetype="string", stylename=title_style_left)
|
defender_tc = TableCell(valuetype="string", stylename=title_style_left)
|
||||||
defender_tc.addElement(P(text="Défenseur⋅se"))
|
defender_tc.addElement(P(text="Défenseur⋅se"))
|
||||||
@ -1243,7 +1252,9 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
table.addElement(header_notes)
|
table.addElement(header_notes)
|
||||||
jury_tc = TableCell(valuetype="string", value="Juré⋅e", stylename=title_style_botleft)
|
jury_tc = TableCell(valuetype="string", value="Juré⋅e", stylename=title_style_botleft)
|
||||||
jury_tc.addElement(P(text="Juré⋅e"))
|
jury_tc.addElement(P(text="Juré⋅e"))
|
||||||
|
jury_tc.setAttribute('numbercolumnsspanned', "2")
|
||||||
header_notes.addElement(jury_tc)
|
header_notes.addElement(jury_tc)
|
||||||
|
header_notes.addElement(CoveredTableCell())
|
||||||
|
|
||||||
for i in range(pool_size):
|
for i in range(pool_size):
|
||||||
defender_w_tc = TableCell(valuetype="string", stylename=title_style_botleft)
|
defender_w_tc = TableCell(valuetype="string", stylename=title_style_botleft)
|
||||||
@ -1251,11 +1262,11 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
header_notes.addElement(defender_w_tc)
|
header_notes.addElement(defender_w_tc)
|
||||||
|
|
||||||
defender_o_tc = TableCell(valuetype="string", stylename=title_style_bot)
|
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)
|
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="Écrit (/9)"))
|
opponent_w_tc.addElement(P(text="Écrit (/10)"))
|
||||||
header_notes.addElement(opponent_w_tc)
|
header_notes.addElement(opponent_w_tc)
|
||||||
|
|
||||||
opponent_o_tc = TableCell(valuetype="string", stylename=title_style_bot)
|
opponent_o_tc = TableCell(valuetype="string", stylename=title_style_bot)
|
||||||
@ -1263,7 +1274,7 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
header_notes.addElement(opponent_o_tc)
|
header_notes.addElement(opponent_o_tc)
|
||||||
|
|
||||||
reporter_w_tc = TableCell(valuetype="string", stylename=title_style_bot)
|
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)
|
header_notes.addElement(reporter_w_tc)
|
||||||
|
|
||||||
reporter_o_tc = TableCell(valuetype="string",
|
reporter_o_tc = TableCell(valuetype="string",
|
||||||
@ -1285,6 +1296,9 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
name_tc = TableCell(valuetype="string", stylename=style_leftright)
|
name_tc = TableCell(valuetype="string", stylename=style_leftright)
|
||||||
name_tc.addElement(P(text=f"{jury.user.first_name} {jury.user.last_name}"))
|
name_tc.addElement(P(text=f"{jury.user.first_name} {jury.user.last_name}"))
|
||||||
jury_row.addElement(name_tc)
|
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():
|
for passage in self.object.passages.all():
|
||||||
notes = Note.objects.get(jury=jury, passage=passage)
|
notes = Note.objects.get(jury=jury, passage=passage)
|
||||||
@ -1297,14 +1311,16 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
jury_size = self.object.juries.count()
|
jury_size = self.object.juries.count()
|
||||||
min_row = 4
|
min_row = 4
|
||||||
max_row = 4 + jury_size - 1
|
max_row = 4 + jury_size - 1
|
||||||
min_column = 2
|
min_column = 3
|
||||||
|
|
||||||
# Add line for averages
|
# Add line for averages
|
||||||
average_row = TableRow()
|
average_row = TableRow()
|
||||||
table.addElement(average_row)
|
table.addElement(average_row)
|
||||||
average_tc = TableCell(valuetype="string", stylename=title_style_topleftright)
|
average_tc = TableCell(valuetype="string", stylename=title_style_topleftright)
|
||||||
average_tc.addElement(P(text="Moyenne"))
|
average_tc.addElement(P(text="Moyenne"))
|
||||||
|
average_tc.setAttribute('numbercolumnsspanned', "2")
|
||||||
average_row.addElement(average_tc)
|
average_row.addElement(average_tc)
|
||||||
|
average_row.addElement(CoveredTableCell())
|
||||||
for i, passage in enumerate(self.object.passages.all()):
|
for i, passage in enumerate(self.object.passages.all()):
|
||||||
for j, note in enumerate(passage.averages):
|
for j, note in enumerate(passage.averages):
|
||||||
tc = TableCell(valuetype="float", value=note,
|
tc = TableCell(valuetype="float", value=note,
|
||||||
@ -1321,17 +1337,19 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
table.addElement(coeff_row)
|
table.addElement(coeff_row)
|
||||||
coeff_tc = TableCell(valuetype="string", stylename=title_style_leftright)
|
coeff_tc = TableCell(valuetype="string", stylename=title_style_leftright)
|
||||||
coeff_tc.addElement(P(text="Coefficient"))
|
coeff_tc.addElement(P(text="Coefficient"))
|
||||||
|
coeff_tc.setAttribute('numbercolumnsspanned', "2")
|
||||||
coeff_row.addElement(coeff_tc)
|
coeff_row.addElement(coeff_tc)
|
||||||
|
coeff_row.addElement(CoveredTableCell())
|
||||||
for passage in self.object.passages.all():
|
for passage in self.object.passages.all():
|
||||||
defender_w_tc = TableCell(valuetype="float", value=1, stylename=style_left)
|
defender_w_tc = TableCell(valuetype="float", value=1, stylename=style_left)
|
||||||
defender_w_tc.addElement(P(text="1"))
|
defender_w_tc.addElement(P(text="1"))
|
||||||
coeff_row.addElement(defender_w_tc)
|
coeff_row.addElement(defender_w_tc)
|
||||||
|
|
||||||
defender_o_tc = TableCell(valuetype="float", value=2 - 0.5 * passage.defender_penalties, stylename=style)
|
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.5 * passage.defender_penalties)))
|
defender_o_tc.addElement(P(text=str(2 - 0.4 * passage.defender_penalties)))
|
||||||
coeff_row.addElement(defender_o_tc)
|
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"))
|
opponent_w_tc.addElement(P(text="1"))
|
||||||
coeff_row.addElement(opponent_w_tc)
|
coeff_row.addElement(opponent_w_tc)
|
||||||
|
|
||||||
@ -1339,7 +1357,7 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
opponent_o_tc.addElement(P(text="2"))
|
opponent_o_tc.addElement(P(text="2"))
|
||||||
coeff_row.addElement(opponent_o_tc)
|
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"))
|
reporter_w_tc.addElement(P(text="1"))
|
||||||
coeff_row.addElement(reporter_w_tc)
|
coeff_row.addElement(reporter_w_tc)
|
||||||
|
|
||||||
@ -1358,7 +1376,9 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
table.addElement(subtotal_row)
|
table.addElement(subtotal_row)
|
||||||
subtotal_tc = TableCell(valuetype="string", stylename=title_style_botleft)
|
subtotal_tc = TableCell(valuetype="string", stylename=title_style_botleft)
|
||||||
subtotal_tc.addElement(P(text="Sous-total"))
|
subtotal_tc.addElement(P(text="Sous-total"))
|
||||||
|
subtotal_tc.setAttribute('numbercolumnsspanned', "2")
|
||||||
subtotal_row.addElement(subtotal_tc)
|
subtotal_row.addElement(subtotal_tc)
|
||||||
|
subtotal_row.addElement(CoveredTableCell())
|
||||||
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)
|
||||||
@ -1406,6 +1426,7 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
table.addElement(scores_header)
|
table.addElement(scores_header)
|
||||||
team_tc = TableCell(valuetype="string", stylename=title_style_topbotleft)
|
team_tc = TableCell(valuetype="string", stylename=title_style_topbotleft)
|
||||||
team_tc.addElement(P(text="Équipe"))
|
team_tc.addElement(P(text="Équipe"))
|
||||||
|
team_tc.setAttribute('numbercolumnsspanned', "2")
|
||||||
scores_header.addElement(team_tc)
|
scores_header.addElement(team_tc)
|
||||||
problem_tc = TableCell(valuetype="string", stylename=title_style_topbot)
|
problem_tc = TableCell(valuetype="string", stylename=title_style_topbot)
|
||||||
problem_tc.addElement(P(text="Problème"))
|
problem_tc.addElement(P(text="Problème"))
|
||||||
@ -1452,6 +1473,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.defender.team.name} ({passage.defender.team.trigram})"))
|
team_tc.addElement(P(text=f"{passage.defender.team.name} ({passage.defender.team.trigram})"))
|
||||||
|
team_tc.setAttribute('numbercolumnsspanned', "2")
|
||||||
team_row.addElement(team_tc)
|
team_row.addElement(team_tc)
|
||||||
|
|
||||||
problem_tc = TableCell(valuetype="string",
|
problem_tc = TableCell(valuetype="string",
|
||||||
|
Loading…
Reference in New Issue
Block a user