Skip to content
Snippets Groups Projects

Generování protokolů a zpracování scanů

Merged Martin Mareš requested to merge mj/protokoly into devel
1 file
+ 50
28
Compare changes
  • Side-by-side
  • Inline
+ 50
28
@@ -6,7 +6,7 @@ import shutil
from sqlalchemy.orm import joinedload
import subprocess
import tempfile
from typing import Optional
from typing import List, Optional
import mo
import mo.db as db
@@ -15,7 +15,7 @@ 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):
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
the_job = TheJob()
@@ -24,16 +24,19 @@ def schedule_create_protocols(contest: db.Contest, site: Optional[db.Place], for
job.in_json = {
'contest_id': contest.contest_id,
'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()
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ů,
# 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)
return s
return '{' + s + '}'
@job_handler(db.JobType.create_protocols)
@@ -43,6 +46,9 @@ def handle_create_protocols(the_job: TheJob):
Vstupní JSON:
{ 'contest_id': ID contestu,
'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:
@@ -52,11 +58,15 @@ def handle_create_protocols(the_job: TheJob):
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
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()
contest = sess.query(db.Contest).options(joinedload(db.Contest.round)).get(contest_id)
assert contest is not None
round = contest.round
user_subq = sess.query(db.Participation.user_id).filter_by(contest=contest)
if site_id is not None:
@@ -71,35 +81,47 @@ def handle_create_protocols(the_job: TheJob):
.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()
tasks = sess.query(db.Task).filter_by(round=round).filter(db.Task.task_id.in_(task_ids)).order_by(db.Task.code).all()
pages = []
for p in pants:
for t in tasks:
args = [
':'.join(['MO', round.round_code_short(), t.code, str(p.user_id)]),
p.user.full_name(),
p.grade,
p.school_place.name,
t.code,
]
pages.append('\\proto' + "".join([tex_arg(x) for x in args]))
for _ in range(num_universal):
pages.append('\\universal')
for _ in range(num_blank):
pages.append('\\blank')
if not pages:
job.result = 'Prázdný výstup'
return
temp_dir = tempfile.mkdtemp(prefix='proto-', dir=data_dir('tmp'))
logger.debug('Job: Vytvářím protokoly v %s', temp_dir)
logger.debug('Job: Vytvářím protokoly v %s (%s listů)', temp_dir, len(pages))
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
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')
f.write('\n\\bye\n')
for p in pages:
f.write(p + '\n')
if npages == 0:
job.result = 'Prázdný výstup'
return
f.write('\n\\bye\n')
env = dict(os.environ)
env['TEXINPUTS'] = part_path('tex') + '//:'
@@ -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.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)
Loading