Skip to content
Snippets Groups Projects
Commit 96fefcf8 authored by Jiří Setnička's avatar Jiří Setnička
Browse files

Nastavení ručního zjednoznačnění pořadí u výsledkovek

Požaduje právo manage_round/manage_contest.

Issue #210
parent c37af8e8
No related branches found
No related tags found
No related merge requests found
This commit is part of merge request !105. Comments created here will be created in the context of that merge request.
from flask import render_template, request, g
from flask.helpers import url_for
from flask import render_template, request
from flask.helpers import flash, url_for
from typing import List, Optional, Union
from sqlalchemy.orm import joinedload
from flask_wtf.form import FlaskForm
import werkzeug.exceptions
from werkzeug.utils import redirect
import wtforms
import mo
import mo.db as db
......@@ -10,8 +12,8 @@ from mo.rights import Right
from mo.score import Score
from mo.web import app
from mo.web.org_contest import get_context
from mo.web.table import Cell, CellLink, Column, Row, Table, cell_pion_link
from mo.util_format import format_decimal
from mo.web.table import Cell, CellInput, CellLink, Column, Row, Table, cell_pion_link
from mo.util_format import format_decimal, inflect_number
class OrderCell(Cell):
......@@ -78,8 +80,14 @@ class SolPointsCell(Cell):
return f'<td>{points}' # no paper no link
class ScoreEditForm(FlaskForm):
submit = wtforms.SubmitField("Uložit zjednoznačnění")
@app.route('/org/contest/r/<int:round_id>/score')
@app.route('/org/contest/r/<int:round_id>/score/edit', methods=('GET', 'POST'), endpoint="org_score_edit")
@app.route('/org/contest/c/<int:ct_id>/score')
@app.route('/org/contest/c/<int:ct_id>/score/edit', methods=('GET', 'POST'), endpoint="org_score_edit")
def org_score(round_id: Optional[int] = None, ct_id: Optional[int] = None):
ctx = get_context(round_id=round_id, ct_id=ct_id)
contest = ctx.contest
......@@ -92,11 +100,52 @@ def org_score(round_id: Optional[int] = None, ct_id: Optional[int] = None):
raise werkzeug.exceptions.Forbidden()
can_view_submits = ctx.rights.have_right(Right.view_submits)
is_edit = request.endpoint == 'org_score_edit'
can_manage = (round_id is not None and ctx.rights.have_right(Right.manage_round)) or (ct_id is not None and ctx.rights.have_right(Right.manage_contest))
if is_edit and not can_manage:
raise werkzeug.exceptions.Forbidden()
score = Score(round.master, contest)
tasks = score.get_tasks()
results = score.get_sorted_results()
messages = score.get_messages()
edit_form: Optional[ScoreEditForm] = None
if is_edit:
edit_form = ScoreEditForm()
if edit_form.validate_on_submit():
count = 0
for result in results:
try:
score_suborder = int(request.form.get(f"suborder_{result.user.user_id}"))
except ValueError:
score_suborder = None
if score_suborder != result.pion.score_suborder:
app.logger.info(f"Změněno zjednoznačnění u soutěžícího #{result.user.user_id} v soutěži #{result.pion.contest_id}: {result.pion.score_suborder}->{score_suborder}")
mo.util.log(
type=db.LogType.participant,
what=result.user.user_id,
details={
'action': 'pion-changed-suborder',
'contest_id': result.pion.contest_id,
'old_score_suborder': result.pion.score_suborder,
'new_score_suborder': score_suborder
},
)
result.pion.score_suborder = score_suborder
count += 1
if count > 0:
sess.commit()
flash('Změněno zjednoznačnění u ' + inflect_number(count, 'soutěžícího', 'soutěžících', 'soutěžících'), 'success')
else:
flash('Žádné změny k uložení', 'info')
return redirect(ctx.url_for('org_score'))
# Pro tvorbu odkazů na správné contesty ve výsledkovkách dělených kol
all_subcontests: List[db.Contest] = sess.query(db.Contest).filter(
db.Contest.round_id.in_(
......@@ -138,6 +187,8 @@ def org_score(round_id: Optional[int] = None, ct_id: Optional[int] = None):
)
columns.append(Column(key=f'task_{task.task_id}', name=task.code, title=title))
columns.append(Column(key='total_points', name='celkove_body', title='Celkové body'))
if is_edit:
columns.append(Column(key='suborder', name='zjednoznacneni_poradi', title='Zjednoznačnění'))
# columns.append(Column(key='order_key', name='order_key', title='Třídící klíč'))
# Construct rows
......@@ -173,6 +224,7 @@ def org_score(round_id: Optional[int] = None, ct_id: Optional[int] = None):
'total_points': format_decimal(result.get_total_points()),
'birth_year': pant.birth_year,
'order_key': result._order_key,
'suborder': CellInput(f"suborder_{user.user_id}", pion.score_suborder, "number", attrs={"size": 6}),
})
sols = result.get_sols_map()
......@@ -196,6 +248,7 @@ def org_score(round_id: Optional[int] = None, ct_id: Optional[int] = None):
columns=columns,
rows=table_rows,
filename=filename,
show_downlink=not is_edit,
)
group_rounds = round.get_group_rounds(True)
......@@ -208,6 +261,8 @@ def org_score(round_id: Optional[int] = None, ct_id: Optional[int] = None):
contest=contest, round=round, tasks=tasks,
table=table, messages=messages,
group_rounds=group_rounds,
round_id=round_id, ct_id=ct_id, can_manage=can_manage,
edit_form=edit_form,
)
else:
return table.send_as(format)
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}
{{ round.round_code() }}: Výsledky pro {{ round.name|lower }} kategorie {{ round.category }}{% if contest %} {{ contest.place.name_locative() }}{% endif %}
......@@ -42,7 +43,7 @@
{% if group_rounds|length > 1 %}
<p>Toto je <b>sdílená výsledková listina</b> pro několik kol:
{% for r in group_rounds %}{% if loop.index > 1 %}, {% endif %}<a href="{{ url_for('org_round', round_id=r.round_id) }}">{{ r.round_code() }} {{ r.name }}</a>{% endfor %}.
{% for r in group_rounds %}{% if loop.index > 1 %}, {% endif %}<a href="{{ ctx.url_for('org_round') }}">{{ r.round_code() }} {{ r.name }}</a>{% endfor %}.
Jsou v ní započítány body ze všech úloh těchto kol.</p>
{% endif %}
......@@ -62,6 +63,22 @@ Rozkliknutím bodů se lze dostat na detail daného řešení.</p>
{% endif %}
{% endif %}
{% if edit_form %}
<p><strong>Zjednoznačnění pořadí:</strong> U soutěžících na sdílených pozicích vyplňte číslo do políčka na konci řádku. Třídí se vzestupně od nejmenšího, prázdné políčko se považuje za nulu.</p>
<form method="POST" class="form form-horizontal" action="">
{{ edit_form.csrf_token }}
{{ wtf.form_field(edit_form.submit, class="btn btn-primary pull-right") }}<br>
{% elif can_manage %}
<a class="btn btn-default pull-right" href="{{ ctx.url_for('org_score_edit') }}">Zjednoznačnit pořadí</a><br>
{% endif %}
{{ table.to_html() }}
{% if edit_form %}
{{ wtf.form_field(edit_form.submit, class="btn btn-primary pull-right") }}
</form>
{% elif can_manage %}
<a class="btn btn-default pull-right" href="{{ ctx.url_for('org_score_edit') }}">Zjednoznačnit pořadí</a><br>
{% endif %}
{% endblock %}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment