mirror of
https://gitlab.com/animath/si/plateforme.git
synced 2025-02-24 07:41:19 +00:00
Compare commits
7 Commits
c4ec6a6f29
...
10a42d3633
Author | SHA1 | Date | |
---|---|---|---|
|
10a42d3633 | ||
|
bb579d640c | ||
|
d7b4233282 | ||
|
9092cf1846 | ||
|
37b86d4ea0 | ||
|
40988348d3 | ||
|
1cbf95e6e1 |
File diff suppressed because it is too large
Load Diff
@ -128,7 +128,7 @@ class ValidateParticipationForm(forms.Form):
|
|||||||
class TournamentForm(forms.ModelForm):
|
class TournamentForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Tournament
|
model = Tournament
|
||||||
fields = '__all__'
|
exclude = ('notes_sheet_id', )
|
||||||
widgets = {
|
widgets = {
|
||||||
'date_start': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
|
'date_start': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
|
||||||
'date_end': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
|
'date_end': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
|
||||||
|
@ -928,7 +928,7 @@ class Pool(models.Model):
|
|||||||
header = [
|
header = [
|
||||||
sum(([f"Problème {passage.solution_number}"] + (passage_width - 1) * [""]
|
sum(([f"Problème {passage.solution_number}"] + (passage_width - 1) * [""]
|
||||||
for passage in passages), start=["Problème", ""]),
|
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 [])
|
+ (["Observateur⋅rice"] if pool_size == 4 else [])
|
||||||
for _passage in passages), start=["Rôle", ""]),
|
for _passage in passages), start=["Rôle", ""]),
|
||||||
sum((["Écrit (/20)", "Oral (/20)", "Écrit (/10)", "Oral (/10)", "Écrit (/10)", "Oral (/10)"]
|
sum((["Écrit (/20)", "Oral (/20)", "Écrit (/10)", "Oral (/10)", "Écrit (/10)", "Oral (/10)"]
|
||||||
|
@ -6,7 +6,16 @@
|
|||||||
{% trans "any" as any %}
|
{% trans "any" as any %}
|
||||||
<div class="card bg-body shadow">
|
<div class="card bg-body shadow">
|
||||||
<div class="card-header text-center">
|
<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>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<dl class="row">
|
<dl class="row">
|
||||||
@ -51,7 +60,6 @@
|
|||||||
{% if my_note is not None %}
|
{% 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>
|
<button class="btn btn-info" data-bs-toggle="modal" data-bs-target="#{{ my_note.modal_name }}Modal">{% trans "Update notes" %}</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#updatePassageModal">{% trans "Update" %}</button>
|
|
||||||
</div>
|
</div>
|
||||||
{% elif user.registration.participates %}
|
{% elif user.registration.participates %}
|
||||||
<div class="card-footer text-center">
|
<div class="card-footer text-center">
|
||||||
|
@ -5,7 +5,15 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="card bg-body shadow">
|
<div class="card bg-body shadow">
|
||||||
<div class="card-header text-center">
|
<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>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<dl class="row">
|
<dl class="row">
|
||||||
@ -62,35 +70,15 @@
|
|||||||
</a>
|
</a>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
|
{% if pool.bbb_url %}
|
||||||
<dt class="col-sm-3">{% trans "BigBlueButton link:" %}</dt>
|
<dt class="col-sm-3">{% trans "BigBlueButton link:" %}</dt>
|
||||||
<dd class="col-sm-9">{{ pool.bbb_url|urlize }}</dd>
|
<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.is_volunteer %}
|
||||||
{% if user.registration.is_admin or user.registration in pool.tournament.organizers.all or user.registration == pool.jury_president %}
|
{% 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">
|
<dd class="col-sm-9">
|
||||||
<a class="btn 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>
|
|
||||||
</dd>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<div class="card bg-body shadow">
|
|
||||||
<div class="card-header text-center">
|
|
||||||
<h5>{% trans "Ranking" %}</h5>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<ul>
|
|
||||||
{% for participation, note in notes %}
|
|
||||||
<li><strong>{{ participation.team }} :</strong> {{ note|floatformat }}</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{% if user.registration.is_volunteer %}
|
|
||||||
<div class="card-footer text-center">
|
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<a class="btn btn-sm btn-info" href="{% url 'participation:pool_scale_note_sheet' pk=pool.pk %}">
|
<a class="btn btn-sm btn-info" href="{% url 'participation:pool_scale_note_sheet' pk=pool.pk %}">
|
||||||
<i class="fas fa-download"></i>
|
<i class="fas fa-download"></i>
|
||||||
@ -115,19 +103,48 @@
|
|||||||
{% trans "Download all notation sheets" %}
|
{% trans "Download all notation sheets" %}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</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>
|
||||||
|
</dd>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<div class="card bg-body shadow">
|
||||||
|
<div class="card-header text-center">
|
||||||
|
<h5>{% trans "Ranking" %}</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<ul>
|
||||||
|
{% for participation, note in notes %}
|
||||||
|
<li><strong>{{ participation.team }} :</strong> {{ note|floatformat }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% 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">
|
<button class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#uploadNotesModal">
|
||||||
<i class="fas fa-upload"></i>
|
<i class="fas fa-upload"></i>
|
||||||
{% trans "Upload notes from a CSV file" %}
|
{% trans "Upload notes from a CSV file" %}
|
||||||
</button>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</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>
|
</div>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
@ -61,7 +61,10 @@
|
|||||||
|
|
||||||
{% if user.registration.is_admin or user.registration in tournament.organizers.all %}
|
{% if user.registration.is_admin or user.registration in tournament.organizers.all %}
|
||||||
<div class="card-footer text-center">
|
<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>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
@ -106,22 +109,6 @@
|
|||||||
</div>
|
</div>
|
||||||
{% if user.registration.is_admin or user.registration in tournament.organizers.all %}
|
{% if user.registration.is_admin or user.registration in tournament.organizers.all %}
|
||||||
<div class="card-footer text-center">
|
<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">
|
<div class="btn-group">
|
||||||
<a href="{% url 'participation:tournament_harmonize' pk=tournament.pk round=1 %}" class="btn btn-secondary">
|
<a href="{% url 'participation:tournament_harmonize' pk=tournament.pk round=1 %}" class="btn btn-secondary">
|
||||||
<i class="fas fa-ranking-star"></i>
|
<i class="fas fa-ranking-star"></i>
|
||||||
@ -133,6 +120,32 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</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 %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -6,6 +6,14 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<form method="post" enctype="multipart/form-data">
|
<form method="post" enctype="multipart/form-data">
|
||||||
<div id="form-content">
|
<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">
|
<div class="alert alert-info">
|
||||||
<a class="alert-link" href="{% url "participation:pool_notes_template" pk=pool.pk %}">
|
<a class="alert-link" href="{% url "participation:pool_notes_template" pk=pool.pk %}">
|
||||||
{% trans "Download empty notation sheet" %}
|
{% trans "Download empty notation sheet" %}
|
||||||
|
@ -703,8 +703,11 @@ class TournamentPublishNotesView(VolunteerMixin, SingleObjectMixin, RedirectView
|
|||||||
raise Http404
|
raise Http404
|
||||||
|
|
||||||
tournament = Tournament.objects.get(pk=kwargs["pk"])
|
tournament = Tournament.objects.get(pk=kwargs["pk"])
|
||||||
tournament.pools.filter(round=kwargs["round"]).update(results_available=True)
|
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!"))
|
messages.success(request, _("Notes published!"))
|
||||||
|
else:
|
||||||
|
messages.success(request, _("Notes hidden!"))
|
||||||
return super().get(request, *args, **kwargs)
|
return super().get(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_redirect_url(self, *args, **kwargs):
|
def get_redirect_url(self, *args, **kwargs):
|
||||||
@ -739,7 +742,7 @@ class TournamentHarmonizeView(VolunteerMixin, DetailView):
|
|||||||
.format(tournament=tournament, round=context["round"])
|
.format(tournament=tournament, round=context["round"])
|
||||||
|
|
||||||
notes = dict()
|
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'])
|
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())
|
tweak = sum(tweak.diff for tweak in participation.tweaks.filter(pool__in=context['pools']).all())
|
||||||
notes[participation] = {'note': note, 'tweak': tweak}
|
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()):
|
if not reg.is_admin and (not reg.is_volunteer or tournament not in reg.organized_tournaments.all()):
|
||||||
return self.handle_no_permission()
|
return self.handle_no_permission()
|
||||||
if self.kwargs['round'] not in (1, 2) or self.kwargs['action'] not in ('add', 'remove') \
|
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
|
raise Http404
|
||||||
return super().dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
tournament = self.get_object()
|
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)
|
pool = tournament.pools.get(round=kwargs['round'], participations=participation)
|
||||||
tweak_qs = Tweak.objects.filter(participation=participation, pool=pool)
|
tweak_qs = Tweak.objects.filter(participation=participation, pool=pool)
|
||||||
old_diff = tweak_qs.first().diff if tweak_qs.exists() else 0
|
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.set_all(*list(map(int, passage_notes)))
|
||||||
note.save()
|
note.save()
|
||||||
|
|
||||||
|
if os.getenv('GOOGLE_PRIVATE_KEY_ID', None):
|
||||||
|
pool.update_notes_spreadsheet()
|
||||||
|
|
||||||
messages.success(self.request, _("Notes were successfully uploaded."))
|
messages.success(self.request, _("Notes were successfully uploaded."))
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
@ -1428,7 +1435,7 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
|
|
||||||
reporter_tc = TableCell(valuetype="string",
|
reporter_tc = TableCell(valuetype="string",
|
||||||
stylename=title_style_right if pool_size != 4 else title_style)
|
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")
|
reporter_tc.setAttribute('numbercolumnsspanned', "2")
|
||||||
header_role.addElement(reporter_tc)
|
header_role.addElement(reporter_tc)
|
||||||
header_role.addElement(CoveredTableCell())
|
header_role.addElement(CoveredTableCell())
|
||||||
@ -1892,9 +1899,9 @@ class PassageDetailView(LoginRequiredMixin, DetailView):
|
|||||||
if reg.is_volunteer:
|
if reg.is_volunteer:
|
||||||
notes = self.object.notes.all()
|
notes = self.object.notes.all()
|
||||||
if not reg.is_admin \
|
if not reg.is_admin \
|
||||||
or (reg != self.object.pool.jury_president
|
and (reg != self.object.pool.jury_president
|
||||||
and reg not in self.object.pool.tournament.organizers.all()):
|
or reg not in self.object.pool.tournament.organizers.all()):
|
||||||
notes = [note for note in notes if note.has_any_note()]
|
notes = [note for note in notes if note.has_any_note() or note.jury == reg]
|
||||||
context["notes"] = NoteTable(notes)
|
context["notes"] = NoteTable(notes)
|
||||||
|
|
||||||
# Only display the observer column for 4-teams pools
|
# Only display the observer column for 4-teams pools
|
||||||
|
Binary file not shown.
@ -53,7 +53,7 @@ Problème \underline{~~~~} défendu par l'équipe \underline{~~~~~~~~~~~~~~~~~~~
|
|||||||
|
|
||||||
\medskip
|
\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}
|
\section*{\'Evaluation question par question de la solution}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user