|
|
@ -426,28 +426,34 @@ def sloupec_s_poradim(seznam_s_body): |
|
|
|
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): |
|
|
|
# sečteme body za daný problém přes všechna řešení daného problému |
|
|
|
# od daného řešitele |
|
|
|
reseni_resitele = Reseni.objects.filter(resitele__in=resitel) |
|
|
|
hodnoceni_resitele = problem.hodnoceni.filter(reseni__in=reseni_resitele, |
|
|
|
cislo_body=cislo) |
|
|
|
# XXX chyba na řádku výše - řešení může mít více řešitelů, asi chceme contains |
|
|
|
# nebo in |
|
|
|
for r in hodnoceni_resitele: |
|
|
|
soucet += r.body |
|
|
|
|
|
|
|
# a přičteme k tomu hodnocení všech podproblémů |
|
|
|
for p in problem.podproblem.all(): |
|
|
|
# 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): |
|
|
|
# probably FIXED: nezohledňuje číslo, do kterého se body počítají |
|
|
|
return __soucet_resitele_problemu(problem, resitel, cislo, 0) |
|
|
|
## 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): |
|
|
|
# # sečteme body za daný problém přes všechna řešení daného problému |
|
|
|
# # od daného řešitele |
|
|
|
# reseni_resitele = s.Reseni_Resitele.objects.filter(resitele=resitel) |
|
|
|
# hodnoceni_resitele = problem.hodnoceni.filter(reseni__in=reseni_resitele, |
|
|
|
# cislo_body=cislo) |
|
|
|
# # XXX chyba na řádku výše - řešení může mít více řešitelů, asi chceme contains |
|
|
|
# # nebo in |
|
|
|
# for r in hodnoceni_resitele: |
|
|
|
# soucet += r.body |
|
|
|
# |
|
|
|
# # a přičteme k tomu hodnocení všech podproblémů |
|
|
|
# for p in problem.podproblem.all(): |
|
|
|
# # 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): |
|
|
|
# # probably FIXED: nezohledňuje číslo, do kterého se body počítají |
|
|
|
# return __soucet_resitele_problemu(problem, resitel, cislo, 0) |
|
|
|
|
|
|
|
# pro daný problém vrátí jeho nejvyšší nadproblém |
|
|
|
def hlavni_problem(problem): |
|
|
|
while not(problem.nadproblem == None): |
|
|
|
problem = problem.nadproblem |
|
|
|
return problem |
|
|
|
|
|
|
|
# vrátí list všech problémů s body v daném čísle, které již nemají nadproblém |
|
|
|
def hlavni_problemy_cisla(cislo): |
|
|
@ -463,9 +469,7 @@ def hlavni_problemy_cisla(cislo): |
|
|
|
# (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) |
|
|
|
hlavni_problemy.append(hlavni_problem(p)) |
|
|
|
|
|
|
|
# zunikátnění |
|
|
|
hlavni_problemy_set = set(hlavni_problemy) |
|
|
@ -474,38 +478,54 @@ def hlavni_problemy_cisla(cislo): |
|
|
|
|
|
|
|
return hlavni_problemy |
|
|
|
|
|
|
|
def body_resitele_odjakziva(resitel): |
|
|
|
body = 0 |
|
|
|
resitelova_hodnoceni = Hodnoceni.objects.select_related('body').all().filter(reseni_resitele=resitel) |
|
|
|
# TODO: v radku nahore chceme _in nebo _contains |
|
|
|
for hodnoceni in resitelova_hodnoceni: |
|
|
|
body = body + hodnoceni.body |
|
|
|
return body |
|
|
|
# vrátí slovník řešitel:body obsahující počty bodů zadaných řešitelů za daný ročník |
|
|
|
def body_resitelu_za_rocnik(rocnik, aktivni_resitele): |
|
|
|
body_za_rocnik = {} |
|
|
|
# inicializujeme na 0 pro všechny aktivní řešitele |
|
|
|
for ar in aktivni_resitele: |
|
|
|
body_za_rocnik[str(ar.id)] = 0 |
|
|
|
|
|
|
|
# spočítáme body řešitelům přes všechna řešení s hodnocením v daném ročníku |
|
|
|
reseni = Reseni.objects.filter(hodnoceni__cislo_body__rocnik=rocnik) |
|
|
|
for res in reseni: |
|
|
|
for resitel in res.resitele.all(): |
|
|
|
for hodn in res.hodnoceni.all(): |
|
|
|
body_za_rocnik[str(resitel.id)] += hodn.body |
|
|
|
return body_za_rocnik |
|
|
|
|
|
|
|
#def body_resitele_odjakziva(resitel): |
|
|
|
# body = 0 |
|
|
|
# resitelova_hodnoceni = Hodnoceni.objects.select_related('body').all().filter(reseni_resitele=resitel) |
|
|
|
# # TODO: v radku nahore chceme _in nebo _contains |
|
|
|
# for hodnoceni in resitelova_hodnoceni: |
|
|
|
# body = body + hodnoceni.body |
|
|
|
# return body |
|
|
|
|
|
|
|
# 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) |
|
|
|
body_resitele = 0 |
|
|
|
for h in hlavni_problemy: |
|
|
|
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. |
|
|
|
return body_resitele |
|
|
|
#def body_resitele_v_cisle(resitel, cislo): |
|
|
|
# hlavni_problemy = hlavni_problemy_cisla(cislo) |
|
|
|
# body_resitele = 0 |
|
|
|
# for h in hlavni_problemy: |
|
|
|
# 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. |
|
|
|
# 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, do_cisla=None): |
|
|
|
# pokud do_cisla=None, tak do posledního čísla v ročníku |
|
|
|
# do_cisla je objekt Cislo |
|
|
|
cisla = rocnik.cisla.all() # funkce vrátí pole objektů |
|
|
|
# Cislo už lexikograficky setřízené, viz models |
|
|
|
body = 0 |
|
|
|
for cislo in cisla: |
|
|
|
if cislo.poradi == do_cisla.poradi: break |
|
|
|
# druhá část zaručuje, že máme výsledky do daného čísla včetně |
|
|
|
body = body + body_resitele_v_cisle(resitel, cislo) |
|
|
|
return body |
|
|
|
#def body_resitele_v_rocniku(resitel, rocnik, do_cisla=None): |
|
|
|
# # pokud do_cisla=None, tak do posledního čísla v ročníku |
|
|
|
# # do_cisla je objekt Cislo |
|
|
|
# cisla = rocnik.cisla.all() # funkce vrátí pole objektů |
|
|
|
# # Cislo už lexikograficky setřízené, viz models |
|
|
|
# body = 0 |
|
|
|
# for cislo in cisla: |
|
|
|
# if cislo.poradi == do_cisla.poradi: break |
|
|
|
# # druhá část zaručuje, že máme výsledky do daného čísla včetně |
|
|
|
# body = body + body_resitele_v_cisle(resitel, cislo) |
|
|
|
# return body |
|
|
|
|
|
|
|
# TODO: předělat na nový model |
|
|
|
#def vysledkovka_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" |
|
|
@ -612,19 +632,17 @@ class ProblemView(generic.DetailView): |
|
|
|
return context |
|
|
|
|
|
|
|
|
|
|
|
class VysledkyResitele(object): |
|
|
|
"""Pro daného řešitele ukládá počet bodů za jednotlivé úlohy a celkový |
|
|
|
počet bodů za konkrétní ročník do daného čísla a za dané číslo.""" |
|
|
|
class RadekVysledkovky(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, resitel, cislo, rocnik): |
|
|
|
def __init__(self, poradi, resitel, body_problemy_sezn, body_cislo, body_rocnik): |
|
|
|
self.resitel = resitel |
|
|
|
self.cislo = cislo |
|
|
|
self.body_cislo = body_resitele_v_cisle(resitel, cislo) |
|
|
|
self.body = [] |
|
|
|
self.rocnik = rocnik |
|
|
|
self.body_rocnik = body_resitele_v_rocniku(resitel, rocnik, cislo) |
|
|
|
self.body_celkem_odjakziva = resitel.vsechny_body() |
|
|
|
self.poradi = 0 |
|
|
|
self.body_cislo = body_cislo |
|
|
|
self.body_rocnik = body_rocnik |
|
|
|
# TODO self.body_celkem_odjakziva = odjakziva |
|
|
|
self.poradi = poradi |
|
|
|
self.body_problemy_sezn = body_problemy_sezn |
|
|
|
|
|
|
|
class CisloView(generic.DetailView): |
|
|
|
model = Cislo |
|
|
@ -648,38 +666,84 @@ class CisloView(generic.DetailView): |
|
|
|
def get_context_data(self, **kwargs): |
|
|
|
context = super(CisloView, self).get_context_data(**kwargs) |
|
|
|
|
|
|
|
## TODO upravit dle nového modelu |
|
|
|
cislo = context['cislo'] |
|
|
|
hlavni_problemy = hlavni_problemy_cisla(cislo) |
|
|
|
# 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ů) |
|
|
|
hlavni_problemy_slovnik = {} |
|
|
|
for hp in hlavni_problemy: |
|
|
|
hlavni_problemy_slovnik[str(hp.id)] = {} |
|
|
|
|
|
|
|
## 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 |
|
|
|
## chceme letos něco poslal |
|
|
|
# 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 = Resitel.objects.filter( |
|
|
|
rok_maturity__gte=cislo.rocnik.druhy_rok()) |
|
|
|
# TODO: zkusit hodnoceni__rocnik... |
|
|
|
#.filter(hodnoceni_set__rocnik__eq=cislo_rocnik) |
|
|
|
radky_vysledkovky = [] |
|
|
|
# zakládání prázdných záznamů pro řešitele |
|
|
|
cislobody = {} |
|
|
|
for ar in aktivni_resitele: |
|
|
|
# získáme výsledky řešitele - součty přes číslo a ročník |
|
|
|
vr = VysledkyResitele(ar, cislo, cislo.rocnik) |
|
|
|
# řešitele převedeme na řetězec pomocí unikátního id |
|
|
|
cislobody[str(ar.id)] = "" |
|
|
|
for hp in hlavni_problemy: |
|
|
|
vr.body.append( |
|
|
|
body_resitele_problemu_v_cisle(hp, ar, cislo)) |
|
|
|
radky_vysledkovky.append(vr) |
|
|
|
|
|
|
|
# setřídíme řádky výsledkovky/objekty VysledkyResitele podle bodů |
|
|
|
radky_vysledkovky.sort(key=lambda vr: vr.body_rocnik, reverse=True) |
|
|
|
|
|
|
|
# generujeme sloupec s pořadím pomocí stejně zvané funkce |
|
|
|
pocty_bodu = [rv.body_rocnik for rv in radky_vysledkovky] |
|
|
|
sloupec_poradi = sloupec_s_poradim(pocty_bodu) |
|
|
|
slovnik = hlavni_problemy_slovnik[str(hp.id)] |
|
|
|
slovnik[str(ar.id)] = "" |
|
|
|
|
|
|
|
# vezmeme všechna řešení s body do daného čísla |
|
|
|
reseni_do_cisla = Reseni.objects.filter(hodnoceni__cislo_body=cislo) |
|
|
|
|
|
|
|
# projdeme všechna řešení do čísla a přičteme body každému řešiteli do celkových |
|
|
|
# bodů i do bodů za problém |
|
|
|
for reseni in reseni_do_cisla: |
|
|
|
body = reseni.hodnoceni.body |
|
|
|
problem = reseni.problem |
|
|
|
nadproblem = hlavni_problem(problem) |
|
|
|
nadproblem_slovnik = hlavni_problemy_slovnik[str(nadproblem.id)] |
|
|
|
for resitel in reseni.resitele: |
|
|
|
# testujeme na None, pokud 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 |
|
|
|
if cislobody[str(resitel.id)] == "": |
|
|
|
cislobody[str(resitel.id)] = 0 |
|
|
|
cislobody[str(resitel.id)] += body |
|
|
|
|
|
|
|
if nadproblem_slovnik[str(resitel.id)] == "": |
|
|
|
nadproblem_slovnik[str(resitel.id)] = 0 |
|
|
|
nadproblem_slovnik[str(resitel.id)] += body |
|
|
|
|
|
|
|
# zeptáme se na dvojice (řešitel, body) za ročník a setřídíme sestupně |
|
|
|
resitel_rocnikbody_slov = body_resitelu_za_rocnik(cislo.rocnik, aktivni_resitele) |
|
|
|
resitel_rocnikbody_sezn = sorted(resitel_rocnikbody_slov.items(), |
|
|
|
key = lambda x: x[1], reverse = True) |
|
|
|
|
|
|
|
# řešitelé setřídění podle bodů za číslo sestupně |
|
|
|
setrizeni_resitele_id = [dvojice[0] for dvojice in resitel_rocnikbody_sezn] |
|
|
|
setrizeni_resitele = [Resitel.objects.get(id=i) for i in setrizeni_resitele_id] |
|
|
|
|
|
|
|
# vytvoříme jednotlivé sloupce výsledkovky |
|
|
|
radky_vysledkovky = [] |
|
|
|
rocnik_body = [] |
|
|
|
cislo_body = [] |
|
|
|
hlavni_problemy_body = [] |
|
|
|
for ar_id in setrizeni_resitele_id: |
|
|
|
# vytáhneme ze slovníků body pro daného řešitele |
|
|
|
rocnik_body.append(resitel_rocnikbody_slov[ar_id]) |
|
|
|
cislo_body.append(cislobody[ar_id]) |
|
|
|
problemy = [] |
|
|
|
for hp in hlavni_problemy: |
|
|
|
problemy.append(hlavni_problemy_slovnik[str(hp.id)][ar_id]) |
|
|
|
hlavni_problemy_body.append(problemy) |
|
|
|
# pořadí určíme pomocí funkce, které dáme celkové body za ročník vzestupně |
|
|
|
poradi = sloupec_s_poradim(rocnik_body) |
|
|
|
|
|
|
|
# každému řádku výsledkovky přidáme jeho pořadí |
|
|
|
i = 0 |
|
|
|
for rv in radky_vysledkovky: |
|
|
|
rv.poradi = sloupec_poradi[i] |
|
|
|
i = i + 1 |
|
|
|
radky_vysledkovky = [] |
|
|
|
for i in range(0, len(setrizeni_resitele_id)): |
|
|
|
radek = RadekVysledkovky(poradi[i], setrizeni_resitele[i], |
|
|
|
hlavni_problemy_body[i], cislo_body[i], rocnik_body[i]) |
|
|
|
radky_vysledkovky.append(radek) |
|
|
|
|
|
|
|
# vytahané informace předáváme do kontextu |
|
|
|
context['cislo'] = cislo |
|
|
@ -689,7 +753,6 @@ class CisloView(generic.DetailView): |
|
|
|
# context['resene_problemy'] = resene_problemy |
|
|
|
#XXX testovat |
|
|
|
#XXX opravit to, že se nezobrazují body za jednotlivé úlohy |
|
|
|
|
|
|
|
return context |
|
|
|
|
|
|
|
# problemy = sorted(set(r.problem for r in reseni), key=lambda x:(poradi_typu[x.typ], x.kod_v_rocniku())) |
|
|
|