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

Lze nahrávat hromadně i odevzdaná řešení

parent 75334aad
No related branches found
No related tags found
No related merge requests found
......@@ -116,9 +116,10 @@ class UploadFeedback:
task: Optional[db.Task] = None
user: Optional[db.User] = None
tmp_name: Optional[str] = None
is_solution: bool = False
def parse_feedback_name(name: str) -> Optional[UploadFeedback]:
def parse_feedback_name(name: str, round_id: int) -> (Optional[UploadFeedback], Optional[str]):
name = os.path.basename(name)
# Formát jmen generovaný dávkovým stahováním
......@@ -128,7 +129,7 @@ def parse_feedback_name(name: str) -> Optional[UploadFeedback]:
file_name=name,
task_code=m['task'],
user_id=int(m['user_id']),
)
), None
# Formát jmen, pod kterými se ukládají jednotlivě stahovaná řešení
m = re.match(r'(?P<task>[^_]+)_(reseni|opravene)_(?P<user_id>\d+)_', name)
......@@ -137,7 +138,7 @@ def parse_feedback_name(name: str) -> Optional[UploadFeedback]:
file_name=name,
task_code=m['task'],
user_id=int(m['user_id']),
)
), None
# Formát jmen, pod kterými se dříve ukládala jednotlivě stahovaná řešení
m = re.match(r'(?P<task>.+)-(reseni|opravene)-(?P<paper_id>\d+)\.', name)
......@@ -148,9 +149,32 @@ def parse_feedback_name(name: str) -> Optional[UploadFeedback]:
file_name=name,
task_code=m['task'],
user_id=paper.for_user,
)
), None
return None
# Hromadný upload skenů
m = re.match(r'(?P<task>[^_]+)_(?P<what>reseni|opravene)_(?P<lastname>[^_]+)_(?P<firstname>[^_]+)\.', name)
if m:
users = (db.get_session().query(db.User.user_id)
.select_from(db.Participation)
.join(db.User, db.User.user_id == db.Participation.user_id)
.join(db.Contest, db.Contest.master_contest_id == db.Participation.contest_id)
.filter(db.Contest.round_id == round_id)
.filter(and_(
db.f_unaccent(db.User.first_name).ilike(db.f_unaccent(m['firstname'])),
db.f_unaccent(db.User.last_name ).ilike(db.f_unaccent(m['lastname']))))
.all())
if len(users) > 1:
return None, f'Nalezeno více soutěžící se jménem "{m["firstname"]} {m["lastname"]}"'
elif len(users) == 0:
return None, f'Nenalezen žádný soutěžících se jménem "{m["firstname"]} {m["lastname"]}".'
return UploadFeedback(
file_name=name,
task_code=m['task'],
user_id=users[0].user_id,
is_solution=(m['what']=='reseni'),
), None
return None, f'Nerozpoznáno jméno souboru {name}.'
@job_handler(db.JobType.upload_feedback)
......@@ -196,7 +220,7 @@ def handle_upload_feedback(the_job: TheJob):
contents = zip.infolist()
for item in contents:
if not item.is_dir():
fb = parse_feedback_name(item.filename)
fb, err = parse_feedback_name(item.filename, round_id)
if fb:
tmp_file = NamedTemporaryFile(mode='w+b', delete=False)
logger.debug(f'Job: Extrahuji {item.filename} do {tmp_file.name}')
......@@ -206,7 +230,7 @@ def handle_upload_feedback(the_job: TheJob):
fb.tmp_name = tmp_file.name
files.append(fb)
else:
the_job.error(f'Nerozpoznáno jméno souboru {item.filename}')
the_job.error(err)
except zipfile.BadZipFile as e:
logger.debug(f'Job: Nahraný soubor není validní ZIP: {str(e)}')
the_job.error('Chybný formát souboru. Je to opravdu ZIP?')
......@@ -266,7 +290,7 @@ def handle_upload_feedback(the_job: TheJob):
paper = db.Paper(
for_user_obj=fb.user,
task=fb.task,
type=db.PaperType.feedback,
type=db.PaperType.solution if fb.is_solution else db.PaperType.feedback,
uploaded_by_obj=job.user,
)
try:
......@@ -279,6 +303,9 @@ def handle_upload_feedback(the_job: TheJob):
.filter_by(task=fb.task, user=fb.user)
.with_for_update()
.one())
if fb.is_solution:
sol.final_submit_obj = paper
else:
sol.final_feedback_obj = paper
sess.commit()
......
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}Nahrání opravených řešení{% if task %} úlohy {{ task.code }}: {{ task.name }}{% endif %}{% endblock %}
{% block title %}Nahrání odevzdaných či opravených řešení{% if task %} úlohy {{ task.code }}: {{ task.name }}{% endif %}{% endblock %}
{% block breadcrumbs %}
{{ ctx.breadcrumbs(action="Nahrát ZIP řešení") }}
{% endblock %}
......@@ -9,12 +9,11 @@
{% block body %}
<p>Zde můžete nahrát najednou více PDF souborů zabalených do jednoho souboru typu ZIP.
<p>Soubory opravených řešení se musí jmenovat stejně jako původní soubory účastnických řešení.
Na zařazení souborů do adresářů nezáleží.
<p>Pokud ZIP obsahuje jen podmnožinu účastníků, řešení ostatních účastníků se nezmění.
Pokud nahrajete řešení téhož účastníka znovu, uloží se nová verze.
<p>Na zařazení souborů do adresářů <i>nezáleží</i>.
<form action="https://{{ bucket_name }}.storage.googleapis.com" method="post" class="form" enctype="multipart/form-data" role="form">
{% for key, value in policy.items() %}
<input type="hidden" name="{{ key }}" value="{{ value }}">
......@@ -25,4 +24,21 @@ Pokud nahrajete řešení téhož účastníka znovu, uloží se nová verze.
<input class="btn btn-primary" type="submit" value="Odeslat">
</form>
<h4>Opravená řešení</h4>
<p>Soubory opravených řešení se musí jmenovat stejně jako původně z Osmo stažené soubory odevzdaných řešení.
<p>Alternativně použijte formát:
<pre>
&lt;<i>kód úlohy</i>&gt;_opravene_&lt;<i>příjmení</i>&gt;_&lt;<i>jméno</i>&gt;.pdf
</pre>
<p>tj. například <kbd>B2-1_opravene_pilny_josef.pdf</kbd>. U jména a příjmení nezáleží na diakritice, ani velikosti písmen. Pokud existuje v rámci kola více soutěžících se stejným jménem, skončí nahrání chybou, jejich řešení je třeba nahrát jednotlivě.
<h4>Odevzdaná řešení</h4>
<p>Soubory odevzdaných řešení musí být pojmenované podle této šablony:
<pre>
&lt;<i>kód úlohy</i>&gt;_reseni_&lt;<i>příjmení</i>&gt;_&lt;<i>jméno</i>&gt;.pdf
</pre>
<p>tj. například <kbd>B2-1_reseni_pilny_josef.pdf</kbd>.
{% endblock %}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment