Compare commits

...

7 Commits

Author SHA1 Message Date
Emmy D'Anello 10a42d3633
Only harmonize valid participations
Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
2024-03-31 22:12:54 +02:00
Emmy D'Anello bb579d640c
Add buttons to hide notes from public if needed
Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
2024-03-31 22:11:01 +02:00
Emmy D'Anello d7b4233282
Rapporteure -> Rapportrice
Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
2024-03-31 21:47:14 +02:00
Emmy D'Anello 9092cf1846
Improve edit buttons
Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
2024-03-31 21:36:09 +02:00
Emmy D'Anello 37b86d4ea0
Better download link to the ODS file
Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
2024-03-31 21:23:57 +02:00
Emmy D'Anello 40988348d3
Upload notes to Google Sheets after uploading a CSV file
Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
2024-03-31 20:59:00 +02:00
Emmy D'Anello 1cbf95e6e1
Display at least our notes in the notes table
Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
2024-03-31 20:56:49 +02:00
10 changed files with 581 additions and 412 deletions

File diff suppressed because it is too large Load Diff

View File

@ -128,7 +128,7 @@ class ValidateParticipationForm(forms.Form):
class TournamentForm(forms.ModelForm):
class Meta:
model = Tournament
fields = '__all__'
exclude = ('notes_sheet_id', )
widgets = {
'date_start': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
'date_end': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),

View File

