Skip to content
Snippets Groups Projects
Commit 7f9fe3db 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 dd1263f7
No related branches found
No related tags found
No related merge requests found
from flask import render_template, request, g from flask import render_template, request
from flask.helpers import url_for from flask.helpers import flash, url_for
from typing import List, Optional, Union from typing import List, Optional, Union
from sqlalchemy.orm import joinedload from flask_wtf.form import FlaskForm
import werkzeug.exceptions import werkzeug.exceptions
from werkzeug.utils import redirect
import wtforms
import mo import mo
import mo.db as db import mo.db as db
...@@ -10,8 +12,8 @@ from mo.rights import Right ...@@ -10,8 +12,8 @@ from mo.rights import Right
from mo.score import Score from mo.score import Score
from mo.web import app from mo.web import app
from mo.web.org_contest import get_context from mo.web.org_contest import get_context
from mo.web.table import Cell, CellLink, Column, Row, Table, cell_pion_link from mo.web.table import Cell, CellInput, CellLink, Column, Row, Table, cell_pion_link
from mo.util_format import format_decimal from mo.util_format import format_decimal, inflect_number
class OrderCell(Cell): class OrderCell(Cell):
...@@ -78,8 +80,14 @@ class SolPointsCell(Cell): ...@@ -78,8 +80,14 @@ class SolPointsCell(Cell):
return f'<td>{points}' # no paper no link 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')
@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')
@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): def org_score(round_id: Optional[int] = None, ct_id: Optional[int] = None):
ctx = get_context(round_id=round_id, ct_id=ct_id) ctx = get_context(round_id=round_id, ct_id=ct_id)
contest = ctx.contest contest = ctx.contest
...@@ -92,11 +100,52 @@ def org_score(round_id: Optional[int] = None, ct_id: Optional[int] = None): ...@@ -92,11 +100,52 @@ def org_score(round_id: Optional[int] = None, ct_id: Optional[int] = None):
raise werkzeug.exceptions.Forbidden() raise werkzeug.exceptions.Forbidden()
can_view_submits = ctx.rights.have_right(Right.view_submits) 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) score = Score(round.master, contest)
tasks = score.get_tasks() tasks = score.get_tasks()
results = score.get_sorted_results() results = score.get_sorted_results()
messages = score.get_messages() 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 # 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( all_subcontests: List[db.Contest] = sess.query(db.Contest).filter(
db.Contest.round_id.in_( db.Contest.round_id.in_(
...@@ -138,6 +187,8 @@ def org_score(round_id: Optional[int] = None, ct_id: Optional[int] = None): ...@@ -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=f'task_{task.task_id}', name=task.code, title=title))
columns.append(Column(key='total_points', name='celkove_body', title='Celkové body')) 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íč')) # columns.append(Column(key='order_key', name='order_key', title='Třídící klíč'))
# Construct rows # Construct rows
...@@ -173,6 +224,7 @@ def org_score(round_id: Optional[int] = None, ct_id: Optional[int] = None): ...@@ -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()), 'total_points': format_decimal(result.get_total_points()),
'birth_year': pant.birth_year, 'birth_year': pant.birth_year,
'order_key': result._order_key, 'order_key': result._order_key,
'suborder': CellInput(f"suborder_{user.user_id}", pion.score_suborder, "number", attrs={"size": 6}),
}) })
sols = result.get_sols_map() sols = result.get_sols_map()
...@@ -196,6 +248,7 @@ def org_score(round_id: Optional[int] = None, ct_id: Optional[int] = None): ...@@ -196,6 +248,7 @@ def org_score(round_id: Optional[int] = None, ct_id: Optional[int] = None):
columns=columns, columns=columns,
rows=table_rows, rows=table_rows,
filename=filename, filename=filename,
show_downlink=not is_edit,
) )
group_rounds = round.get_group_rounds(True) group_rounds = round.get_group_rounds(True)
...@@ -208,6 +261,8 @@ def org_score(round_id: Optional[int] = None, ct_id: Optional[int] = None): ...@@ -208,6 +261,8 @@ def org_score(round_id: Optional[int] = None, ct_id: Optional[int] = None):
contest=contest, round=round, tasks=tasks, contest=contest, round=round, tasks=tasks,
table=table, messages=messages, table=table, messages=messages,
group_rounds=group_rounds, group_rounds=group_rounds,
round_id=round_id, ct_id=ct_id, can_manage=can_manage,
edit_form=edit_form,
) )
else: else:
return table.send_as(format) return table.send_as(format)
{% extends "base.html" %} {% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %} {% block title %}
{{ round.round_code() }}: Výsledky pro {{ round.name|lower }} kategorie {{ round.category }}{% if contest %} {{ contest.place.name_locative() }}{% endif %} {{ round.round_code() }}: Výsledky pro {{ round.name|lower }} kategorie {{ round.category }}{% if contest %} {{ contest.place.name_locative() }}{% endif %}
...@@ -62,6 +63,22 @@ Rozkliknutím bodů se lze dostat na detail daného řešení.</p> ...@@ -62,6 +63,22 @@ Rozkliknutím bodů se lze dostat na detail daného řešení.</p>
{% endif %} {% endif %}
{% 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="{{ url_for('org_score_edit', round_id=round_id, ct_id=ct_id) }}">Editovat pořadí</a><br>
{% endif %}
{{ table.to_html() }} {{ 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="{{ url_for('org_score_edit', round_id=round_id, ct_id=ct_id) }}">Editovat pořadí</a><br>
{% endif %}
{% endblock %} {% endblock %}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment