Jonas Havelka
2 years ago
14 changed files with 490 additions and 546 deletions
@ -1,9 +1,9 @@ |
|||
\setlength{\tabcolsep}{3pt} |
|||
\begin{longtable}{|r|l|c|r|{% for p in problemy %}c@{\hskip.5em}{% endfor %}|r|r|}\hline |
|||
& & & & \multicolumn{ {{ problemy|length}} }{c|}{\textbf{Témata}} & & \\\textbf{Poř.}& \textbf{Jméno}& \textbf{R.}& \raisebox{0.7mm}{$\sum_{-1}$}& {% for p in problemy %}\textbf{ {{ p.kod_v_rocniku }} }&{% endfor %}\raisebox{0.7mm}{$\sum_0$}&\raisebox{0.7mm}{$\sum_1$}\\\hline |
|||
\begin{longtable}{|r|l|c|r|{% for p in vysledkovka.temata_a_spol %}c@{\hskip.5em}{% endfor %}|r|r|}\hline |
|||
& & & & \multicolumn{ {{ vysledkovka.temata_a_spol|length}} }{c|}{\textbf{Témata}} & & \\\textbf{Poř.}& \textbf{Jméno}& \textbf{R.}& \raisebox{0.7mm}{$\sum_{-1}$}& {% for p in vysledkovka.temata_a_spol %}\textbf{ {{ p.kod_v_rocniku }} }&{% endfor %}\raisebox{0.7mm}{$\sum_0$}&\raisebox{0.7mm}{$\sum_1$}\\\hline |
|||
\endhead |
|||
\hline |
|||
\endfoot |
|||
{% for rv in radky_vysledkovky %}{{rv.poradi}}&{% if rv.titul %}\titul{ {{ rv.titul}}}{% endif %}{{rv.resitel.osoba.jmeno|slice:":1"}}. {{rv.resitel.osoba.prijmeni}}&{{rv.rocnik_resitele|default:""}}&{{rv.body_celkem_odjakziva}}&{% for b in rv.body_problemy_sezn %}{{b}}&{% endfor %}{{rv.body_cislo}}&{{rv.body_rocnik|default:0}}\\ |
|||
{% for rv in vysledkovka.radky_vysledkovky %}{{rv.poradi}}&{% if rv.titul %}\titul{ {{ rv.titul}}}{% endif %}{{rv.resitel.osoba.jmeno|slice:":1"}}. {{rv.resitel.osoba.prijmeni}}&{{rv.rocnik_resitele|default:""}}&{{rv.body_celkem_odjakziva}}&{% for b in rv.body_problemy_sezn %}{{b}}&{% endfor %}{{rv.body_cislo}}&{{rv.body_rocnik|default:0}}\\ |
|||
{% endfor %} |
|||
\end{longtable} |
|||
|
@ -1 +0,0 @@ |
|||
{% include "vysledkovky/vysledkovka_rocnik.html" with radky_vysledkovky=radky_vysledkovky_s_neverejnymi cisla=cisla_s_neverejnymi %} |
@ -1,462 +1,451 @@ |
|||
import abc |
|||
from functools import cached_property |
|||
|
|||
import seminar.models as m |
|||
from django.db.models import Q, Sum, Count |
|||
from seminar.utils import aktivniResitele, resi_v_rocniku, cisla_rocniku, hlavni_problem, hlavni_problemy_f, problemy_cisla, podproblemy_v_cislu |
|||
import time |
|||
from django.db.models import Q, Sum |
|||
from seminar.utils import resi_v_rocniku, cisla_rocniku, hlavni_problem,\ |
|||
hlavni_problemy_f, problemy_cisla, podproblemy_v_cislu |
|||
|
|||
ROCNIK_ZRUSENI_TEMAT = 25 |
|||
|
|||
def sloupec_s_poradim(setrizene_body): |
|||
""" |
|||
Ze seznamu obsahujícího sestupně setřízené body řešitelů za daný ročník |
|||
vytvoří seznam s pořadími (včetně 3.-5. a pak 2 volná místa atp.), |
|||
podle toho, jak jdou za sebou ve výsledkovce. |
|||
Parametr: |
|||
setrizene_body (seznam integerů): sestupně setřízená čísla |
|||
|
|||
Výstup: |
|||
sloupec_s_poradim (seznam stringů) |
|||
""" |
|||
|
|||
# ze seznamu obsahujícího setřízené body spočítáme sloupec s pořadím |
|||
aktualni_poradi = 1 |
|||
sloupec_s_poradim = [] |
|||
|
|||
# seskupíme seznam všech bodů podle hodnot |
|||
for index in range(0, len(setrizene_body)): |
|||
# pokud je pořadí větší než číslo řádku, tak jsme vypsali větší rozsah a chceme |
|||
# vypsat už jen prázdné místo, než dojdeme na správný řádek |
|||
if (index + 1) < aktualni_poradi: |
|||
sloupec_s_poradim.append("") |
|||
continue |
|||
velikost_skupiny = 0 |
|||
# zjistíme počet po sobě jdoucích stejných hodnot |
|||
while setrizene_body[index] == setrizene_body[index + velikost_skupiny]: |
|||
velikost_skupiny = velikost_skupiny + 1 |
|||
# na konci musíme ošetřit přetečení seznamu |
|||
if (index + velikost_skupiny) > len(setrizene_body) - 1: |
|||
break |
|||
# pokud je velikost skupiny 1, vypíšu pořadí |
|||
if velikost_skupiny == 1: |
|||
sloupec_s_poradim.append("{}.".format(aktualni_poradi)) |
|||
# pokud je skupina větší, vypíšu rozsah |
|||
else: |
|||
sloupec_s_poradim.append("{}.–{}.".format(aktualni_poradi, |
|||
aktualni_poradi+velikost_skupiny-1)) |
|||
# zvětšíme aktuální pořadí o tolik, kolik pozic bylo přeskočeno |
|||
aktualni_poradi = aktualni_poradi + velikost_skupiny |
|||
return sloupec_s_poradim |
|||
|
|||
|
|||
|
|||
|
|||
def body_resitelu(resitele, za, odjakziva=True, jen_verejne=False): |
|||
""" Funkce počítající počty bodů pro zadané řešitele, |
|||
buď odjakživa do daného ročníku/čísla anebo za daný ročník/číslo. |
|||
Parametry: |
|||
resitele (seznam obsahující položky typu Resitel): aktivní řešitelé |
|||
za (Rocnik/Cislo): za co se mají počítat body |
|||
(generování starších výsledkovek) |
|||
odjakziva (bool): zda se mají počítat body odjakživa, nebo jen za číslo/ročník |
|||
zadané v "za" |
|||
Výstup: |
|||
slovník (Resitel.id):body |
|||
""" |
|||
resitele_id = [r.id for r in resitele] |
|||
# Zjistíme, typ objektu v parametru "za" |
|||
if isinstance(za, m.Rocnik): |
|||
cislo = None |
|||
rocnik = za |
|||
rok = rocnik.prvni_rok |
|||
elif isinstance(za, m.Cislo): |
|||
cislo = za |
|||
rocnik = None |
|||
rok = cislo.rocnik.prvni_rok |
|||
else: |
|||
assert True, "body_resitelu: za není ani číslo ani ročník." |
|||
|
|||
|
|||
# Kvůli rychlosti používáme sčítáme body už v databázi, viz |
|||
# https://docs.djangoproject.com/en/3.0/topics/db/aggregation/, |
|||
# sekce Filtering on annotations (protože potřebujeme filtrovat výsledky |
|||
# jen do nějakého data, abychom uměli správně nagenerovat výsledkovky i |
|||
# za historická čísla. |
|||
|
|||
# Níže se vytváří dotaz na součet bodů za správně vyfiltrovaná hodnocení, |
|||
# který se použije ve výsledném dotazu. |
|||
if cislo and odjakziva: # Body se sčítají odjakživa do zadaného čísla. |
|||
# Vyfiltrujeme všechna hodnocení, která jsou buď ze starších ročníků, |
|||
# anebo ze stejného ročníku, jak je zadané číslo, tam ale sčítáme jen |
|||
# pro čísla s pořadím nejvýše stejným, jako má zadané číslo. |
|||
body_k_zapocteni = Sum('reseni__hodnoceni__body', |
|||
filter=( Q(reseni__hodnoceni__cislo_body__rocnik__prvni_rok__lt=rok) | |
|||
Q(reseni__hodnoceni__cislo_body__rocnik__prvni_rok=rok, |
|||
reseni__hodnoceni__cislo_body__poradi__lte=cislo.poradi) )) |
|||
elif cislo and not odjakziva: # Body se sčítají za dané číslo. |
|||
body_k_zapocteni = Sum('reseni__hodnoceni__body', |
|||
filter=( Q(reseni__hodnoceni__cislo_body__rocnik__prvni_rok=rok, |
|||
reseni__hodnoceni__cislo_body__poradi__lte=cislo.poradi) )) |
|||
elif rocnik and odjakziva: # Spočítáme body za starší ročníky až do zadaného včetně. |
|||
if jen_verejne: |
|||
body_k_zapocteni = Sum('reseni__hodnoceni__body', |
|||
filter= Q(reseni__hodnoceni__cislo_body__rocnik__prvni_rok__lte=rok, |
|||
reseni__hodnoceni__cislo_body__verejna_vysledkovka=True)) |
|||
else: |
|||
body_k_zapocteni = Sum('reseni__hodnoceni__body', |
|||
filter= Q(reseni__hodnoceni__cislo_body__rocnik__prvni_rok__lte=rok)) |
|||
elif rocnik and not odjakziva: # Spočítáme body za daný ročník. |
|||
if jen_verejne: |
|||
body_k_zapocteni = Sum('reseni__hodnoceni__body', |
|||
filter=Q(reseni__hodnoceni__cislo_body__rocnik=rocnik, |
|||
reseni__hodnoceni__cislo_body__verejna_vysledkovka=True)) |
|||
else: |
|||
body_k_zapocteni = Sum('reseni__hodnoceni__body', |
|||
filter=Q(reseni__hodnoceni__cislo_body__rocnik=rocnik)) |
|||
else: |
|||
assert True, "body_resitelu: Neplatná kombinace za a odjakživa." |
|||
|
|||
# Následující řádek přidá ke každému řešiteli údaj ".body" se součtem jejich bodů |
|||
resitele_s_body = m.Resitel.objects.filter(id__in=resitele_id).annotate( |
|||
body=body_k_zapocteni) |
|||
# Teď jen z QuerySetu řešitelů anotovaných body vygenerujeme slovník |
|||
# indexovaný řešitelským id obsahující body. |
|||
# Pokud jsou body None, nahradíme za 0. |
|||
slovnik = {int(res.id) : (res.body if res.body else 0) for res in resitele_s_body} |
|||
return slovnik |
|||
|
|||
class RadekVysledkovkyRocniku(object): |
|||
""" Obsahuje věci, které se hodí vědět při konstruování výsledkovky. |
|||
Umožňuje snazší práci v templatu (lepší, než seznam).""" |
|||
|
|||
def __init__(self, poradi, resitel, body_cisla_sezn, body_rocnik, body_odjakziva, rok): |
|||
self.poradi = poradi |
|||
self.resitel = resitel |
|||
self.rocnik_resitele = resitel.rocnik(rok) |
|||
self.body_rocnik = body_rocnik |
|||
self.body_celkem_odjakziva = body_odjakziva |
|||
self.body_cisla_sezn = body_cisla_sezn |
|||
self.titul = resitel.get_titul(body_odjakziva) |
|||
|
|||
def setrid_resitele_a_body(slov_resitel_body): |
|||
setrizeni_resitele_id = [dvojice[0] for dvojice in slov_resitel_body] |
|||
setrizene_body = [dvojice[1] for dvojice in slov_resitel_body] |
|||
return setrizeni_resitele_id, setrizene_body |
|||
|
|||
def data_vysledkovky_rocniku(rocnik, jen_verejne=True): |
|||
""" Přebírá ročník (např. context["rocnik"]) a vrací výsledkovou listinu ve |
|||
formě vhodné pro šablonu "seminar/vysledkovka_rocniku.html" |
|||
""" |
|||
|
|||
start = time.time() |
|||
|
|||
## TODO možná chytřeji vybírat aktivní řešitele |
|||
# aktivní řešitelé - chceme letos něco poslal, TODO později vyfiltrujeme ty, kdo mají |
|||
# u alespoň jedné hodnoty něco jiného než NULL |
|||
aktivni_resitele = list(resi_v_rocniku(rocnik)) |
|||
cisla = cisla_rocniku(rocnik, jen_verejne) |
|||
body_cisla_slov = {} |
|||
for cislo in cisla: |
|||
# získáme body za číslo |
|||
_, cislobody = secti_body_za_cislo(cislo, aktivni_resitele) |
|||
body_cisla_slov[cislo.id] = cislobody |
|||
|
|||
# získáme body za ročník, seznam obsahuje dvojice (řešitel_id, body) setřízené sestupně |
|||
resitel_rocnikbody_sezn = secti_body_za_rocnik(rocnik, aktivni_resitele, jen_verejne=jen_verejne) |
|||
|
|||
# setřídíme řešitele podle počtu bodů a získáme seznam s body od nejvyšších po nenižší |
|||
setrizeni_resitele_id, setrizene_body = setrid_resitele_a_body(resitel_rocnikbody_sezn) |
|||
poradi = sloupec_s_poradim(setrizene_body) |
|||
|
|||
# získáme body odjakživa |
|||
resitel_odjakzivabody_slov = body_resitelu(aktivni_resitele, rocnik, jen_verejne=jen_verejne) |
|||
|
|||
# vytvoříme jednotlivé sloupce výsledkovky |
|||
radky_vysledkovky = [] |
|||
i = 0 |
|||
setrizeni_resitele_dict = {} # Tento slovnik se vyrab |
|||
for r in m.Resitel.objects.filter(id__in=setrizeni_resitele_id).select_related('osoba'): |
|||
setrizeni_resitele_dict[r.id] = r |
|||
|
|||
for ar_id in setrizeni_resitele_id: |
|||
# seznam počtu bodů daného řešitele pro jednotlivá čísla |
|||
body_cisla_sezn = [] |
|||
for cislo in cisla: |
|||
body_cisla_sezn.append(body_cisla_slov[cislo.id][ar_id]) |
|||
|
|||
# vytáhneme informace pro daného řešitele |
|||
radek = RadekVysledkovkyRocniku( |
|||
poradi[i], # pořadí |
|||
setrizeni_resitele_dict[ar_id], # řešitel (z id) |
|||
body_cisla_sezn, # seznam bodů za čísla |
|||
setrizene_body[i], # body za ročník (spočítané výše s pořadím) |
|||
resitel_odjakzivabody_slov[ar_id], # body odjakživa |
|||
rocnik) # ročník semináře pro získání ročníku řešitele |
|||
radky_vysledkovky.append(radek) |
|||
i += 1 |
|||
|
|||
end = time.time() |
|||
print("Vysledkovka rocniku",end-start) |
|||
|
|||
radky_vysledkovky = [radek for radek in radky_vysledkovky if radek.body_rocnik > 0] |
|||
return radky_vysledkovky, cisla |
|||
|
|||
class RadekVysledkovkyCisla(object): |
|||
"""Obsahuje věci, které se hodí vědět při konstruování výsledkovky. |
|||
Umožňuje snazší práci v templatu (lepší, než seznam).""" |
|||
|
|||
def __init__(self, poradi, resitel, body_problemy_sezn, |
|||
body_cislo, body_rocnik, body_odjakziva, rok, body_podproblemy, body_podproblemy_iter): |
|||
self.resitel = resitel |
|||
self.rocnik_resitele = resitel.rocnik(rok) |
|||
self.body_cislo = body_cislo |
|||
self.body_rocnik = body_rocnik |
|||
self.body_celkem_odjakziva = body_odjakziva |
|||
self.poradi = poradi |
|||
self.body_problemy_sezn = body_problemy_sezn |
|||
self.titul = resitel.get_titul(body_odjakziva) |
|||
self.body_podproblemy = body_podproblemy |
|||
self.body_podproblemy_iter = body_podproblemy_iter # TODELETE |
|||
|
|||
|
|||
def pricti_body(slovnik, resitel, body): |
|||
""" Přiřazuje danému řešiteli body do slovníku. """ |
|||
# testujeme na None (""), pokud je to první řešení |
|||
# daného řešitele, předěláme na 0 |
|||
# (v dalším kroku přičteme reálný počet bodů), |
|||
# rozlišujeme tím mezi 0 a neodevzdaným řešením |
|||
|
|||
# Speciálně pokud jsou body None (hodnocení není obodované), vraťse |
|||
# TODO nejde to udělat lépe? |
|||
if body is None: |
|||
return |
|||
|
|||
if slovnik[resitel.id] == "": |
|||
slovnik[resitel.id] = 0 |
|||
|
|||
slovnik[resitel.id] += body |
|||
|
|||
def secti_body_za_rocnik(za, aktivni_resitele, jen_verejne): |
|||
""" Spočítá body za ročník (celý nebo do daného čísla), |
|||
setřídí je sestupně a vrátí jako seznam. |
|||
Parametry: |
|||
za (typu Rocnik nebo Cislo) spočítá za ročník, nebo za ročník až do |
|||
daného čísla |
|||
""" |
|||
# spočítáme všem řešitelům jejich body za ročník (False => ne odjakživa) |
|||
resitel_rocnikbody_slov = body_resitelu(aktivni_resitele, za, False, jen_verejne=jen_verejne) |
|||
# zeptáme se na dvojice (řešitel, body) za ročník a setřídíme sestupně |
|||
resitel_rocnikbody_sezn = sorted(resitel_rocnikbody_slov.items(), |
|||
key = lambda x: x[1], reverse = True) |
|||
return resitel_rocnikbody_sezn |
|||
|
|||
def secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy=None): |
|||
""" Spočítá u řešitelů body za číslo a za jednotlivé hlavní problémy (témata).""" |
|||
# TODO setřídit hlavní problémy čísla podle id, ať jsou ve stejném pořadí pokaždé |
|||
# pro každý hlavní problém zavedeme slovník s body za daný hlavní problém |
|||
# pro jednotlivé řešitele (slovník slovníků hlavních problémů) |
|||
|
|||
print("Scitam cislo",cislo) |
|||
|
|||
if hlavni_problemy is None: |
|||
hlavni_problemy = hlavni_problemy_f(problemy_cisla(cislo)) |
|||
|
|||
def ne_clanek_ne_konfera(problem): |
|||
inst = problem.get_real_instance() |
|||
return not(isinstance(inst, m.Clanek) or isinstance(inst, m.Konfera)) |
|||
|
|||
if cislo.rocnik.rocnik < ROCNIK_ZRUSENI_TEMAT: |
|||
temata_a_spol = hlavni_problemy |
|||
else: |
|||
temata_a_spol = list(filter(ne_clanek_ne_konfera, hlavni_problemy)) |
|||
|
|||
hlavni_problemy_slovnik = {} |
|||
for hp in temata_a_spol: |
|||
hlavni_problemy_slovnik[hp.id] = {} |
|||
|
|||
hlavni_problemy_slovnik[-1] = {} |
|||
|
|||
# zakládání prázdných záznamů pro řešitele |
|||
cislobody = {} |
|||
for ar in aktivni_resitele: |
|||
# řešitele převedeme na řetězec pomocí unikátního id |
|||
cislobody[ar.id] = "" |
|||
for hp in temata_a_spol: |
|||
slovnik = hlavni_problemy_slovnik[hp.id] |
|||
slovnik[ar.id] = "" |
|||
|
|||
hlavni_problemy_slovnik[-1][ar.id] = "" |
|||
|
|||
hodnoceni_do_cisla = m.Hodnoceni.objects.prefetch_related('problem', 'reseni', 'reseni__resitele').filter(cislo_body=cislo) |
|||
|
|||
start = time.time() |
|||
|
|||
for hodnoceni in hodnoceni_do_cisla: |
|||
prob = hodnoceni.problem |
|||
nadproblem = hlavni_problem(prob) |
|||
if ne_clanek_ne_konfera(nadproblem): |
|||
nadproblem_slovnik = hlavni_problemy_slovnik[nadproblem.id] |
|||
else: |
|||
nadproblem_slovnik = hlavni_problemy_slovnik[-1] |
|||
|
|||
body = hodnoceni.body |
|||
|
|||
# a mít více řešitelů |
|||
for resitel in hodnoceni.reseni.resitele.all(): |
|||
if resitel not in aktivni_resitele: |
|||
print("Skipping {}".format(resitel.id)) |
|||
continue |
|||
pricti_body(cislobody, resitel, body) |
|||
pricti_body(nadproblem_slovnik, resitel, body) |
|||
end = time.time() |
|||
print("for cykly:", end-start) |
|||
return hlavni_problemy_slovnik, cislobody |
|||
|
|||
|
|||
def secti_body_za_cislo_podle_temat(cislo, aktivni_resitele, podproblemy=None, temata=None): |
|||
""" Spočítá u řešitelů body za číslo za úlohy v jednotlivých hlavních problémech (témata).""" |
|||
if temata is None: |
|||
temata = hlavni_problemy_f(problemy_cisla(cislo)) |
|||
|
|||
if podproblemy is None: |
|||
podproblemy_v_cislu(cislo, hlavni_problemy=temata) |
|||
|
|||
body_slovnik = {} |
|||
for tema in temata: |
|||
body_slovnik[tema.id] = {} |
|||
for problem in podproblemy[tema.id]: |
|||
body_slovnik[tema.id][problem.id] = {} |
|||
body_slovnik[-1] = {} |
|||
for problem in podproblemy[-1]: |
|||
body_slovnik[-1][problem.id] = {} |
|||
|
|||
# zakládání prázdných záznamů pro řešitele |
|||
for ar in aktivni_resitele: |
|||
for tema in temata: |
|||
for problem in podproblemy[tema.id]: |
|||
body_slovnik[tema.id][problem.id][ar.id] = "" |
|||
|
|||
for problem in podproblemy[-1]: |
|||
body_slovnik[-1][problem.id][ar.id] = "" |
|||
|
|||
temata = set(t.id for t in temata) |
|||
|
|||
hodnoceni_do_cisla = m.Hodnoceni.objects.prefetch_related('problem', 'reseni', 'reseni__resitele').filter(cislo_body=cislo) |
|||
|
|||
for hodnoceni in hodnoceni_do_cisla: |
|||
prob = hodnoceni.problem |
|||
nadproblem = hlavni_problem(prob) |
|||
if nadproblem.id in temata: |
|||
nadproblem_slovnik = body_slovnik[nadproblem.id] |
|||
else: |
|||
nadproblem_slovnik = body_slovnik[-1] |
|||
|
|||
problem_slovnik = nadproblem_slovnik[prob.id] |
|||
|
|||
body = hodnoceni.body |
|||
|
|||
# a mít více řešitelů |
|||
for resitel in hodnoceni.reseni.resitele.all(): |
|||
if resitel not in aktivni_resitele: |
|||
print("Skipping {}".format(resitel.id)) |
|||
continue |
|||
pricti_body(problem_slovnik, resitel, body) |
|||
return body_slovnik |
|||
|
|||
|
|||
# TODELETE |
|||
class FixedIterator: |
|||
def next(self): |
|||
return self.niter.__next__() |
|||
|
|||
def __init__(self, niter): |
|||
self.niter = niter |
|||
# TODELETE |
|||
|
|||
|
|||
def data_vysledkovky_cisla(cislo): |
|||
problemy = problemy_cisla(cislo) |
|||
hlavni_problemy = hlavni_problemy_f(problemy) |
|||
## TODO možná chytřeji vybírat aktivní řešitele |
|||
# aktivní řešitelé - chceme letos něco poslal, TODO později vyfiltrujeme ty, kdo mají |
|||
# u alespoň jedné hodnoty něco jiného než NULL |
|||
aktivni_resitele = list(resi_v_rocniku(cislo.rocnik)) |
|||
def body_resitelu( |
|||
za=None, |
|||
do: m.Deadline = None, |
|||
od: m.Deadline = None, |
|||
jen_verejne: bool = True, |
|||
resitele=None, |
|||
null=0 |
|||
) -> dict[int, int]: |
|||
filtr = Q() |
|||
|
|||
# získáme body za číslo |
|||
hlavni_problemy_slovnik, cislobody = secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy) |
|||
if jen_verejne: |
|||
filtr &= Q(reseni__hodnoceni__deadline_body__verejna_vysledkovka=True) |
|||
|
|||
# získáme body za ročník, seznam obsahuje dvojice (řešitel_id, body) setřízené sestupně |
|||
resitel_rocnikbody_sezn = secti_body_za_rocnik(cislo, aktivni_resitele, jen_verejne=True) |
|||
# Zjistíme, typ objektu v parametru "za" |
|||
if isinstance(za, m.Rocnik): |
|||
filtr &= Q(reseni__hodnoceni__deadline_body__cislo__rocnik=za) |
|||
elif isinstance(za, m.Cislo): |
|||
filtr &= Q(reseni__hodnoceni__deadline_body__cislo=za) |
|||
|
|||
if do: |
|||
filtr &= Q(reseni__hodnoceni__deadline_body__lte=do) |
|||
|
|||
if od: |
|||
filtr &= Q(reseni__hodnoceni__deadline_body__gte=od) |
|||
|
|||
resiteleQuery = m.Resitel.objects.all() |
|||
|
|||
if resitele is not None: |
|||
resitele_id = [r.id for r in resitele] |
|||
resiteleQuery = resiteleQuery.filter(id__in=resitele_id) |
|||
|
|||
# získáme body odjakživa |
|||
resitel_odjakzivabody_slov = body_resitelu(aktivni_resitele, cislo, jen_verejne=True) |
|||
# Přidáme ke každému řešiteli údaj ".body" se součtem jejich bodů |
|||
resitele_s_body = resiteleQuery.annotate( |
|||
body=Sum('reseni__hodnoceni__body', filter=filtr)) |
|||
|
|||
# řešitelé setřídění podle bodů za číslo sestupně |
|||
setrizeni_resitele_id = [dvojice[0] for dvojice in resitel_rocnikbody_sezn] |
|||
|
|||
# spočítáme pořadí řešitelů |
|||
setrizeni_resitele_body = [dvojice[1] for dvojice in resitel_rocnikbody_sezn] |
|||
poradi = sloupec_s_poradim(setrizeni_resitele_body) |
|||
# Teď jen z QuerySetu řešitelů anotovaných body vygenerujeme slovník |
|||
# indexovaný řešitelským id obsahující body. |
|||
# Pokud jsou body None, nahradíme za 0. |
|||
slovnik = { |
|||
int(res.id): (res.body if res.body else null) for res in resitele_s_body |
|||
} |
|||
return slovnik |
|||
|
|||
# vytvoříme jednotlivé sloupce výsledkovky |
|||
radky_vysledkovky = [] |
|||
i = 0 |
|||
|
|||
class Vysledkovka(abc.ABC): |
|||
jen_verejne: bool |
|||
rocnik: m.Rocnik |
|||
do_deadlinu: m.Deadline |
|||
|
|||
@property |
|||
@abc.abstractmethod |
|||
def aktivni_resitele(self) -> list[m.Resitel]: |
|||
... |
|||
|
|||
@cached_property |
|||
def resitele_s_body_za_rocnik_setrizeny_seznam(self) -> list[tuple[int, int]]: |
|||
# spočítáme všem řešitelům jejich body za ročník |
|||
resitel_body_za_rocnik_slovnik = body_resitelu( |
|||
resitele=self.aktivni_resitele, |
|||
za=self.rocnik, |
|||
jen_verejne=self.jen_verejne, |
|||
do=self.do_deadlinu |
|||
) |
|||
|
|||
# zeptáme se na dvojice (řešitel, body) za ročník a setřídíme sestupně |
|||
resitele_s_body_za_rocnik_setrizeny_seznam = sorted( |
|||
resitel_body_za_rocnik_slovnik.items(), |
|||
key=lambda x: x[1], reverse=True |
|||
) |
|||
|
|||
return resitele_s_body_za_rocnik_setrizeny_seznam |
|||
|
|||
@cached_property |
|||
def body_za_rocnik_seznamy(self) -> tuple[list[int], list[int]]: |
|||
if len(self.resitele_s_body_za_rocnik_setrizeny_seznam) == 0: |
|||
return [], [] |
|||
return tuple(zip(*self.resitele_s_body_za_rocnik_setrizeny_seznam)) |
|||
|
|||
@cached_property |
|||
def setrizeni_resitele_id(self) -> list[int]: |
|||
return self.body_za_rocnik_seznamy[0] |
|||
|
|||
@cached_property |
|||
def setrizene_body(self) -> list[int]: |
|||
return self.body_za_rocnik_seznamy[1] |
|||
|
|||
@cached_property |
|||
def resitel_body_odjakziva_slovnik(self) -> dict[int, int]: |
|||
return body_resitelu(jen_verejne=self.jen_verejne, do=self.do_deadlinu) |
|||
|
|||
@cached_property |
|||
def poradi(self): |
|||
# ze seznamu obsahujícího setřízené body spočítáme sloupec s pořadím |
|||
aktualni_poradi = 1 |
|||
sloupec_s_poradim = [] |
|||
|
|||
# seskupíme seznam všech bodů podle hodnot |
|||
for index in range(0, len(self.setrizene_body)): |
|||
# pokud je pořadí větší než číslo řádku, tak jsme vypsali větší rozsah |
|||
# a chceme vypsat už jen prázdné místo, než dojdeme na správný řádek |
|||
if (index + 1) < aktualni_poradi: |
|||
sloupec_s_poradim.append("") |
|||
continue |
|||
velikost_skupiny = 0 |
|||
# zjistíme počet po sobě jdoucích stejných hodnot |
|||
while self.setrizene_body[index] == self.setrizene_body[ |
|||
index + velikost_skupiny]: |
|||
velikost_skupiny += 1 |
|||
# na konci musíme ošetřit přetečení seznamu |
|||
if (index + velikost_skupiny) > len(self.setrizene_body) - 1: |
|||
break |
|||
# pokud je velikost skupiny 1, vypíšu pořadí |
|||
if velikost_skupiny == 1: |
|||
sloupec_s_poradim.append(f"{aktualni_poradi}.") |
|||
# pokud je skupina větší, vypíšu rozsah |
|||
else: |
|||
sloupec_s_poradim.append( |
|||
f"{aktualni_poradi}.–{aktualni_poradi + velikost_skupiny - 1}." |
|||
) |
|||
# zvětšíme aktuální pořadí o tolik, kolik pozic bylo přeskočeno |
|||
aktualni_poradi += velikost_skupiny |
|||
return sloupec_s_poradim |
|||
|
|||
|
|||
class VysledkovkaRocniku(Vysledkovka): |
|||
|
|||
def __init__(self, rocnik: m.Rocnik, jen_verejne: bool = True): |
|||
self.rocnik = rocnik |
|||
self.jen_verejne = jen_verejne |
|||
self.do_deadlinu = m.Deadline.objects.filter(cislo__rocnik=rocnik).last() |
|||
|
|||
@cached_property |
|||
def aktivni_resitele(self) -> list[m.Resitel]: |
|||
return list(resi_v_rocniku(self.rocnik)) |
|||
|
|||
@cached_property |
|||
def cisla_rocniku(self) -> list[m.Cislo]: |
|||
return cisla_rocniku(self.rocnik, self.jen_verejne) |
|||
|
|||
@cached_property |
|||
def body_za_cisla_slovnik(self) -> dict[int, dict[int, int]]: |
|||
body_cisla_slovnik = dict() |
|||
for cislo in self.cisla_rocniku: |
|||
# získáme body za číslo |
|||
body_za_cislo = body_resitelu( |
|||
za=cislo, |
|||
resitele=self.aktivni_resitele, |
|||
jen_verejne=self.jen_verejne, |
|||
null="" |
|||
) |
|||
body_cisla_slovnik[cislo.id] = body_za_cislo |
|||
return body_cisla_slovnik |
|||
|
|||
class RadekVysledkovkyRocniku: |
|||
""" Obsahuje věci, které se hodí vědět při konstruování výsledkovky. |
|||
Umožňuje snazší práci v templatu (lepší, než seznam).""" |
|||
|
|||
def __init__(self, poradi, resitel, body_cisla_seznam, body_rocnik, body_odjakziva, rok): |
|||
self.poradi = poradi |
|||
self.resitel = resitel |
|||
self.rocnik_resitele = resitel.rocnik(rok) |
|||
self.body_rocnik = body_rocnik |
|||
self.body_celkem_odjakziva = body_odjakziva |
|||
self.body_cisla_seznam = body_cisla_seznam |
|||
self.titul = resitel.get_titul(body_odjakziva) |
|||
|
|||
@cached_property |
|||
def radky_vysledkovky(self) -> list[RadekVysledkovkyRocniku]: |
|||
radky_vysledkovky = [] |
|||
|
|||
i = 0 |
|||
setrizeni_resitele_dict = dict() |
|||
for r in m.Resitel.objects.filter( |
|||
id__in=self.setrizeni_resitele_id |
|||
).select_related('osoba'): |
|||
setrizeni_resitele_dict[r.id] = r |
|||
|
|||
for ar_id in self.setrizeni_resitele_id: |
|||
if self.setrizene_body[i] > 0: |
|||
# seznam počtu bodů daného řešitele pro jednotlivá čísla |
|||
body_cisla_seznam = [] |
|||
for cislo in self.cisla_rocniku: |
|||
body_cisla_seznam.append(self.body_za_cisla_slovnik[cislo.id][ar_id]) |
|||
|
|||
# Pokud řešitel dostal nějaké body |
|||
if self.resitele_s_body_za_rocnik_setrizeny_seznam[i] != 0: |
|||
# vytáhneme informace pro daného řešitele |
|||
radek = self.RadekVysledkovkyRocniku( |
|||
poradi=self.poradi[i], |
|||
resitel=setrizeni_resitele_dict[ar_id], |
|||
body_cisla_seznam=body_cisla_seznam, |
|||
body_rocnik=self.setrizene_body[i], |
|||
body_odjakziva=self.resitel_body_odjakziva_slovnik[ar_id], |
|||
rok=self.rocnik) # ročník semináře pro získání ročníku řešitele |
|||
radky_vysledkovky.append(radek) |
|||
|
|||
i += 1 |
|||
|
|||
return radky_vysledkovky |
|||
|
|||
|
|||
class VysledkovkaCisla(Vysledkovka): |
|||
def __init__( |
|||
self, |
|||
cislo: m.Cislo, |
|||
jen_verejne: bool = True, |
|||
do_deadlinu: m.Deadline = None |
|||
): |
|||
self.cislo = cislo |
|||
self.rocnik = cislo.rocnik |
|||
self.jen_verejne = jen_verejne |
|||
if do_deadlinu is None: |
|||
do_deadlinu = m.Deadline.objects.filter(cislo=cislo).last() |
|||
self.do_deadlinu = do_deadlinu |
|||
|
|||
@cached_property |
|||
def aktivni_resitele(self) -> list[m.Resitel]: |
|||
# TODO možná chytřeji vybírat aktivní řešitele |
|||
return list(resi_v_rocniku(self.rocnik)) |
|||
|
|||
@cached_property |
|||
def problemy(self) -> list[m.Problem]: |
|||
return problemy_cisla(self.cislo) |
|||
|
|||
@cached_property |
|||
def hlavni_problemy(self) -> list[m.Problem]: |
|||
return hlavni_problemy_f(self.problemy) |
|||
|
|||
@cached_property |
|||
def problemy_s_body_za_cislo(self): |
|||
|
|||
hlavni_problemy_slovnik = dict() |
|||
for hp in self.hlavni_problemy: |
|||
hlavni_problemy_slovnik[hp.id] = {} |
|||
|
|||
hlavni_problemy_slovnik[-1] = {} |
|||
|
|||
# zakládání prázdných záznamů pro řešitele |
|||
cislobody = {} |
|||
for ar in self.aktivni_resitele: |
|||
# řešitele převedeme na řetězec pomocí unikátního id |
|||
cislobody[ar.id] = "" |
|||
for hp in self.temata_a_spol: |
|||
slovnik = hlavni_problemy_slovnik[hp.id] |
|||
slovnik[ar.id] = "" |
|||
|
|||
hlavni_problemy_slovnik[-1][ar.id] = "" |
|||
|
|||
hodnoceni_do_cisla = m.Hodnoceni.objects.prefetch_related( |
|||
'problem', 'reseni', 'reseni__resitele').filter(deadline_body__cislo=self.cislo) |
|||
|
|||
for hodnoceni in hodnoceni_do_cisla: |
|||
prob = hodnoceni.problem |
|||
nadproblem = hlavni_problem(prob) |
|||
if self.ne_clanek_ne_konfera(nadproblem): |
|||
nadproblem_slovnik = hlavni_problemy_slovnik[nadproblem.id] |
|||
else: |
|||
nadproblem_slovnik = hlavni_problemy_slovnik[-1] |
|||
|
|||
body = hodnoceni.body |
|||
|
|||
# a mít více řešitelů |
|||
for resitel in hodnoceni.reseni.resitele.all(): |
|||
if resitel not in self.aktivni_resitele: |
|||
continue |
|||
self.pricti_body(cislobody, resitel, body) |
|||
self.pricti_body(nadproblem_slovnik, resitel, body) |
|||
return hlavni_problemy_slovnik, cislobody |
|||
|
|||
@cached_property |
|||
def hlavni_problemy_slovnik(self) -> dict[int, dict[int, str]]: |
|||
return self.problemy_s_body_za_cislo[0] |
|||
|
|||
@cached_property |
|||
def body_za_cislo(self) -> dict[int, str]: |
|||
return self.problemy_s_body_za_cislo[1] |
|||
|
|||
@cached_property |
|||
def temata_a_spol(self) -> list[m.Problem]: |
|||
if self.cislo.rocnik.rocnik < ROCNIK_ZRUSENI_TEMAT: |
|||
return self.hlavni_problemy |
|||
else: |
|||
return list(filter(self.ne_clanek_ne_konfera, self.hlavni_problemy)) |
|||
|
|||
@cached_property |
|||
def je_nejake_ostatni(self): |
|||
return len(self.hlavni_problemy) - len(self.temata_a_spol) > 0 |
|||
|
|||
@cached_property |
|||
def podproblemy(self) -> list[list[m.Problem]]: |
|||
return podproblemy_v_cislu(self.cislo, self.problemy, self.temata_a_spol) |
|||
|
|||
@cached_property |
|||
def podproblemy_seznam(self) -> list[list[m.Problem]]: |
|||
return [self.podproblemy[it.id] for it in self.temata_a_spol] + [self.podproblemy[-1]] |
|||
|
|||
@cached_property |
|||
def podproblemy_iter(self) -> FixedIterator: |
|||
return FixedIterator(self.podproblemy_seznam.__iter__()) |
|||
|
|||
@cached_property |
|||
def problemy_slovnik(self): |
|||
# získáme body u jednotlivých témat |
|||
""" Spočítá u řešitelů body za číslo za úlohy v jednotlivých hlavních |
|||
problémech (témata). """ |
|||
|
|||
body_slovnik = {} |
|||
for tema in self.temata_a_spol: |
|||
body_slovnik[tema.id] = {} |
|||
for problem in self.podproblemy[tema.id]: |
|||
body_slovnik[tema.id][problem.id] = {} |
|||
body_slovnik[-1] = {} |
|||
for problem in self.podproblemy[-1]: |
|||
body_slovnik[-1][problem.id] = {} |
|||
|
|||
# zakládání prázdných záznamů pro řešitele |
|||
for ar in self.aktivni_resitele: |
|||
for tema in self.temata_a_spol: |
|||
for problem in self.podproblemy[tema.id]: |
|||
body_slovnik[tema.id][problem.id][ar.id] = "" |
|||
|
|||
for problem in self.podproblemy[-1]: |
|||
body_slovnik[-1][problem.id][ar.id] = "" |
|||
|
|||
temata = set(t.id for t in self.temata_a_spol) |
|||
|
|||
hodnoceni = m.Hodnoceni.objects.prefetch_related( |
|||
'problem', 'reseni', 'reseni__resitele') |
|||
if self.jen_verejne: |
|||
hodnoceni = hodnoceni.filter(deadline_body__verejna_vysledkovka=True) |
|||
hodnoceni_do_cisla = hodnoceni.filter(deadline_body__cislo=self.cislo) |
|||
|
|||
for hodnoceni in hodnoceni_do_cisla: |
|||
prob = hodnoceni.problem |
|||
nadproblem = hlavni_problem(prob) |
|||
if nadproblem.id in temata: |
|||
nadproblem_slovnik = body_slovnik[nadproblem.id] |
|||
else: |
|||
nadproblem_slovnik = body_slovnik[-1] |
|||
|
|||
problem_slovnik = nadproblem_slovnik[prob.id] |
|||
|
|||
body = hodnoceni.body |
|||
|
|||
# a mít více řešitelů |
|||
for resitel in hodnoceni.reseni.resitele.all(): |
|||
if resitel not in self.aktivni_resitele: |
|||
continue |
|||
self.pricti_body(problem_slovnik, resitel, body) |
|||
return body_slovnik |
|||
|
|||
class RadekVysledkovkyCisla(object): |
|||
"""Obsahuje věci, které se hodí vědět při konstruování výsledkovky. |
|||
Umožňuje snazší práci v templatu (lepší, než seznam).""" |
|||
|
|||
def __init__(self, poradi, resitel, body_hlavni_problemy_seznam, body_cislo, body_rocnik, body_odjakziva, rok, body_podproblemy, body_podproblemy_iter): |
|||
self.resitel = resitel |
|||
self.rocnik_resitele = resitel.rocnik(rok) |
|||
self.body_cislo = body_cislo |
|||
self.body_rocnik = body_rocnik |
|||
self.body_celkem_odjakziva = body_odjakziva |
|||
self.poradi = poradi |
|||
self.body_hlavni_problemy_seznam = body_hlavni_problemy_seznam |
|||
self.titul = resitel.get_titul(body_odjakziva) |
|||
self.body_podproblemy = body_podproblemy |
|||
self.body_podproblemy_iter = body_podproblemy_iter |
|||
|
|||
@cached_property |
|||
def radky_vysledkovky(self) -> list[RadekVysledkovkyCisla]: |
|||
# vytvoříme jednotlivé sloupce výsledkovky |
|||
radky_vysledkovky = [] |
|||
i = 0 |
|||
|
|||
setrizeni_resitele_slovnik = {} |
|||
setrizeni_resitele = m.Resitel.objects.filter(id__in=self.setrizeni_resitele_id).select_related('osoba') |
|||
|
|||
for r in setrizeni_resitele: |
|||
setrizeni_resitele_slovnik[r.id] = r |
|||
|
|||
for ar_id in self.setrizeni_resitele_id: |
|||
if self.setrizene_body[i] > 0: |
|||
# získáme seznam bodů za problémy pro daného řešitele |
|||
body_problemy = [] |
|||
body_podproblemy = [] |
|||
for hp in self.temata_a_spol: |
|||
body_problemy.append(self.hlavni_problemy_slovnik[hp.id][ar_id]) |
|||
body_podproblemy.append([ |
|||
self.problemy_slovnik[hp.id][it.id][ar_id] |
|||
for it in self.podproblemy[hp.id] |
|||
]) |
|||
if self.je_nejake_ostatni: |
|||
body_problemy.append(self.hlavni_problemy_slovnik[-1][ar_id]) |
|||
body_podproblemy.append( |
|||
[self.problemy_slovnik[-1][it.id][ar_id] for it in self.podproblemy[-1]]) |
|||
# vytáhneme informace pro daného řešitele |
|||
radek = self.RadekVysledkovkyCisla( |
|||
poradi=self.poradi[i], |
|||
resitel=setrizeni_resitele_slovnik[ar_id], |
|||
body_hlavni_problemy_seznam=body_problemy, |
|||
body_cislo=self.body_za_cislo[ar_id], |
|||
body_rocnik=self.setrizene_body[i], |
|||
body_odjakziva=self.resitel_body_odjakziva_slovnik[ar_id], |
|||
rok=self.rocnik, |
|||
body_podproblemy=body_podproblemy, # body všech podproblémů |
|||
body_podproblemy_iter=FixedIterator(body_podproblemy.__iter__()) |
|||
) # ročník semináře pro zjištění ročníku řešitele |
|||
radky_vysledkovky.append(radek) |
|||
i += 1 |
|||
return radky_vysledkovky |
|||
|
|||
@staticmethod |
|||
def pricti_body(slovnik, resitel, body): |
|||
""" Přiřazuje danému řešiteli body do slovníku. """ |
|||
# testujeme na None (""), pokud je to první řešení |
|||
# daného řešitele, předěláme na 0 |
|||
# (v dalším kroku přičteme reálný počet bodů), |
|||
# rozlišujeme tím mezi 0 a neodevzdaným řešením |
|||
|
|||
# Speciálně pokud jsou body None (hodnocení není obodované), vraťse |
|||
# TODO nejde to udělat lépe? |
|||
if body is None: |
|||
return |
|||
|
|||
if slovnik[resitel.id] == "": |
|||
slovnik[resitel.id] = 0 |
|||
|
|||
slovnik[resitel.id] += body |
|||
|
|||
@staticmethod |
|||
def ne_clanek_ne_konfera(problem): |
|||
|
|||
return not(isinstance(problem.get_real_instance(), m.Clanek) or isinstance(problem.get_real_instance(), m.Konfera)) |
|||
|
|||
if cislo.rocnik.rocnik < ROCNIK_ZRUSENI_TEMAT: |
|||
temata_a_spol = hlavni_problemy |
|||
else: |
|||
temata_a_spol = list(filter(ne_clanek_ne_konfera, hlavni_problemy)) |
|||
|
|||
# získáme body u jednotlivých témat |
|||
podproblemy = podproblemy_v_cislu(cislo, problemy, temata_a_spol) |
|||
problemy_slovnik = secti_body_za_cislo_podle_temat(cislo, aktivni_resitele, podproblemy, temata_a_spol) |
|||
|
|||
# def not_empty(value): |
|||
# return value != '' |
|||
# |
|||
# je_nejake_ostatni = any(filter(not_empty, hlavni_problemy_slovnik[-1].values())) > 0 |
|||
|
|||
je_nejake_ostatni = len(hlavni_problemy) - len(temata_a_spol) > 0 |
|||
|
|||
setrizeni_resitele_slovnik = {} |
|||
setrizeni_resitele = m.Resitel.objects.filter(id__in=setrizeni_resitele_id).select_related('osoba') |
|||
for r in setrizeni_resitele: |
|||
setrizeni_resitele_slovnik[r.id] = r |
|||
|
|||
for ar_id in setrizeni_resitele_id: |
|||
# získáme seznam bodů za problémy pro daného řešitele |
|||
body_problemy = [] |
|||
body_podproblemy = [] |
|||
for hp in temata_a_spol: |
|||
body_problemy.append(hlavni_problemy_slovnik[hp.id][ar_id]) |
|||
body_podproblemy.append([problemy_slovnik[hp.id][it.id][ar_id] for it in podproblemy[hp.id]]) |
|||
if je_nejake_ostatni: |
|||
body_problemy.append(hlavni_problemy_slovnik[-1][ar_id]) |
|||
body_podproblemy.append([problemy_slovnik[-1][it.id][ar_id] for it in podproblemy[-1]]) |
|||
# vytáhneme informace pro daného řešitele |
|||
radek = RadekVysledkovkyCisla( |
|||
poradi[i], # pořadí |
|||
setrizeni_resitele_slovnik[ar_id], # řešitel (z id) |
|||
body_problemy, # seznam bodů za hlavní problémy čísla |
|||
cislobody[ar_id], # body za číslo |
|||
setrizeni_resitele_body[i], # body za ročník (spočítané výše s pořadím) |
|||
resitel_odjakzivabody_slov[ar_id], # body odjakživa |
|||
cislo.rocnik, |
|||
body_podproblemy, # body všech podproblémů |
|||
FixedIterator(body_podproblemy.__iter__()) # TODELETE |
|||
) # ročník semináře pro zjištění ročníku řešitele |
|||
radky_vysledkovky.append(radek) |
|||
i += 1 |
|||
|
|||
# vytahané informace předáváme do kontextu |
|||
pt = [podproblemy[it.id] for it in temata_a_spol]+[podproblemy[-1]] |
|||
radky_vysledkovky = [radek for radek in radky_vysledkovky if radek.body_rocnik > 0] |
|||
return ( |
|||
radky_vysledkovky, |
|||
temata_a_spol, |
|||
je_nejake_ostatni, |
|||
pt, |
|||
FixedIterator(pt.__iter__()) |
|||
) |
|||
inst = problem.get_real_instance() |
|||
return not (isinstance(inst, m.Clanek) or isinstance(inst, m.Konfera)) |
|||
|
@ -1,37 +0,0 @@ |
|||
from .utils import data_vysledkovky_cisla, \ |
|||
data_vysledkovky_rocniku |
|||
|
|||
|
|||
def vysledkovka_cisla(cislo, context=None): |
|||
if context is None: |
|||
context = {} |
|||
context['cislo'] = cislo |
|||
|
|||
( |
|||
context['radky_vysledkovky'], |
|||
context['problemy'], |
|||
context['ostatni'], |
|||
context['podproblemy'], |
|||
context['podproblemy_iter'] |
|||
) = data_vysledkovky_cisla(cislo) |
|||
return context |
|||
|
|||
|
|||
def vysledkovka_rocniku(rocnik, context=None, request=None, sneverejnou=False): |
|||
if context is None: |
|||
context = {} |
|||
|
|||
( |
|||
context['radky_vysledkovky'], |
|||
context['cisla'] |
|||
) = data_vysledkovky_rocniku(rocnik) |
|||
|
|||
context['vysledkovka'] = len(context['cisla']) != 0 |
|||
|
|||
if sneverejnou and request and request.user.je_org: |
|||
( |
|||
context['radky_vysledkovky_s_neverejnymi'], |
|||
context['cisla_s_neverejnymi'] |
|||
) = data_vysledkovky_rocniku(rocnik, jen_verejne=False) |
|||
|
|||
return context |
Loading…
Reference in new issue