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
Branches
No related tags found
No related merge requests found
...@@ -116,9 +116,10 @@ class UploadFeedback: ...@@ -116,9 +116,10 @@ class UploadFeedback:
task: Optional[db.Task] = None task: Optional[db.Task] = None
user: Optional[db.User] = None user: Optional[db.User] = None
tmp_name: Optional[str] = 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) name = os.path.basename(name)
# Formát jmen generovaný dávkovým stahováním # Formát jmen generovaný dávkovým stahováním
...@@ -128,7 +129,7 @@ def parse_feedback_name(name: str) -> Optional[UploadFeedback]: ...@@ -128,7 +129,7 @@ def parse_feedback_name(name: str) -> Optional[UploadFeedback]:
file_name=name, file_name=name,
task_code=m['task'], task_code=m['task'],
user_id=int(m['user_id']), user_id=int(m['user_id']),
) ), None
# Formát jmen, pod kterými se ukládají jednotlivě stahovaná řešení # 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) 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]: ...@@ -137,7 +138,7 @@ def parse_feedback_name(name: str) -> Optional[UploadFeedback]:
file_name=name, file_name=name,
task_code=m['task'], task_code=m['task'],
user_id=int(m['user_id']), user_id=int(m['user_id']),
) ), None
# Formát jmen, pod kterými se dříve ukládala jednotlivě stahovaná řešení # 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) 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]: ...@@ -148,9 +149,32 @@ def parse_feedback_name(name: str) -> Optional[UploadFeedback]:
file_name=name, file_name=name,
task_code=m['task'], task_code=m['task'],
user_id=paper.for_user, 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) @job_handler(db.JobType.upload_feedback)
...@@ -196,7 +220,7 @@ def handle_upload_feedback(the_job: TheJob): ...@@ -196,7 +220,7 @@ def handle_upload_feedback(the_job: TheJob):
contents = zip.infolist() contents = zip.infolist()
for item in contents: for item in contents:
if not item.is_dir(): if not item.is_dir():
fb = parse_feedback_name(item.filename) fb, err = parse_feedback_name(item.filename, round_id)
if fb: if fb:
tmp_file = NamedTemporaryFile(mode='w+b', delete=False) tmp_file = NamedTemporaryFile(mode='w+b', delete=False)
logger.debug(f'Job: Extrahuji {item.filename} do {tmp_file.name}') logger.debug(f'Job: Extrahuji {item.filename} do {tmp_file.name}')
...@@ -206,7 +230,7 @@ def handle_upload_feedback(the_job: TheJob): ...@@ -206,7 +230,7 @@ def handle_upload_feedback(the_job: TheJob):
fb.tmp_name = tmp_file.name fb.tmp_name = tmp_file.name
files.append(fb) files.append(fb)
else: else:
the_job.error(f'Nerozpoznáno jméno souboru {item.filename}') the_job.error(err)
except zipfile.BadZipFile as e: except zipfile.BadZipFile as e:
logger.debug(f'Job: Nahraný soubor není validní ZIP: {str(e)}') logger.debug(f'Job: Nahraný soubor není validní ZIP: {str(e)}')
the_job.error('Chybný formát souboru. Je to opravdu ZIP?') the_job.error('Chybný formát souboru. Je to opravdu ZIP?')
...@@ -266,7 +290,7 @@ def handle_upload_feedback(the_job: TheJob): ...@@ -266,7 +290,7 @@ def handle_upload_feedback(the_job: TheJob):
paper = db.Paper( paper = db.Paper(
for_user_obj=fb.user, for_user_obj=fb.user,
task=fb.task, task=fb.task,
type=db.PaperType.feedback, type=db.PaperType.solution if fb.is_solution else db.PaperType.feedback,
uploaded_by_obj=job.user, uploaded_by_obj=job.user,
) )
try: try:
...@@ -279,6 +303,9 @@ def handle_upload_feedback(the_job: TheJob): ...@@ -279,6 +303,9 @@ def handle_upload_feedback(the_job: TheJob):
.filter_by(task=fb.task, user=fb.user) .filter_by(task=fb.task, user=fb.user)
.with_for_update() .with_for_update()
.one()) .one())
if fb.is_solution:
sol.final_submit_obj = paper
else:
sol.final_feedback_obj = paper sol.final_feedback_obj = paper
sess.commit() sess.commit()
......
{% extends "base.html" %} {% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %} {% 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 %} {% block breadcrumbs %}
{{ ctx.breadcrumbs(action="Nahrát ZIP řešení") }} {{ ctx.breadcrumbs(action="Nahrát ZIP řešení") }}
{% endblock %} {% endblock %}
...@@ -9,12 +9,11 @@ ...@@ -9,12 +9,11 @@
{% block body %} {% block body %}
<p>Zde můžete nahrát najednou více PDF souborů zabalených do jednoho souboru typu ZIP. <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í. <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. 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"> <form action="https://{{ bucket_name }}.storage.googleapis.com" method="post" class="form" enctype="multipart/form-data" role="form">
{% for key, value in policy.items() %} {% for key, value in policy.items() %}
<input type="hidden" name="{{ key }}" value="{{ value }}"> <input type="hidden" name="{{ key }}" value="{{ value }}">
...@@ -25,4 +24,21 @@ Pokud nahrajete řešení téhož účastníka znovu, uloží se nová verze. ...@@ -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"> <input class="btn btn-primary" type="submit" value="Odeslat">
</form> </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 %} {% endblock %}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment