#!/usr/bin/env python3 # Generátor výsledkové listiny pro MO-P import argparse import locale from sqlalchemy.orm import joinedload import mo.db as db from mo.score import Score from mo.util import die, init_standalone from mo.util_format import format_decimal parser = argparse.ArgumentParser(description='Vygeneruje výsledkovou listinu MO-P') parser.add_argument('year', type=int) parser.add_argument('seq', type=int) args = parser.parse_args() init_standalone() sess = db.get_session() def get_results(round, contests): results = {} for contest in contests: place_code = contest.place.get_code() print(f"Počítám oblast {place_code}") score = Score(round, contest) results[place_code] = score.get_sorted_results() for msg in score.get_messages(): if msg[0] != 'info': print(f'\t{msg[0].upper()}: {msg[1]}') return results def write_tex(round, tasks, contests, results): with open('final.tex', 'w') as out: out.write(r'\def\HranicePostupu{%s}' % (format_decimal(round.score_winner_limit,)) + "\n") out.write(r'\def\HraniceUspesnychResitelu{%s}' % (format_decimal(round.score_successful_limit),) + "\n") out.write('\n') for c in contests: res = results[c.place.get_code()] if round.seq <= 2: out.write(r'\kraj{%s}' % c.place.name + '\n') if not res: out.write(r'\nobody' + '\n') out.write(r'\endkraj' + '\n\n') continue out.write(r'\begintable' + '\n') prev_typ = "" for r in res: if r.winner: typ = 'v' elif r.successful: typ = 'u' else: typ = 'n' if typ != prev_typ: if prev_typ: out.write(r'\sep%s' % typ) prev_typ = typ out.write(r'\%s' % typ) cols = [] o = r.order if not r.successful or o.continuation: cols.append("") elif o.span > 1: cols.append(f'{o.place}.--{o.place + o.span - 1}.') else: cols.append(f'{o.place}.') cols.append(r.user.full_name()) cols.append(r.pant.school_place.name) cols.append(r.pant.grade) sol_map = r.get_sols_map() for t in tasks: s = sol_map.get(t.task_id) if s is not None: cols.append(format_decimal(s.points)) else: cols.append('--') cols.append(format_decimal(r.get_total_points())) out.write("".join(['{' + str(col) + '}' for col in cols]) + '\n') out.write(r'\endtable' + '\n') if round.seq <= 2: out.write(r'\endkraj' + '\n\n') def write_html(round, tasks, contests, results): num_cols = 4 + len(tasks) + 1 with open('final.html', 'w') as out: for c in contests: out.write(f'<tr><th colspan={num_cols}>{c.place.name}\n') res = results[c.place.get_code()] if not res: out.write(f'<tr class=nobody><td colspan={num_cols}>Nikdo se nezúčastnil.\n') out.write(f'<tr><td colspan={num_cols}>\n\n') continue for r in res: if r.winner: out.write('<tr class=marked>') elif r.successful: out.write('<tr class=success>') else: out.write('<tr>') cols = [] o = r.order if not r.successful or o.continuation: cols.append("") elif o.span > 1: cols.append(f'{o.place}.–{o.place + o.span - 1}.') else: cols.append(f'{o.place}.') cols.append(r.user.full_name()) cols.append(r.pant.school_place.name) cols.append(r.pant.grade) sol_map = r.get_sols_map() for t in tasks: s = sol_map.get(t.task_id) if s is not None: cols.append(format_decimal(s.points)) else: cols.append('–') cols.append(format_decimal(r.get_total_points())) out.write("".join(['<td>' + str(col) for col in cols]) + '\n') out.write(f'<tr><td colspan={num_cols}>\n\n') round = sess.query(db.Round).filter_by(year=args.year, category='P', seq=args.seq).filter(db.Round.master_round_id == db.Round.round_id).one() print(f"Kolo {round.round_code()}") round_group_subq = sess.query(db.Round.round_id).filter_by(master_round_id=round.round_id) tasks = sess.query(db.Task).filter(db.Task.round_id.in_(round_group_subq)).order_by(db.Task.code).all() contests = (sess.query(db.Contest) .filter_by(round=round) .options(joinedload(db.Contest.place)) .all()) assert contests contests.sort(key=lambda c: locale.strxfrm(c.place.name)) results = get_results(round, contests) write_tex(round, tasks, contests, results) write_html(round, tasks, contests, results)