Skip to content
Snippets Groups Projects
Commit eb4ddfdd authored by Martin Mareš's avatar Martin Mareš
Browse files

Protokoly: Výběr úloh, extra stránky a spousta drobností

parent b2ade683
No related branches found
No related tags found
No related merge requests found
This commit is part of merge request !81. Comments created here will be created in the context of that merge request.
...@@ -6,7 +6,7 @@ import shutil ...@@ -6,7 +6,7 @@ import shutil
from sqlalchemy.orm import joinedload from sqlalchemy.orm import joinedload
import subprocess import subprocess
import tempfile import tempfile
from typing import Optional from typing import List, Optional
import mo import mo
import mo.db as db import mo.db as db
...@@ -15,7 +15,7 @@ from mo.util import logger, data_dir, part_path ...@@ -15,7 +15,7 @@ from mo.util import logger, data_dir, part_path
import mo.util_format import mo.util_format
def schedule_create_protocols(contest: db.Contest, site: Optional[db.Place], for_user: db.User): def schedule_create_protocols(contest: db.Contest, site: Optional[db.Place], for_user: db.User, tasks: List[db.Task], num_universal: int, num_blank: int):
place = site or contest.place place = site or contest.place
the_job = TheJob() the_job = TheJob()
...@@ -24,16 +24,19 @@ def schedule_create_protocols(contest: db.Contest, site: Optional[db.Place], for ...@@ -24,16 +24,19 @@ def schedule_create_protocols(contest: db.Contest, site: Optional[db.Place], for
job.in_json = { job.in_json = {
'contest_id': contest.contest_id, 'contest_id': contest.contest_id,
'site_id': site.place_id if site else None, 'site_id': site.place_id if site else None,
'task_ids': [t.task_id for t in tasks],
'num_universal': num_universal,
'num_blank': num_blank,
} }
the_job.submit() the_job.submit()
def tex_escape(s: str) -> str: def tex_arg(s: str) -> str:
# Primitivní escapování do TeXu. Nesnaží se ani tak o věrnou intepretaci všech znaků, # Primitivní escapování do TeXu. Nesnaží se ani tak o věrnou intepretaci všech znaků,
# jako o zabránění pádu TeXu kvůli divným znakům. # jako o zabránění pádu TeXu kvůli divným znakům.
s = re.sub(r'[\\{}#$%^]', '?', s) s = re.sub(r'[\\{}#$%^~]', '?', s)
s = re.sub(r'([&_])', r'\\\1', s) s = re.sub(r'([&_])', r'\\\1', s)
return s return '{' + s + '}'
@job_handler(db.JobType.create_protocols) @job_handler(db.JobType.create_protocols)
...@@ -43,6 +46,9 @@ def handle_create_protocols(the_job: TheJob): ...@@ -43,6 +46,9 @@ def handle_create_protocols(the_job: TheJob):
Vstupní JSON: Vstupní JSON:
{ 'contest_id': ID contestu, { 'contest_id': ID contestu,
'site_id': ID soutěžního místa nebo none, 'site_id': ID soutěžního místa nebo none,
'task_ids': [task_id, ...],
'num_universal': počet papírů s univerzalní hlavičkou,
'num_blank': pocet pokračovacích papírů,
} }
Výstupní JSON: Výstupní JSON:
...@@ -53,10 +59,14 @@ def handle_create_protocols(the_job: TheJob): ...@@ -53,10 +59,14 @@ def handle_create_protocols(the_job: TheJob):
assert job.in_json is not None assert job.in_json is not None
contest_id = job.in_json['contest_id'] # type: ignore contest_id = job.in_json['contest_id'] # type: ignore
site_id = job.in_json['site_id'] # type: ignore site_id = job.in_json['site_id'] # type: ignore
task_ids = job.in_json['task_ids'] # type: ignore
num_universal = job.in_json['num_universal'] # type: ignore
num_blank = job.in_json['num_blank'] # type: ignore
sess = db.get_session() sess = db.get_session()
contest = sess.query(db.Contest).options(joinedload(db.Contest.round)).get(contest_id) contest = sess.query(db.Contest).options(joinedload(db.Contest.round)).get(contest_id)
assert contest is not None assert contest is not None
round = contest.round
user_subq = sess.query(db.Participation.user_id).filter_by(contest=contest) user_subq = sess.query(db.Participation.user_id).filter_by(contest=contest)
if site_id is not None: if site_id is not None:
...@@ -71,36 +81,48 @@ def handle_create_protocols(the_job: TheJob): ...@@ -71,36 +81,48 @@ def handle_create_protocols(the_job: TheJob):
.all()) .all())
pants.sort(key=lambda p: p.user.sort_key()) pants.sort(key=lambda p: p.user.sort_key())
tasks = sess.query(db.Task).filter_by(round=contest.round).order_by(db.Task.code).all() tasks = sess.query(db.Task).filter_by(round=round).filter(db.Task.task_id.in_(task_ids)).order_by(db.Task.code).all()
temp_dir = tempfile.mkdtemp(prefix='proto-', dir=data_dir('tmp'))
logger.debug('Job: Vytvářím protokoly v %s', temp_dir)
tex_src = os.path.join(temp_dir, 'proto.tex')
npages = 0
with open(tex_src, 'w') as f:
f.write('\\input protokol.tex\n\n')
kolo = f'{contest.round.name} {contest.round.year}. ročníku MO kategorie {contest.round.category}'
f.write('\\def\\kolo{' + kolo + '}\n\n')
pages = []
for p in pants: for p in pants:
for t in tasks: for t in tasks:
args = [ args = [
':'.join(['MO', contest.round.round_code_short(), t.code, str(p.user_id)]), ':'.join(['MO', round.round_code_short(), t.code, str(p.user_id)]),
p.user.full_name(), p.user.full_name(),
p.grade, p.grade,
p.school_place.name, p.school_place.name,
t.code, t.code,
] ]
f.write('\\proto' + "".join(['{' + tex_escape(x) + '}' for x in args]) + '\n') pages.append('\\proto' + "".join([tex_arg(x) for x in args]))
npages += 1
f.write('\n\\bye\n') for _ in range(num_universal):
pages.append('\\universal')
if npages == 0: for _ in range(num_blank):
pages.append('\\blank')
if not pages:
job.result = 'Prázdný výstup' job.result = 'Prázdný výstup'
return return
temp_dir = tempfile.mkdtemp(prefix='proto-', dir=data_dir('tmp'))
logger.debug('Job: Vytvářím protokoly v %s (%s listů)', temp_dir, len(pages))
tex_src = os.path.join(temp_dir, 'proto.tex')
with open(tex_src, 'w') as f:
f.write('\\input protokol.tex\n\n')
kolo = f'{round.name} {round.year}. ročníku Matematické olympiády'
kat = f'Kategorie {round.category}'
if round.level > 0:
kat += ', ' + contest.place.name
f.write('\\def\\kolo' + tex_arg(kolo) + '\n\n')
f.write('\\def\\kat' + tex_arg(kat) + '\n\n')
for p in pages:
f.write(p + '\n')
f.write('\n\\bye\n')
env = dict(os.environ) env = dict(os.environ)
env['TEXINPUTS'] = part_path('tex') + '//:' env['TEXINPUTS'] = part_path('tex') + '//:'
...@@ -115,6 +137,6 @@ def handle_create_protocols(the_job: TheJob): ...@@ -115,6 +137,6 @@ def handle_create_protocols(the_job: TheJob):
) )
job.out_file = the_job.attach_file(os.path.join(temp_dir, 'proto.pdf'), '.pdf') job.out_file = the_job.attach_file(os.path.join(temp_dir, 'proto.pdf'), '.pdf')
job.result = 'Celkem ' + mo.util_format.inflect_number(npages, 'strana', 'strany', 'stran') job.result = 'Celkem ' + mo.util_format.inflect_number(len(pages), 'list', 'listy', 'listů')
shutil.rmtree(temp_dir) shutil.rmtree(temp_dir)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment