diff --git a/mo/web/templates/user_contest.html b/mo/web/templates/user_contest.html index b46abb3f60fc70cb99746e235d38f4010fdeb5e7..b1412201ac75014769adfdeaab87b45b2d5b5309 100644 --- a/mo/web/templates/user_contest.html +++ b/mo/web/templates/user_contest.html @@ -6,28 +6,52 @@ <h2>{{ round.name }} {{ round.year }}. ročníku kategorie {{ round.category }}: {{ contest.place.name }}</h2> +{% if state == db.RoundState.preparing %} +<p> + Soutěžní kolo se <b>připravuje</b>{% if round.ct_tasks_start and round.ct_tasks_start > g.now %}, + začne <b>{{ round.ct_tasks_start|timeformat }} ({{ human_timedelta(round.ct_tasks_start, g.now) }})</b>{% endif %}. + Až začne, budete mít na této stránce {% if round.has_tasks() %}k dispozici text zadání,{% endif %} + přehled úloh a budete zde moci odevzdat svá řešení k jednotlivým úlohám. + Do té doby zde nenajdete nic jiného. +</p> +{% elif state == db.RoundState.running and not round.can_submit() %} +<p> + Soutěžní kolo <b>je připraveno</b>, ale zatím nelze odevzdávat. Odevzdávání začne + <b>{{ round.ct_tasks_start|timeformat }} ({{ human_timedelta(round.ct_tasks_start, g.now) }})</b>. + Až začne, budete mít na této stránce {% if round.has_tasks() %}k dispozici text zadání,{% endif %} + přehled úloh a budete zde moci odevzdat svá řešení k jednotlivým úlohám. + Do té doby zde nenajdete nic jiného. +</p> +{% else %} {% if state == db.RoundState.running %} -<p>Soutěž běží. - {% if round.ct_submit_end == None %} - Můžete odevzdávat svá řešení. - {% else %} - Svá řešení odevzdávejte do {{ round.ct_submit_end|timeformat }}. - V případě technických problémů můžete odevzdat i později, - ale není zaručeno, že řešení budou hodnocena. - {% endif %} - +<p> +{% if round.ct_submit_end == None %} + Soutěžní kolo běží, <b>můžete odevzdávat svá řešení.</b> +{% elif round.ct_submit_end > g.now %} + Soutěžní kolo běží, <b>svá řešení odevzdávejte do {{ round.ct_submit_end|timeformat }} ({{ human_timedelta(round.ct_submit_end, g.now) }})</b>. + V případě technických problémů můžete odevzdat i později, ale není zaručeno, že řešení budou hodnocena. +{% else %} + Řádný termín soutěžního kola <b>již skončil</b> (v {{ round.ct_submit_end|timeformat }}, {{ human_timedelta(round.ct_submit_end, g.now) }}), + ale stále můžete odevzdat svá řešení, která se vám nepovedla odevzdat kvůli + technickým problémům. Není však zaručeno, že řešení budou hodnocena. +{% endif %} +</p> +{% if round.can_submit() %} <p>Řešení odevzdávejte ve formátu PDF jako soubor o velikosti maximálně {{ max_submit_size // 1048576 }} MB. +{% endif %} {% elif state == db.RoundState.grading %} <p>Odevzdávání bylo ukončeno. Vyčkejte prosím, až úlohy opravíme. {% elif state == db.RoundState.closed %} -<p>FIXME +<p>Soutěžní kolo bylo ukončeno, níže si můžete prohlédnout svá ohodnocená a okomentovaná řešení. + +<p>FIXME výsledkovka {% else %} <p>Soutěž se nachází v neznámém stavu. To by se nemělo stát :) {% endif %} -{% if statement_visible %} +{% if round.task_statement_available() %} <p>Můžete si stáhnout <a href='{{ url_for('user_task_statement', id=contest.contest_id) }}'>zadání úloh</a>. {% endif %} @@ -41,9 +65,8 @@ {% if round.state == db.RoundState.closed %} <th>Opraveno <th>Body - {% else %} - <th>Akce {% endif %} + <th>Akce <tbody> {% for task, sol in task_sols %} <tr> @@ -60,13 +83,13 @@ <td> {% endif %} <td>{{ sol.points if sol.points != None else '–' }} - {% else %} - <td> - {% if round.state == db.RoundState.running %} - <a class='btn btn-xs btn-primary' href='{{ url_for('user_contest_task', contest_id=contest.contest_id, task_id=task.task_id) }}'>Odevzdat</a> - {% endif %} {% endif %} + <td> + <a class='btn btn-xs btn-primary' href='{{ url_for('user_contest_task', contest_id=contest.contest_id, task_id=task.task_id) }}'> + {% if round.can_submit() %}Odevzdat{% else %}Detail úlohy{% endif %} + </a> {% endfor %} </table> +{% endif %} {% endblock %} diff --git a/mo/web/templates/user_contest_task.html b/mo/web/templates/user_contest_task.html index 819f7a11854239e13a8036c561bd57a77a236e0d..400ee0e335f2d06d154b2c6db1348001093c9308 100644 --- a/mo/web/templates/user_contest_task.html +++ b/mo/web/templates/user_contest_task.html @@ -7,14 +7,18 @@ <p><a href='{{ url_for('user_contest', id=contest.contest_id) }}'>Zpět na seznam úloh</a> +{% if round.can_submit() %} <h3>Odevzdat řešení</h3> -{% if round.ct_submit_end != None and g.now > round.ct_submit_end %} -<p class="alert alert-danger">Pozor, odevzdáváte po termínu. Vaše řešení nemusí být hodnoceno. -Doporučujeme využít políčko pro komentář a vysvětlit situaci. +{% if round.ct_submit_end and g.now > round.ct_submit_end %} +<p class="alert alert-danger">Pozor, odevzdáváte po termínu (uplynul {{ round.ct_submit_end|timeformat }}, +{{ human_timedelta(round.ct_submit_end) }}). Vaše řešení nemusí být hodnoceno. Doporučujeme využít políčko pro komentář a vysvětlit situaci. {% endif %} {{ wtf.quick_form(form, form_type='basic', button_map={'submit': 'primary'}) }} +{% else %} +<p><i>Soutěžní kolo neběží, již není možné odevzdat nové řešení.</i></p> +{% endif %} <h3>Historie vašich řešení</h3> diff --git a/mo/web/templates/user_index.html b/mo/web/templates/user_index.html index c55c8fa42446bb53944a903cd66055a3a4cfcaf4..be8b2d4be21f4884e5d88dab3e78505d30babfd7 100644 --- a/mo/web/templates/user_index.html +++ b/mo/web/templates/user_index.html @@ -5,7 +5,7 @@ {% if pions %} <p>Účastníte se následujících kol MO: - <table class=data> + <table class="table"> <thead> <tr> <th title='ročník MO'>Roč. @@ -21,11 +21,9 @@ <td>{{ round.category }} <td>{{ round.name }} <td>{{ contest.place.name }} - <td>{{ round.state.friendly_name() }} + <td>{{ round.long_state() }} <td><div class="btn-group"> - {% if round.state == db.RoundState.running %} - <a class='btn btn-xs btn-primary' href='{{ url_for('user_contest', id=contest.contest_id) }}'>Odevzdávat</a> - {% endif %} + <a class='btn btn-xs btn-primary' href='{{ url_for('user_contest', id=contest.contest_id) }}'>Detail kola</a> </div> {% endfor %} </table> diff --git a/mo/web/user.py b/mo/web/user.py index e1cc7cdae85cc409416231d0599e067d0725b101..761d1114d68c4179bacc9ab233541b2db7518cdf 100644 --- a/mo/web/user.py +++ b/mo/web/user.py @@ -29,7 +29,6 @@ def user_index(): .join(db.Contest) .join(db.Round) .filter(db.Participation.user == g.user) - .filter(db.Round.state != db.RoundState.preparing) .options(joinedload(db.Contest.place)) .order_by(db.Round.year.desc(), db.Round.category, db.Round.seq) .all()) @@ -50,12 +49,6 @@ def get_contest(id: int) -> db.Contest: if not contest: raise werkzeug.exceptions.NotFound() - # FIXME: Časem chceme účastníky pustit i v jiných stavech - # FIXME: A také místo generického Forbidden říci něco konkrétnějšího - # (je možné, že se sem účastník dostal reloadem stránky po konci contestu) - if contest.round.state != db.RoundState.running: - raise werkzeug.exceptions.Forbidden() - # FIXME: Kontrolovat nějak pion.state? pion = (db.get_session().query(db.Participation) .filter_by(user=g.user, contest=contest) @@ -94,7 +87,6 @@ def user_contest(id: int): 'user_contest.html', contest=contest, task_sols=task_sols, - statement_visible=contest.round.task_statement_available(), max_submit_size=config.MAX_CONTENT_LENGTH, db=db, # kvůli hodnotám enumů ) @@ -104,7 +96,7 @@ def user_contest(id: int): def user_task_statement(id: int): contest = get_contest(id) - if not contest.round.task_statement_available(): + if not contest.round.task_statement_available(mo.now): logger.warn(f'Účastník #{g.user.user_id} chce zadání, na které nemá právo') raise werkzeug.exceptions.Forbidden() @@ -123,8 +115,14 @@ def user_contest_task(contest_id: int, task_id: int): task = get_task(contest, task_id) sess = db.get_session() + round = contest.round + if round.state == db.RoundState.preparing or (round.state == db.RoundState.running and not round.can_submit(mo.now)): + # Dokud se kolo připravuje nebo čeká na zveřejnění zadání, tak ani nezobrazujeme + # stránku, abychom něco neprozradili jménem úlohy + raise werkzeug.exceptions.Forbidden() + form = SubmitForm() - if form.validate_on_submit(): + if round.can_submit(now) and form.validate_on_submit(): # FIXME: Tohle je pomalé, dělá se tu zbytečná další kopie dat. # Nicméně werkzeugu by měla jít podstrčit stream factory, # která bude vyrábět streamy rovnou uložené v našem tmp.