|
@ -252,6 +252,7 @@ class ArchivView(generic.ListView): |
|
|
context["nahledy"] = "\n".join(tags) |
|
|
context["nahledy"] = "\n".join(tags) |
|
|
return context |
|
|
return context |
|
|
|
|
|
|
|
|
|
|
|
### Výsledky |
|
|
|
|
|
|
|
|
def sloupec_s_poradim(vysledky): |
|
|
def sloupec_s_poradim(vysledky): |
|
|
# počet řešitelů ve výsledkovce nad aktuálním |
|
|
# počet řešitelů ve výsledkovce nad aktuálním |
|
@ -264,14 +265,80 @@ def sloupec_s_poradim(vysledky): |
|
|
# připravíme si obsahy buněk ve sloupci pořadí pro skupinu |
|
|
# připravíme si obsahy buněk ve sloupci pořadí pro skupinu |
|
|
if len(skupina) == 1: |
|
|
if len(skupina) == 1: |
|
|
poradi_l += ["{}.".format(lepsich_resitelu + 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 |
|
|
# je-li účastníků se stejným počtem bodů víc, |
|
|
|
|
|
# pořadí (rozsah X.-Y.) je jen u prvního |
|
|
else: |
|
|
else: |
|
|
poradi_l += [u"{}.–{}.".format(lepsich_resitelu + 1, lepsich_resitelu + len(skupina))] + [""] * (len(skupina)-1) |
|
|
poradi_l += ["{}.–{}.".format(lepsich_resitelu + 1, lepsich_resitelu + len(skupina))] + [""] * (len(skupina)-1) |
|
|
lepsich_resitelu += len(skupina) |
|
|
lepsich_resitelu += len(skupina) |
|
|
#pomlcka je opravdu pomlcka v unicode!!dulezite pro vysledkovku v TeXu |
|
|
#pomlcka je opravdu pomlcka v unicode!!dulezite pro vysledkovku v TeXu |
|
|
|
|
|
|
|
|
return poradi_l |
|
|
return poradi_l |
|
|
|
|
|
|
|
|
|
|
|
# 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, soucet): |
|
|
|
|
|
# FIXME: správně je nadproblem_(typ problemu), ale to by bylo potřeba nějak |
|
|
|
|
|
# zjistit, jaký typ nodu to vlastně je a aplikovat to ve volání funkce |
|
|
|
|
|
|
|
|
|
|
|
# sečteme body za daný problém přes všechna řešení daného problému |
|
|
|
|
|
# od daného řešitele |
|
|
|
|
|
reseni_resitele = problem.hodnoceni_set.filter(reseni_resitele__contains=resitel) |
|
|
|
|
|
for r in reseni_resitele: |
|
|
|
|
|
soucet += r.body |
|
|
|
|
|
|
|
|
|
|
|
for p in problem.nadproblem_set: |
|
|
|
|
|
# i přes jméno by to měla být množina jeho podproblémů |
|
|
|
|
|
soucet += __soucet_resitele_problemu(p, resitel, soucet) |
|
|
|
|
|
return soucet |
|
|
|
|
|
|
|
|
|
|
|
# spočítá součet všech bodů ze všech podproblémů daného problému daného řešitele |
|
|
|
|
|
def body_resitele_problemu_v_cisle(problem, resitel, cislo): |
|
|
|
|
|
return __soucet_resitele_problemu(problem, resitel, 0) |
|
|
|
|
|
|
|
|
|
|
|
# vrátí list všech problémů s body v daném čísle, které již nemají nadproblém |
|
|
|
|
|
def hlavni_problemy_cisla(cislo): |
|
|
|
|
|
hodnoceni = cislo.hodnoceni_set # hodnocení, která se vážou k danému číslu |
|
|
|
|
|
|
|
|
|
|
|
reseni = [h.reseni for h in hodnoceni] |
|
|
|
|
|
problemy = [h.problem for h in hodnoceni] |
|
|
|
|
|
problemy_set = set(problemy) # chceme každý problém unikátně, |
|
|
|
|
|
problemy = (list(problemy_set)) # převedení na množinu a zpět to zaručí |
|
|
|
|
|
|
|
|
|
|
|
# hlavní problémy čísla |
|
|
|
|
|
# (mají vlastní sloupeček ve výsledkovce, nemají nadproblém) |
|
|
|
|
|
hlavni_problemy = [] |
|
|
|
|
|
for p in problemy: |
|
|
|
|
|
while not(p.nadproblem == None): |
|
|
|
|
|
p = p.nadproblem |
|
|
|
|
|
hlavni_problemy.append(p) |
|
|
|
|
|
|
|
|
|
|
|
# zunikátnění |
|
|
|
|
|
hlavni_problemy_set = set(hlavni_problemy) |
|
|
|
|
|
hlavni_problemy = list(hlavni_problemy_set) |
|
|
|
|
|
|
|
|
|
|
|
return hlavni_problemy |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# spočítá součet všech bodů řešitele za dané číslo |
|
|
|
|
|
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) |
|
|
|
|
|
# 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. |
|
|
|
|
|
return body_resitele |
|
|
|
|
|
|
|
|
|
|
|
# spočítá součet všech bodů řešitele za daný rok (nebo jen do daného čísla včetně) |
|
|
|
|
|
def body_resitele_v_rocniku(resitel, rocnik_node, do_cisla=None) |
|
|
|
|
|
# pokud do_cisla=None, tak do posledního čísla v ročníku |
|
|
|
|
|
# do_cisla je objekt Cislo |
|
|
|
|
|
cislo_node = rocnik_node.firstChild |
|
|
|
|
|
body = 0 |
|
|
|
|
|
while not (cislo_node = None or cislo_node.cislo = do_cisla.CisloNode.next): |
|
|
|
|
|
# druhá část zaručuje, že máme výsledky do daného čísla včetně |
|
|
|
|
|
body = body + body_resitele_v_cisle(resitel, cislo_node.cislo) |
|
|
|
|
|
cislo_node = cislo_node.next |
|
|
|
|
|
return body |
|
|
|
|
|
|
|
|
#def vysledkovka_rocniku(rocnik, jen_verejne=True): |
|
|
#def vysledkovka_rocniku(rocnik, jen_verejne=True): |
|
|
# """Přebírá ročník (např. context["rocnik"]) a vrací výsledkovou listinu ve |
|
|
# """Přebírá ročník (např. context["rocnik"]) a vrací výsledkovou listinu ve |
|
@ -380,11 +447,11 @@ class ProblemView(generic.DetailView): |
|
|
|
|
|
|
|
|
class VysledkyResitele(object): |
|
|
class VysledkyResitele(object): |
|
|
"""Pro daného řešitele ukládá počet bodů za jednotlivé úlohy a celkový |
|
|
"""Pro daného řešitele ukládá počet bodů za jednotlivé úlohy a celkový |
|
|
počet bodů za číslo.""" |
|
|
počet bodů za konkrétní číslo.""" |
|
|
|
|
|
|
|
|
def __init__(self, jmeno, prijmeni): |
|
|
def __init__(self, resitel): |
|
|
resitel_jmeno = jmeno |
|
|
resitel_jmeno = resitel.osoba.jmeno |
|
|
resitel_prijmeni = prijmeni |
|
|
resitel_prijmeni = resitel.osoba.prijmeni |
|
|
body = {} |
|
|
body = {} |
|
|
body_cislo = 0 |
|
|
body_cislo = 0 |
|
|
|
|
|
|
|
@ -410,50 +477,12 @@ class CisloView(generic.DetailView): |
|
|
{'verbose_name': queryset.model._meta.verbose_name}) |
|
|
{'verbose_name': queryset.model._meta.verbose_name}) |
|
|
return obj |
|
|
return obj |
|
|
|
|
|
|
|
|
# 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, soucet): |
|
|
|
|
|
# FIXME: správně je nadproblem_(typ problemu), ale to by bylo potřeba nějak |
|
|
|
|
|
# zjistit, jaký typ nodu to vlastně je a aplikovat to ve volání funkce |
|
|
|
|
|
|
|
|
|
|
|
# sečteme body za daný problém přes všechna řešení daného problému |
|
|
|
|
|
# od daného řešitele |
|
|
|
|
|
reseni_resitele = problem.hodnoceni_set.filter(reseni_resitele__contains=resitel) |
|
|
|
|
|
for r in reseni_resitele: |
|
|
|
|
|
soucet += r.body |
|
|
|
|
|
|
|
|
|
|
|
for p in problem.nadproblem_set: |
|
|
|
|
|
# i přes jméno by to měla být množina jeho podproblémů |
|
|
|
|
|
soucet += __soucet_resitele_problemu(p, resitel, soucet) |
|
|
|
|
|
return soucet |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def vysledky_resitele_problemu(problem, resitel, cislo): |
|
|
|
|
|
return __soucet_resitele_problemu(problem, resitel, 0) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs): |
|
|
def get_context_data(self, **kwargs): |
|
|
context = super(CisloView, self).get_context_data(**kwargs) |
|
|
context = super(CisloView, self).get_context_data(**kwargs) |
|
|
|
|
|
|
|
|
## TODO upravit dle nového modelu |
|
|
## TODO upravit dle nového modelu |
|
|
cislo = context['cislo'] |
|
|
cislo = context['cislo'] |
|
|
hodnoceni = cislo.hodnoceni_set # hodnocení, která se vážou k danému číslu |
|
|
hlavni_problemy = hlavni_problemy_cisla(cislo) |
|
|
|
|
|
|
|
|
reseni = [h.reseni for h in hodnoceni] |
|
|
|
|
|
problemy = [h.problem for h in hodnoceni] |
|
|
|
|
|
problemy_set = set(problemy) # chceme každý problém unikátně, |
|
|
|
|
|
problemy = (list(problemy_set)) # převedení na množinu a zpět to zaručí |
|
|
|
|
|
|
|
|
|
|
|
# hlavní problémy čísla |
|
|
|
|
|
# (mají vlastní sloupeček ve výsledkovce, nemají nadproblém) |
|
|
|
|
|
hlavni_problemy = [] |
|
|
|
|
|
for p in problemy: |
|
|
|
|
|
while not(p.nadproblem == None): |
|
|
|
|
|
p = nadproblem |
|
|
|
|
|
hlavni_problemy.append(p) |
|
|
|
|
|
|
|
|
|
|
|
# zunikátnění |
|
|
|
|
|
hlavni_problemy_set = set(hlavni_problemy) |
|
|
|
|
|
hlavni_problemy = list(hlavni_problemy_set) |
|
|
|
|
|
|
|
|
|
|
|
## TODO dostat pro tyto problémy součet v daném čísle pro daného řešitele |
|
|
## TODO dostat pro tyto problémy součet v daném čísle pro daného řešitele |
|
|
## TODO možná chytřeji vybírat aktivní řešitele |
|
|
## TODO možná chytřeji vybírat aktivní řešitele |
|
@ -463,15 +492,16 @@ class CisloView(generic.DetailView): |
|
|
#.filter(hodnoceni_set__rocnik__eq=cislo_rocnik) |
|
|
#.filter(hodnoceni_set__rocnik__eq=cislo_rocnik) |
|
|
radky_vysledkovky = [] |
|
|
radky_vysledkovky = [] |
|
|
for ar in aktivni_resitele: |
|
|
for ar in aktivni_resitele: |
|
|
vr = VysledkyResitele(ar.jmeno, ar.prijmeni) |
|
|
vr = VysledkyResitele(ar) |
|
|
for h in hlavni_problemy: |
|
|
for h in hlavni_problemy: |
|
|
body = vysledky_resitele_problemu(h, ar, cislo) |
|
|
body = body_resitele_problemu_v_cisle(h, ar, cislo) |
|
|
vr.body[h.kod_v_rocniku] = body |
|
|
# vr.body[h.kod_v_rocniku] = body |
|
|
vr.body_cislo = vr.body_cislo + body |
|
|
vr.body_cislo = vr.body_cislo + body |
|
|
radky_vysledkovky.append(vr) |
|
|
radky_vysledkovky.append(vr) |
|
|
|
|
|
|
|
|
## TODO: spočítat počet bodů řešitele v daném ročníku a seřadit je podle toho |
|
|
## TODO: spočítat počet bodů řešitele v daném ročníku a seřadit je podle toho |
|
|
## TODO: možná použít tyto funkce i v RocnikVysledkovkaView (a umístit sem nebo tam)? |
|
|
## řazení viz fce výše - pochopit a případně přepsat |
|
|
|
|
|
## počet bodů udělat ve fce body_resitele_v_rocniku |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# vysledky = VysledkyKCisluZaRocnik.objects.filter(cislo = context['cislo']).\ |
|
|
# vysledky = VysledkyKCisluZaRocnik.objects.filter(cislo = context['cislo']).\ |
|
@ -487,6 +517,7 @@ class CisloView(generic.DetailView): |
|
|
# |
|
|
# |
|
|
# poradi_typu = { |
|
|
# poradi_typu = { |
|
|
# Problem.TYP_ULOHA: 1, |
|
|
# Problem.TYP_ULOHA: 1, |
|
|
|
|
|
|
|
|
# Problem.TYP_SERIAL: 2, |
|
|
# Problem.TYP_SERIAL: 2, |
|
|
# Problem.TYP_ORG_CLANEK: 3, |
|
|
# Problem.TYP_ORG_CLANEK: 3, |
|
|
# Problem.TYP_TEMA: 4, |
|
|
# Problem.TYP_TEMA: 4, |
|
@ -529,7 +560,7 @@ class CisloView(generic.DetailView): |
|
|
# context['problemy'] = problemy |
|
|
# context['problemy'] = problemy |
|
|
# context['v_cisle_zadane'] = v_cisle_zadane |
|
|
# context['v_cisle_zadane'] = v_cisle_zadane |
|
|
# context['resene_problemy'] = resene_problemy |
|
|
# context['resene_problemy'] = resene_problemy |
|
|
# return context |
|
|
return context |
|
|
|
|
|
|
|
|
class ArchivTemataView(generic.ListView): |
|
|
class ArchivTemataView(generic.ListView): |
|
|
model = Problem |
|
|
model = Problem |
|
|