@ -404,31 +404,39 @@ 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 = problem . hodnoceni_set . filter ( reseni__resitele = resitel ,
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 reseni_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 ) :
hodnoceni = cislo . hodnoceni . select_related ( ' problem ' , ' reseni ' ) . all ( ) # hodnocení, která se vážou k danému číslu
hodnoceni = cislo . hodnoceni . select_related ( ' problem ' , ' reseni ' ) . all ( )
# hodnocení, která se vážou k danému číslu
reseni = [ h . reseni for h in hodnoceni ]
problemy = [ h . problem for h in hodnoceni ]
@ -439,9 +447,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 )
@ -450,38 +456,83 @@ 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
# POZOR! Aktuálně počítá jen za posledních 10 let od zadaného ročníku
def body_resitelu_odjakziva ( rocnik , resitele ) :
body_odjakziva = { }
for r in resitele :
body_odjakziva [ str ( r . id ) ] = 0
# # Body za posledních 10 let je dobrá aproximace pro naše potřeby (výsledkovka
# # s aktivními řešiteli)
#
# body_pred_roky = []
# for i in range(0, 10):
# body_pred_roky.append(body_resitelu_za_rocnik(rocnik-i, resitele))
#
# for r in resitele:
# for i in range(0,10):
# body_odjakziva[str(r.id)] += body_pred_roky[i][str(r.id)]
# Nasledující řešení je sice správné, ale moc pomalé:
for res in Reseni . objects . prefetch_related ( ' resitele ' , ' hodnoceni ' ) . all ( ) :
for r in res . resitele . all ( ) :
# daný řešitel nemusí být v naší podmnožině
if r not in resitele : continue
for hodn in res . hodnoceni . all ( ) :
pricti_body ( body_odjakziva , r , hodn . body )
return body_odjakziva
# 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 . prefetch_related ( ' resitele ' , ' hodnoceni ' ) . filter ( hodnoceni__cislo_body__rocnik = rocnik )
for res in reseni :
for resitel in res . resitele . all ( ) :
for hodn in res . hodnoceni . all ( ) :
pricti_body ( body_za_rocnik , resitel , 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"
@ -563,7 +614,8 @@ class RocnikView(generic.DetailView):
#context['vysledkovka'] = vysledkovka_rocniku(context["rocnik"])
#context['vysledkovka_s_neverejnymi'] = vysledkovka_rocniku(context["rocnik"], jen_verejne=False)
context [ ' temata_v_rocniku ' ] = verejna_temata ( context [ " rocnik " ] )
#context['temata_v_rocniku'] = verejna_temata(context["rocnik"])
# FIXME: opravit vylistování témat v ročníku
return context
@ -587,19 +639,30 @@ 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 Radek Vysledkov ky( 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 , body_odjakziva ) :
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
self . body_celkem_odjakziva = body_odjakziva
self . poradi = poradi
self . body_problemy_sezn = body_problemy_sezn
# přiřazuje danému řešiteli body do slovníku
def pricti_body ( slovnik , resitel , body ) :
# 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
if slovnik [ str ( resitel . id ) ] == " " :
slovnik [ str ( resitel . id ) ] = 0
slovnik [ str ( resitel . id ) ] + = body
class CisloView ( generic . DetailView ) :
model = Cislo
@ -623,48 +686,103 @@ 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
aktivni_resitele = Resitel . objects . filter (
rok_maturity__gte = cislo . rocnik . druhy_rok ( ) )
# 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 ( 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 . prefetch_related ( ' problem ' , ' hodnoceni ' , ' resitele ' ) . filter ( hodnoceni__cislo_body = cislo )
# 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
# 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 :
# řešení může řešit více problémů
for prob in list ( reseni . problem . all ( ) ) :
nadproblem = hlavni_problem ( prob )
nadproblem_slovnik = hlavni_problemy_slovnik [ str ( nadproblem . id ) ]
# a více hodnocení
for hodn in list ( reseni . hodnoceni . all ( ) ) :
body = hodn . body
# a více řešitelů
for resitel in list ( reseni . resitele . all ( ) ) :
pricti_body ( cislobody , resitel , body )
pricti_body ( nadproblem_slovnik , resitel , 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 )
# získáme body odjakživa
resitel_odjakzivabody_slov = body_resitelu_odjakziva ( cislo . rocnik . druhy_rok ( ) ,
aktivni_resitele )
# ř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 = [ ]
odjakziva_body = [ ]
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
odjakziva_body . append ( resitel_odjakzivabody_slov [ ar_id ] )
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 )
print ( " {} : body za problémy - {} , číslobody - {} , ročníkbody - {} , odjakživabody - " . format ( ar_id , problemy , cislobody [ ar_id ] , resitel_rocnikbody_slov [ ar_id ] ) )
# pořadí určíme pomocí funkce, které dáme celkové body za ročník vzestupně
poradi = sloupec_s_poradim ( rocnik_body )
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 ] ,
odjakziva_body [ i ] )
radky_vysledkovky . append ( radek )
print ( " Přikládám {} -tý řádek. " . format ( i ) )
print ( " Následuje předávání do kontextu. " )
# vytahané informace předáváme do kontextu
context [ ' cislo ' ] = cislo
context [ ' radky_vysledkovky ' ] = radky_vysledkovky
context [ ' radky_vysledkovky ' ] = radky_vysledkovky
context [ ' problemy ' ] = hlavni_problemy
# context['v_cisle_zadane'] = TODO
# context['resene_problemy'] = resene_problemy
#XXX testovat
#XXX opravit to, že se nezobrazují body za jednotlivé úlohy
#XXX nefungují body odjakživa - asi typový problém
#XXX nefungují tituly - možná korelace s výše uvedeným problémem
print ( " Předávám kontext. " )
return context
# problemy = sorted(set(r.problem for r in reseni), key=lambda x:(poradi_typu[x.typ], x.kod_v_rocniku()))