diff --git a/seminar/templates/seminar/archiv/cislo.html b/seminar/templates/seminar/archiv/cislo.html
index d8b030c8..63788e06 100644
--- a/seminar/templates/seminar/archiv/cislo.html
+++ b/seminar/templates/seminar/archiv/cislo.html
@@ -67,21 +67,21 @@
{% endfor %}
Za číslo
| Za ročník
- | Odjakživa
- {% for rv in vysledkovka %}
+ {# | Odjakživa#}
+ {% for rv in radky_vysledkovky %}
|
{% autoescape off %}{{ rv.poradi }}{% endautoescape %}
|
- {% if rv.titul %}
- {{ rv.titul }}MM
+ {% if rv.resitel.get_titul != "" %}
+ {{ rv.resitel.get_titul }}MM
{% endif %}
- {{ rv.resitel.plne_jmeno }}
- {% for b in rv.body_ulohy %}
+ {{ rv.resitel.osoba.plne_jmeno }}
+ {% for b in rv.hlavni_problemy_body %}
| {{ b }}
{% endfor %}
| {{ rv.body_cislo }}
- | {{ rv.body_celkem_rocnik }}
- | {{ rv.body_celkem_odjakziva }}
+ | {{ rv.body_rocnik }}
+ {# | {{ rv.body_celkem_odjakziva }}#}
|
{% endfor %}
diff --git a/seminar/urls.py b/seminar/urls.py
index 4ec060ce..48a4b754 100644
--- a/seminar/urls.py
+++ b/seminar/urls.py
@@ -23,7 +23,7 @@ urlpatterns = [
path('archiv/temata/', views.ArchivTemataView.as_view()),
path('rocnik//', views.RocnikView.as_view(), name='seminar_rocnik'),
- #path('cislo/./', views.CisloView.as_view(), name='seminar_cislo'),
+ path('cislo/./', views.CisloView.as_view(), name='seminar_cislo'),
path('problem//', views.ProblemView.as_view(), name='seminar_problem'),
path('treenode//', views.TreeNodeView.as_view(), name='seminar_treenode'),
#path('problem/(?P\d+)/(?P\d+)/', views.PrispevekView.as_view(), name='seminar_problem_prispevek'),
diff --git a/seminar/views/views_all.py b/seminar/views/views_all.py
index 40357769..945d283e 100644
--- a/seminar/views/views_all.py
+++ b/seminar/views/views_all.py
@@ -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 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, 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()))