@ -928,7 +928,7 @@ class Pool(models.Model):
header = [
sum(([f"Problème {passage.solution_number}"] + (passage_width - 1) * [""]
for passage in passages), start=["Problème", ""]),
sum((["Défenseur⋅se", "", "Opposant⋅e", "", "Rapporteur⋅e", ""]
sum((["Défenseur⋅se", "", "Opposant⋅e", "", "Rapporteur⋅rice", ""]
+ (["Observateur⋅rice"] if pool_size == 4 else [])
for _passage in passages), start=["Rôle", ""]),
sum((["Écrit (/20)", "Oral (/20)", "Écrit (/10)", "Oral (/10)", "Écrit (/10)", "Oral (/10)"]

View File

@ -6,7 +6,16 @@
{% trans "any" as any %}
<div class="card bg-body shadow">
<div class="card-header text-center">
<h4>{{ passage }}</h4>
<h4>
{{ passage }}
{% if user.registration.is_admin or user.registration in passage.pool.tournament.organizers.all %}
<button class="btn btn-sm btn-secondary"
data-bs-toggle="modal" data-bs-target="#updatePassageModal">
<i class="fas fa-edit"></i>
{% trans "Update" %}
</button>
{% endif %}
</h4>
</div>
<div class="card-body">
<dl class="row">
@ -51,7 +60,6 @@
{% if my_note is not None %}
<button class="btn btn-info" data-bs-toggle="modal" data-bs-target="#{{ my_note.modal_name }}Modal">{% trans "Update notes" %}</button>
{% endif %}
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#updatePassageModal">{% trans "Update" %}</button>
</div>
{% elif user.registration.participates %}
<div class="card-footer text-center">

View File

@ -5,7 +5,15 @@
{% block content %}
<div class="card bg-body shadow">
<div class="card-header text-center">
<h4>{{ pool }}</h4>
<h4>
{{ pool }}
{% if user.registration.is_admin or user.registration in pool.tournament.organizers.all %}
<button class="btn btn-sm btn-secondary" data-bs-toggle="modal" data-bs-target="#updatePoolModal">
<i class="fas fa-edit"></i>
{% trans "Update" %}
</button>
{% endif %}
</h4>
</div>
<div class="card-body">
<dl class="row">
@ -62,14 +70,44 @@
</a>
</dd>
<dt class="col-sm-3">{% trans "BigBlueButton link:" %}</dt>
<dd class="col-sm-9">{{ pool.bbb_url|urlize }}</dd>
{% if pool.bbb_url %}
<dt class="col-sm-3">{% trans "BigBlueButton link:" %}</dt>
<dd class="col-sm-9">{{ pool.bbb_url|urlize }}</dd>
{% endif %}
{% if user.registration.is_admin or user.registration.is_volunteer %}
{% if user.registration.is_admin or user.registration in pool.tournament.organizers.all or user.registration == pool.jury_president %}
<dt class="col-sm-3">{% trans "Notation sheet:" %}</dt>
<dt class="col-sm-3">{% trans "Notation sheets:" %}</dt>
<dd class="col-sm-9">
<a class="btn btn-success" href="https://docs.google.com/spreadsheets/d/{{ pool.tournament.notes_sheet_id }}/edit">
<div class="btn-group">
<a class="btn btn-sm btn-info" href="{% url 'participation:pool_scale_note_sheet' pk=pool.pk %}">
<i class="fas fa-download"></i>
{% trans "Download the scale sheet" %}{% if pool.passages.count == 5 %} — {% trans "Room" %} 1{% endif %}
</a>
{% if pool.passages.count == 5 %}
<a class="btn btn-info" href="{% url 'participation:pool_scale_note_sheet' pk=pool.pk %}?page=2">
{% trans "Room" %} 2
</a>
{% endif %}
<a class="btn btn-sm btn-info" href="{% url 'participation:pool_final_note_sheet' pk=pool.pk %}">
<i class="fas fa-download"></i>
{% trans "Download the final notation sheet" %}{% if pool.passages.count == 5 %} — {% trans "Room" %} 1{% endif %}
</a>
{% if pool.passages.count == 5 %}
<a class="btn btn-sm btn-info" href="{% url 'participation:pool_final_note_sheet' pk=pool.pk %}?page=2">
{% trans "Room" %} 2
</a>
{% endif %}
<a class="btn btn-sm btn-info" href="{% url 'participation:pool_notation_sheets' pool_id=pool.id %}">
<i class="fas fa-archive"></i>
{% trans "Download all notation sheets" %}
</a>
</div>
</dd>
<dt class="col-sm-3">{% trans "Google Sheets Spreadsheet:" %}</dt>
<dd class="col-sm-9">
<a class="btn btn-sm btn-success" href="https://docs.google.com/spreadsheets/d/{{ pool.tournament.notes_sheet_id }}/edit">
<i class="fas fa-table"></i>
{% trans "Go to the Google Sheets page of the pool" %}
</a>
@ -89,45 +127,24 @@
{% endfor %}
</ul>
</div>
{% if user.registration.is_volunteer %}
<div class="card-footer text-center">
<div class="btn-group">
<a class="btn btn-sm btn-info" href="{% url 'participation:pool_scale_note_sheet' pk=pool.pk %}">
<i class="fas fa-download"></i>
{% trans "Download the scale sheet" %}{% if pool.passages.count == 5 %} — {% trans "Room" %} 1{% endif %}
</a>
{% if pool.passages.count == 5 %}
<a class="btn btn-info" href="{% url 'participation:pool_scale_note_sheet' pk=pool.pk %}?page=2">
{% trans "Room" %} 2
{% if user.registration.is_admin or user.registration.is_volunteer %}
{% if user.registration.is_admin or user.registration in pool.tournament.organizers.all or user.registration == pool.jury_president %}
<div class="card-footer text-center">
<div class="btn btn-group">
<button class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#uploadNotesModal">
<i class="fas fa-upload"></i>
{% trans "Upload notes from a CSV file" %}
</button>
<a class="btn btn-sm btn-info" href="{% url 'participation:pool_notes_template' pk=pool.pk %}">
<i class="fas fa-download"></i>
{% trans "Download notation spreadsheet" %}
</a>
{% endif %}
<a class="btn btn-sm btn-info" href="{% url 'participation:pool_final_note_sheet' pk=pool.pk %}">
<i class="fas fa-download"></i>
{% trans "Download the final notation sheet" %}{% if pool.passages.count == 5 %} — {% trans "Room" %} 1{% endif %}
</a>
{% if pool.passages.count == 5 %}
<a class="btn btn-sm btn-info" href="{% url 'participation:pool_final_note_sheet' pk=pool.pk %}?page=2">
{% trans "Room" %} 2
</a>
{% endif %}
<a class="btn btn-sm btn-info" href="{% url 'participation:pool_notation_sheets' pool_id=pool.id %}">
<i class="fas fa-archive"></i>
{% trans "Download all notation sheets" %}
</a>
</div>
</div>
<button class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#uploadNotesModal">
<i class="fas fa-upload"></i>
{% trans "Upload notes from a CSV file" %}
</button>
</div>
{% endif %}
{% endif %}
</div>
</div>
{% if user.registration.is_volunteer %}
<div class="card-footer text-center">
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#updatePoolModal">{% trans "Update" %}</button>
</div>
{% endif %}
</div>
<hr>

View File

@ -61,7 +61,10 @@
{% if user.registration.is_admin or user.registration in tournament.organizers.all %}
<div class="card-footer text-center">
<a href="{% url "participation:tournament_update" pk=tournament.pk %}"><button class="btn btn-secondary">{% trans "Edit tournament" %}</button></a>
<a class="btn btn-secondary" href="{% url "participation:tournament_update" pk=tournament.pk %}">
<i class="fas fa-edit"></i>
{% trans "Edit tournament" %}
</a>
</div>
{% endif %}
</div>
@ -106,22 +109,6 @@
</div>
{% if user.registration.is_admin or user.registration in tournament.organizers.all %}
<div class="card-footer text-center">
{% if not available_notes_1 or not available_notes_2 %}
<div class="btn-group">
{% if not available_notes_1 %}
<a href="{% url 'participation:tournament_publish_notes' pk=tournament.pk round=1 %}" class="btn btn-info">
<i class="fas fa-upload"></i>
{% trans "Publish notes for first round" %}
</a>
{% endif %}
{% if not available_notes_2 %}
<a href="{% url 'participation:tournament_publish_notes' pk=tournament.pk round=2 %}" class="btn btn-info">
<i class="fas fa-upload"></i>
{% trans "Publish notes for second round" %}
</a>
{% endif %}
</div>
{% endif %}
<div class="btn-group">
<a href="{% url 'participation:tournament_harmonize' pk=tournament.pk round=1 %}" class="btn btn-secondary">
<i class="fas fa-ranking-star"></i>
@ -133,6 +120,32 @@
</a>
</div>
</div>
<div class="card-footer text-center">
<div class="btn-group">
{% if not available_notes_1 %}
<a href="{% url 'participation:tournament_publish_notes' pk=tournament.pk round=1 %}" class="btn btn-sm btn-info">
<i class="fas fa-eye"></i>
{% trans "Publish notes for first round" %}
</a>
{% else %}
<a href="{% url 'participation:tournament_publish_notes' pk=tournament.pk round=1 %}?hide" class="btn btn-sm btn-danger">
<i class="fas fa-eye-slash"></i>
{% trans "Unpublish notes for first round" %}
</a>
{% endif %}
{% if not available_notes_2 %}
<a href="{% url 'participation:tournament_publish_notes' pk=tournament.pk round=2 %}" class="btn btn-sm btn-info">
<i class="fas fa-eye"></i>
{% trans "Publish notes for second round" %}
</a>
{% else %}
<a href="{% url 'participation:tournament_publish_notes' pk=tournament.pk round=2 %}?hide" class="btn btn-sm btn-danger">
<i class="fas fa-eye-slash"></i>
{% trans "Unpublish notes for second round" %}
</a>
{% endif %}
</div>
</div>
{% endif %}
</div>
{% endif %}

View File

@ -6,9 +6,17 @@
{% block content %}
<form method="post" enctype="multipart/form-data">
<div id="form-content">
<div class="alert alert-warning">
{% url 'participation:pool_jury' pk=pool.jury as jury_url %}
{% blocktrans trimmed with jury_url=jury_url %}
Remember to export your spreadsheet as a CSV file before uploading it here.
Rows that are full of zeros are ignored.
Unknown juries are not considered.
{% endblocktrans %}
</div>
<div class="alert alert-info">
<a class="alert-link" href="{% url "participation:pool_notes_template" pk=pool.pk %}">
{% trans "Download empty notation sheet" %}
{% trans "Download empty notation sheet" %}
</a>
</div>
{% csrf_token %}

View File

@ -703,8 +703,11 @@ class TournamentPublishNotesView(VolunteerMixin, SingleObjectMixin, RedirectView
raise Http404
tournament = Tournament.objects.get(pk=kwargs["pk"])
tournament.pools.filter(round=kwargs["round"]).update(results_available=True)
messages.success(request, _("Notes published!"))
tournament.pools.filter(round=kwargs["round"]).update(results_available='hide' not in request.GET)
if 'hide' not in request.GET:
messages.success(request, _("Notes published!"))
else:
messages.success(request, _("Notes hidden!"))
return super().get(request, *args, **kwargs)
def get_redirect_url(self, *args, **kwargs):
@ -739,7 +742,7 @@ class TournamentHarmonizeView(VolunteerMixin, DetailView):
.format(tournament=tournament, round=context["round"])
notes = dict()
for participation in self.object.participations.all():
for participation in self.object.participations.filter(valid=True).all():
note = sum(pool.average(participation) for pool in context['pools'])
tweak = sum(tweak.diff for tweak in participation.tweaks.filter(pool__in=context['pools']).all())
notes[participation] = {'note': note, 'tweak': tweak}
@ -759,13 +762,14 @@ class TournamentHarmonizeNoteView(VolunteerMixin, DetailView):
if not reg.is_admin and (not reg.is_volunteer or tournament not in reg.organized_tournaments.all()):
return self.handle_no_permission()
if self.kwargs['round'] not in (1, 2) or self.kwargs['action'] not in ('add', 'remove') \
or self.kwargs['trigram'] not in [p.team.trigram for p in tournament.participations.all()]:
or self.kwargs['trigram'] not in [p.team.trigram
for p in tournament.participations.filter(valid=True).all()]:
raise Http404
return super().dispatch(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
tournament = self.get_object()
participation = tournament.participations.get(team__trigram=kwargs['trigram'])
participation = tournament.participations.filter(valid=True).get(team__trigram=kwargs['trigram'])
pool = tournament.pools.get(round=kwargs['round'], participations=participation)
tweak_qs = Tweak.objects.filter(participation=participation, pool=pool)
old_diff = tweak_qs.first().diff if tweak_qs.exists() else 0
@ -1177,6 +1181,9 @@ class PoolUploadNotesView(VolunteerMixin, FormView, DetailView):
note.set_all(*list(map(int, passage_notes)))
note.save()
if os.getenv('GOOGLE_PRIVATE_KEY_ID', None):
pool.update_notes_spreadsheet()
messages.success(self.request, _("Notes were successfully uploaded."))
return super().form_valid(form)
@ -1428,7 +1435,7 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
reporter_tc = TableCell(valuetype="string",
stylename=title_style_right if pool_size != 4 else title_style)
reporter_tc.addElement(P(text="Rapporteur⋅e"))
reporter_tc.addElement(P(text="Rapporteur⋅rice"))
reporter_tc.setAttribute('numbercolumnsspanned', "2")
header_role.addElement(reporter_tc)
header_role.addElement(CoveredTableCell())
@ -1892,9 +1899,9 @@ class PassageDetailView(LoginRequiredMixin, DetailView):
if reg.is_volunteer:
notes = self.object.notes.all()
if not reg.is_admin \
or (reg != self.object.pool.jury_president
and reg not in self.object.pool.tournament.organizers.all()):
notes = [note for note in notes if note.has_any_note()]
and (reg != self.object.pool.jury_president
or reg not in self.object.pool.tournament.organizers.all()):
notes = [note for note in notes if note.has_any_note() or note.jury == reg]
context["notes"] = NoteTable(notes)
# Only display the observer column for 4-teams pools

Binary file not shown.

View File

@ -53,7 +53,7 @@ Problème \underline{~~~~} défendu par l'équipe \underline{~~~~~~~~~~~~~~~~~~~
\medskip
Synthèse par l'équipe \underline{~~~~~~~~~~~~~~~~~~~~~~~~~~~~} dans le rôle de : ~ $\square$ Opposante ~ $\square$ Rapporteure
Synthèse par l'équipe \underline{~~~~~~~~~~~~~~~~~~~~~~~~~~~~} dans le rôle de : ~ $\square$ Opposante ~ $\square$ Rapportrice
\section*{\'Evaluation question par question de la solution}