|
|
@ -260,25 +260,35 @@ class ArchivView(generic.ListView): |
|
|
|
|
|
|
|
### Výsledky |
|
|
|
|
|
|
|
def sloupec_s_poradim(vysledky): |
|
|
|
# počet řešitelů ve výsledkovce nad aktuálním |
|
|
|
lepsich_resitelu = 0 |
|
|
|
|
|
|
|
poradi_l = [] |
|
|
|
# projdeme skupiny řešitelů se stejným počtem bodů |
|
|
|
for skupina in (list(x) for _, x in groupby(vysledky, lambda x: x.body)): |
|
|
|
|
|
|
|
# připravíme si obsahy buněk ve sloupci pořadí pro skupinu |
|
|
|
if len(skupina) == 1: |
|
|
|
poradi_l += ["{}.".format(lepsich_resitelu + 1)] |
|
|
|
# je-li účastníků se stejným počtem bodů víc, |
|
|
|
# pořadí (rozsah X.-Y.) je jen u prvního |
|
|
|
# ze seznamu všech bodů vytvoří seznam s pořadími (včetně 3.-5. a pak 2 volná místa atp.) |
|
|
|
def sloupec_s_poradim(seznam_s_body): |
|
|
|
aktualni_poradi = 1 |
|
|
|
sloupec_s_poradim = [] |
|
|
|
|
|
|
|
# seskupíme seznam všech bodů podle hodnot |
|
|
|
for index in range(0, len(seznam_s_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 seznam_s_body[index] == seznam_s_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(seznam_s_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: |
|
|
|
poradi_l += ["{}.–{}.".format(lepsich_resitelu + 1, lepsich_resitelu + len(skupina))] + [""] * (len(skupina)-1) |
|
|
|
lepsich_resitelu += len(skupina) |
|
|
|
#pomlcka je opravdu pomlcka v unicode!!dulezite pro vysledkovku v TeXu |
|
|
|
|
|
|
|
return poradi_l |
|
|
|
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 |
|
|
|
|
|
|
|
# spočítá součet bodů získaných daným řešitelem za zadaný problém a všechny jeho podproblémy |
|
|
|
def __soucet_resitele_problemu(problem, resitel, cislo, soucet): |
|
|
@ -323,6 +333,7 @@ def hlavni_problemy_cisla(cislo): |
|
|
|
# zunikátnění |
|
|
|
hlavni_problemy_set = set(hlavni_problemy) |
|
|
|
hlavni_problemy = list(hlavni_problemy_set) |
|
|
|
hlavni_problemy.sort(key=lambda k: k.kod_v_rocniku) # setřídit podle t1, t2, c3, ... |
|
|
|
|
|
|
|
return hlavni_problemy |
|
|
|
|
|
|
@ -331,7 +342,7 @@ def hlavni_problemy_cisla(cislo): |
|
|
|
def body_resitele_v_cisle(resitel, cislo): |
|
|
|
hlavni_problemy = hlavni_problemy_cisla(cislo) |
|
|
|
for h in hlavni_problemy: |
|
|
|
body_resitele = body_resitele + body_resitele_problemu_v_cisle(resitel, cislo) |
|
|
|
body_resitele = body_resitele + body_resitele_problemu_v_cisle(h, resitel, cislo) |
|
|
|
# TODO: je rozdíl mezi odevzdanou úlohou za 0 a tím, když řešitel nic neodevzdal |
|
|
|
# řešit přes kontrolu velikosti množiny řešení daného problému do daného čísla? |
|
|
|
# Tady to ale nevadí, tady se počítá součet za číslo. |
|
|
@ -456,19 +467,16 @@ class ProblemView(generic.DetailView): |
|
|
|
|
|
|
|
class VysledkyResitele(object): |
|
|
|
"""Pro daného řešitele ukládá počet bodů za jednotlivé úlohy a celkový |
|
|
|
počet bodů za konkrétní číslo.""" |
|
|
|
počet bodů za konkrétní ročník do daného čísla a za dané číslo.""" |
|
|
|
|
|
|
|
def __init__(self, resitel): |
|
|
|
def __init__(self, resitel, cislo, rocnik): |
|
|
|
resitel_jmeno = resitel.osoba.jmeno |
|
|
|
resitel_prijmeni = resitel.osoba.prijmeni |
|
|
|
body = {} |
|
|
|
body_rocnik = 0 |
|
|
|
|
|
|
|
def body_za_cislo(self): |
|
|
|
return sum(body.values()) |
|
|
|
|
|
|
|
def body_za_rocnik(self): |
|
|
|
return body_rocnik |
|
|
|
self.cislo = cislo |
|
|
|
body_cislo = body_resitele_v_cisle(resitel, cislo) |
|
|
|
body = [] |
|
|
|
self.rocnik = rocnik |
|
|
|
body_rocnik = body_resitele_v_rocniku(resitel, rocnik, cislo) |
|
|
|
|
|
|
|
class CisloView(generic.DetailView): |
|
|
|
model = Cislo |
|
|
@ -504,17 +512,18 @@ class CisloView(generic.DetailView): |
|
|
|
#.filter(hodnoceni_set__rocnik__eq=cislo_rocnik) |
|
|
|
radky_vysledkovky = [] |
|
|
|
for ar in aktivni_resitele: |
|
|
|
# získáme výsledky řešitele - součty přes jednotlivé hlavní problémy |
|
|
|
vr = VysledkyResitele(ar) |
|
|
|
# ukládání součtu bodů za všechny hlavní problémy => součet bodů za číslo |
|
|
|
vr.body_cislo = body_resitele_v_cisle(ar, cislo) |
|
|
|
# výpočet bodů za ročník do daného čísla (aby fungovalo i pro starší čísla) |
|
|
|
vr.body_rocnik = body_resitele_v_rocniku(ar, cislo.rocnik, cislo) |
|
|
|
# získáme výsledky řešitele - součty přes číslo a ročník |
|
|
|
vr = VysledkyResitele(ar, cislo, cislo.rocnik) |
|
|
|
for hp in hlavni_problemy: |
|
|
|
ar.body.append(body_resitele_problemu_v_cisle(hp, resitel, cislo)) |
|
|
|
radky_vysledkovky.append(vr) |
|
|
|
|
|
|
|
## TODO: seřadit řešitele podle bodů v daném ročníku |
|
|
|
## řazení viz fce výše - pochopit a případně přepsat |
|
|
|
|
|
|
|
## TODO: |
|
|
|
## vytvořit každému řešiteli objekt nesoucí jeho data |
|
|
|
## setřídit tyto objekty podle bodů |
|
|
|
## vygenerovat sloupec s pořadím pomocí stejně zvané funkce |
|
|
|
## předat to do kontextu |
|
|
|
# XXX |
|
|
|
|
|
|
|
# problemy = sorted(set(r.problem for r in reseni), key=lambda x:(poradi_typu[x.typ], x.kod_v_rocniku())) |
|
|
|
# #setridi problemy podle typu a poradi zadani |
|
|
@ -1013,16 +1022,24 @@ def logoutView(request): |
|
|
|
return render(request, 'seminar/login.html', {'form': form}) |
|
|
|
|
|
|
|
|
|
|
|
def prihlaska_log_gdpr_safe(logger, gdpr_logger, msg, form_data): |
|
|
|
msg = "{}, form_hash:{}".format(msg,hash(form_data)) |
|
|
|
logger.warn(msg) |
|
|
|
gdpr_logger.warn(msg+", form:{}".format(form_data)) |
|
|
|
|
|
|
|
|
|
|
|
def prihlaskaView(request): |
|
|
|
generic_logger = logging.getLogger('seminar.prihlaska') |
|
|
|
err_logger = logging.getLogger('seminar.prihlaska.problem') |
|
|
|
form_logger = logging.getLogger('seminar.prihlaska.form') |
|
|
|
if request.method == 'POST': |
|
|
|
form = PrihlaskaForm(request.POST) |
|
|
|
# TODO vyresit, co se bude v jakych situacich zobrazovat |
|
|
|
if form.is_valid(): |
|
|
|
generic_logger.info("Form valid") |
|
|
|
fcd = form.cleaned_data |
|
|
|
form_hash = hash(frozenset(fcd.items())) |
|
|
|
fcd["hash"] = form_hash |
|
|
|
form_logger.info(fcd) |
|
|
|
form_hash = hash(fcd) |
|
|
|
form_logger.info(fcd,form_hash=form_hash) |
|
|
|
|
|
|
|
with transaction.atomic(): |
|
|
|
u = User.objects.create_user( |
|
|
@ -1051,7 +1068,8 @@ def prihlaskaView(request): |
|
|
|
o.stat = fcd['stat'] |
|
|
|
else: |
|
|
|
# Unknown country - log it |
|
|
|
err_logger.warn("Unknown country {}. Form hash:{}".format(fcd['stat_text'],form_hash)) |
|
|
|
msg = "Unknown country {}".format(fcd['stat_text']) |
|
|
|
err_logger.warn(msg,form_hash=form_hash) |
|
|
|
|
|
|
|
o.save() |
|
|
|
o.user = u |
|
|
@ -1068,7 +1086,8 @@ def prihlaskaView(request): |
|
|
|
r.skola = fcd['skola'] |
|
|
|
else: |
|
|
|
# Unknown school - log it |
|
|
|
err_logger.warn("Unknown school {}, {}. Form hash:{}".format(fcd['skola_nazev'],fcd['skola_adresa'],form_hash)) |
|
|
|
msg = "Unknown school {}, {}".format(fcd['skola_nazev'],fcd['skola_adresa']) |
|
|
|
err_logger.warn(msg,form_hash=form_hash) |
|
|
|
r.save() |
|
|
|
|
|
|
|
|
|
|
|