Skip to content
Snippets Groups Projects
Commit dd95eeb9 authored by Jan Prachař's avatar Jan Prachař
Browse files

Tabulka Moje soutěže

parent ebf2817b
No related branches found
No related tags found
No related merge requests found
......@@ -200,28 +200,34 @@ class Rights:
# Interní rozhodovaní o dostupnosti zadání
def _check_view_statement(self, round: db.Round):
def _check_view_statement(self, round: db.Round) -> tuple[bool, str]:
if round.tasks_file is None:
return False
return False, "zatím chybí"
if self.have_right(Right.manage_round):
# Správce kola může vždy všechno
return True
return True, ""
# Pokud už soutěž skončila, přístup k zadání má každý org.
# XXX: Rozhodujeme podle stavu kola, nikoliv soutěže!
if round.state in [db.RoundState.grading, db.RoundState.closed]:
return True
return True, ""
# Od stanoveného času vidí zadání orgové s právem view_statement.
if (self.have_right(Right.view_statement)
and round.state != db.RoundState.preparing
and round.pr_tasks_start is not None
and mo.now >= round.pr_tasks_start):
return True
if (self.have_right(Right.view_statement)):
# Ve zbylých případech jsme konzervativní a zadání neukazujeme
return False
if (round.state == db.RoundState.preparing
or round.pr_tasks_start is None):
return False, "až začne soutěž"
if mo.now < round.pr_tasks_start:
return False, mo.util_format.timedelta(round.pr_tasks_start)
return True, ""
if round.state not in [db.RoundState.grading, db.RoundState.closed]:
return False, "až začnou opravy"
return True, ""
class RoundRights(Rights):
......@@ -279,6 +285,10 @@ class ContestRights(Rights):
or self.have_right(Right.manage_contest))
def can_view_statement(self) -> bool:
can, _ = self._check_view_statement(self.contest.round)
return can
def can_view_statement_with_reason(self) -> (bool, str):
return self._check_view_statement(self.contest.round)
def cannot_view_statement_reason(self) -> str:
......
......@@ -30,30 +30,38 @@ def org_index():
flash('ID uživatele musí být číslo', 'danger')
sess = db.get_session()
contests_with_role = sess.execute("""
SELECT contest_id, MIN(role) as role
FROM contests
JOIN user_roles ur USING(place_id)
JOIN rounds r USING(round_id)
JOIN users USING(user_id)
WHERE
user_id = :user_id
AND r.year = :current_year
AND (ur.year IS NULL OR ur.year = r.year)
AND (ur.category IS NULL OR ur.category = r.category)
AND (ur.seq IS NULL OR ur.seq = r.seq)
GROUP BY contest_id, r.level, r.category, place_id, r.seq, r.part
ORDER BY r.level, r.category, place_id, r.seq, r.part
""", {'user_id': g.user.user_id, 'current_year': mo.current_year})
roles = (sess.query(db.UserRole)
.filter_by(user_id=g.user.user_id)
.options(joinedload(db.UserRole.place))
.all())
contest_ids = []
roles = []
for row in contests_with_role:
contest_ids.append(row['contest_id'])
roles.append(row['role'])
contests = []
for role in roles:
q = (sess.query(db.Contest, db.UserRole.role, db.Round)
contests = (sess.query(db.Contest)
.select_from(db.Contest)
.filter_by(place_id=role.place_id)
.join(db.UserRole, db.UserRole.user_role_id == role.user_role_id)
.join(db.Round))
if role.year:
q = q.filter(db.Round.year == role.year)
if role.category:
q = q.filter(db.Round.category == role.category)
if role.seq:
q = q.filter(db.Round.seq == role.seq)
contests += q.options(joinedload(db.Contest.place)).all()
contests.sort(key=lambda r: (r[2].year, r[2].category, r[2].seq, r[2].part))
.join(db.Round)
.filter(db.Contest.contest_id.in_(contest_ids))
.options(joinedload(db.Contest.place))
.order_by(db.Round.level, db.Round.category, db.Contest.place_id,
db.Round.seq, db.Round.part)
.all())
return render_template('org_index.html', contests=contests, Right=Right,
return render_template('org_index.html', contests=zip(contests, roles), Right=Right,
role_names=db.role_type_names, gatekeeper=g.gatekeeper)
......
......@@ -6,46 +6,44 @@
<h3>Moje soutěže</h3>
<table class="table table-bordered">
{% set curr = namespace(level = -1) %}
{% for c, role in contests %}
{% set cr = gatekeeper.rights_for_contest(c) %}
{% if curr.level != c.round.level %}
<thead><tr>
<th>Kategorie
<th>Kolo
<th>{{ c.round.get_level().name|capitalize }}
<th>Stav
<th>Zadání
<th>Moje role
<th>Odkazy
</thead>
{% for c,role,r in contests %}
{% set rr = gatekeeper.rights_for_contest(c) %}
{% if c.state == RoundState.preparing %}
<tr class="warning">
{% elif c.state == RoundState.running %}
<tr class="success">
{% elif c.state == RoundState.grading %}
<tr class="info">
{% else %}
<tr>
{% set curr.level = c.round.level %}
{% endif %}
<td class="text-center" style="font-size: 1.2em"><b>{{ r.category }}</b>
<td>{{ r.name }} {{ c.place.name_locativ() if c.place.level > 0 else '' }}
<tr class="rstate-{{c.state.name}}">
<td class="text-center"><b>{{ c.round.category }}</b>
<td>{{ c.round.name }}
<td>{{ c.place.name }}
<td>{{ c.state.friendly_name() }}
<td>
{% if rr.can_view_statement() %}
<a href='{{ url_for('org_task_statement', id=r.round_id) }}'>stáhnout</a>
{% set can, reason = cr.can_view_statement_with_reason() %}
{% if can %}
<a href='{{ url_for('org_task_statement', id=c.round_id) }}'>stáhnout</a>
{% else %}
{{ rr.cannot_view_statement_reason() }}
{{ reason }}
{% endif %}
<td>{{ role_names[role] }}
<td>
<a class="btn btn-xs btn-primary" href='{{ url_for('org_contest', id=c.contest_id) }}'>Detail</a>
<a class="btn btn-xs btn-default" href='{{ url_for('org_contest_list', id=c.contest_id) }}'>Účastníci</a>
{% if rr.can_view_submits() and c.state != RoundState.preparing %}
{% if cr.have_right(Right.view_submits) and c.state != RoundState.preparing %}
<a class="btn btn-xs btn-success" href='{{ url_for('org_contest_solutions', id=c.contest_id) }}'>Odevzdaná řešení</a>
{% endif %}
{% if (c.state == RoundState.grading and rr.can_view_submits()) or c.state == RoundState.closed %}
{% if (c.state == RoundState.grading and cr.have_right(Right.view_submits)) or c.state == RoundState.closed %}
<a class="btn btn-xs btn-warning" href='{{ url_for('org_score', contest_id=c.contest_id) }}'>Výsledky</a>
{% endif %}
{% if rr.have_right(Right.manage_contest) and c.state != RoundState.closed %}
<a class="btn btn-xs btn-primary" href='{{ url_for('org_contest_add_user', id=c.contest_id) }}'>+ Přidat účastníka</a>
{% if cr.have_right(Right.manage_contest) and c.state == RoundState.preparing %}
<a class="btn btn-xs btn-default" href='{{ url_for('org_contest_import', id=c.contest_id) }}'>Import</a>
{% endif %}
</td>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment