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

Protokoly: Job na sazbu

parent 5033e131
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.
......@@ -189,4 +189,5 @@ def job_handler(type: db.JobType):
# Moduly implementující jednotlivé typy jobů
import mo.jobs.protocols
import mo.jobs.submit
# Implementace jobů na sazbu protokolů
import os
import re
import shutil
from sqlalchemy.orm import joinedload
import subprocess
import tempfile
from typing import Optional
import mo
import mo.db as db
from mo.jobs import TheJob, job_handler
from mo.util import logger, data_dir, part_path
import mo.util_format
def schedule_create_protocols(contest: db.Contest, site: Optional[db.Place], for_user: db.User):
place = site or contest.place
the_job = TheJob()
job = the_job.create(db.JobType.create_protocols, for_user)
job.description = f'Formuláře protokolů {contest.round.round_code_short()} {place.name}'
job.in_json = {
'contest_id': contest.contest_id,
'site_id': site.place_id if site else None,
}
the_job.submit()
def tex_escape(s: str) -> str:
# 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.
s = re.sub(r'[\\{}#$%^]', '?', s)
s = re.sub(r'([&_])', r'\\\1', s)
return s
@job_handler(db.JobType.create_protocols)
def handle_create_protocols(the_job: TheJob):
"""Vygeneruje formuláře protokolů.
Vstupní JSON:
{ 'contest_id': ID contestu,
'site_id': ID soutěžního místa nebo none,
}
Výstupní JSON:
null
"""
job = the_job.job
assert job.in_json is not None
contest_id = job.in_json['contest_id'] # type: ignore
site_id = job.in_json['site_id'] # type: ignore
sess = db.get_session()
contest = sess.query(db.Contest).options(joinedload(db.Contest.round)).get(contest_id)
assert contest is not None
user_subq = sess.query(db.Participation.user_id).filter_by(contest=contest)
if site_id is not None:
user_subq = user_subq.filter_by(place_id=site_id)
user_subq = (user_subq
.filter(db.Participation.state.in_((db.PartState.invited, db.PartState.registered, db.PartState.present)))
.subquery())
pants = (sess.query(db.Participant)
.options(joinedload(db.Participant.user), joinedload(db.Participant.school_place))
.filter(db.Participant.user_id.in_(user_subq))
.all())
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()
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')
for p in pants:
for t in tasks:
args = [
':'.join(['MO', contest.round.round_code_short(), t.code, str(p.user_id)]),
p.user.full_name(),
p.grade,
p.school_place.name,
t.code,
]
f.write('\\proto' + "".join(['{' + tex_escape(x) + '}' for x in args]) + '\n')
npages += 1
f.write('\n\\bye\n')
if npages == 0:
job.result = 'Prázdný výstup'
return
env = dict(os.environ)
env['TEXINPUTS'] = part_path('tex') + '//:'
subprocess.run(
['luatex', '--interaction=errorstopmode', 'proto.tex'],
check=True,
cwd=temp_dir,
env=env,
stdin=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
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')
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