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

Tabulka Moje soutěže

parent ebf2817b
No related branches found
No related tags found
1 merge request!65Tabulka Moje soutěže
......@@ -200,28 +200,31 @@ 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
# 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"
# Pokud už soutěž skončila, přístup k zadání má každý org.
# XXX: Rozhodujeme podle stavu kola, nikoliv soutěže!
return True, ""
class RoundRights(Rights):
......@@ -279,25 +282,11 @@ class ContestRights(Rights):
or self.have_right(Right.manage_contest))
def can_view_statement(self) -> bool:
return self._check_view_statement(self.contest.round)
can, _ = self._check_view_statement(self.contest.round)
return can
def cannot_view_statement_reason(self) -> str:
round = self.contest.round
if round.tasks_file is None:
return "zatím chybí"
if self.have_right(Right.manage_round):
# Správce kola může vždy všechno
return ""
if self.have_right(Right.view_statement):
if round.state == db.RoundState.preparing:
return "až začne soutěž"
if round.state == db.RoundState.running and round.pr_tasks_start is None:
return "až začnou opravy"
if mo.now < round.pr_tasks_start:
return mo.util_format.timedelta(round.pr_tasks_start)
if round.state not in [db.RoundState.grading, db.RoundState.closed]:
return "až začnou opravy"
return ""
def can_view_statement_with_reason(self) -> (bool, str):
return self._check_view_statement(self.contest.round)
class Gatekeeper:
......
......@@ -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