diff --git a/seminar/templates/seminar/archiv/rocnik.html b/seminar/templates/seminar/archiv/rocnik.html
index 64c4029d..c047a5b1 100644
--- a/seminar/templates/seminar/archiv/rocnik.html
+++ b/seminar/templates/seminar/archiv/rocnik.html
@@ -42,7 +42,7 @@
{% if user.is_staff and vysledkovka_s_neverejnymi %}
{% autoescape off %}{{ rv.poradi }}{% endautoescape %}
|
{% if rv.titul %}
{{ rv.titul }}MM
{% endif %}
- {{ rv.resitel.plne_jmeno }}
+ {{ rv.resitel.osoba.plne_jmeno }}
| {{ rv.resitel.rocnik }}
- | {{ rv.body_odjakziva }}
- {% for b in rv.body_cisla %}
+ | {{ rv.body_celkem_odjakziva }}
+ {% for b in rv.body_cisla_sezn %}
| {{ b }}
{% endfor %}
| {{ rv.body_rocnik }}
diff --git a/seminar/views/views_all.py b/seminar/views/views_all.py
index 01546843..771c204c 100644
--- a/seminar/views/views_all.py
+++ b/seminar/views/views_all.py
@@ -388,13 +388,17 @@ class ArchivView(generic.ListView):
### Výsledky
-# ze setřízeného(!) 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):
+# ze seznamu obsahujícího sestupně setřízené body řešitelů za daný ročník
+# vytvoří seznam s pořadími (včetně 3.-5. a pak 2 volná místa atp.),
+# podle toho, jak jdou za sebou ve výsledkovce
+def sloupec_s_poradim(setrizene_body):
+
+ # ze seznamu obsahujícího setřízené body spočítáme sloupec s pořadím
aktualni_poradi = 1
sloupec_s_poradim = []
# seskupíme seznam všech bodů podle hodnot
- for index in range(0, len(seznam_s_body)):
+ for index in range(0, len(setrizene_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:
@@ -402,10 +406,10 @@ def sloupec_s_poradim(seznam_s_body):
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]:
+ while setrizene_body[index] == setrizene_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:
+ if (index + velikost_skupiny) > len(setrizene_body) - 1:
break
# pokud je velikost skupiny 1, vypíšu pořadí
if velikost_skupiny == 1:
@@ -418,28 +422,12 @@ 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 = 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)
+# vrátí všechna čísla daného ročníku
+def cisla_rocniku(rocnik, jen_verejne=True):
+ if jen_verejne:
+ return rocnik.verejna_cisla()
+ else:
+ return rocnik.cisla.all()
# pro daný problém vrátí jeho nejvyšší nadproblém
def hlavni_problem(problem):
@@ -447,6 +435,17 @@ def hlavni_problem(problem):
problem = problem.nadproblem
return problem
+def hlavni_problemy_rocniku(rocnik, jen_verejne=True):
+ hlavni_problemy = []
+ for cislo in cisla_rocniku(rocnik, jen_verejne):
+ for problem in hlavni_problemy_cisla(cislo):
+ hlavni_problemy.append(problem)
+ 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 pořadí
+
+ return hlavni_problemy
+
# 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()
@@ -476,27 +475,32 @@ def body_resitelu_odjakziva(rocnik, resitele):
for r in resitele:
body_odjakziva[str(r.id)] = 0
-# POZOR! Aktuálně počítá jen za posledních 10 let od zadaného ročníku
-# # 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_set').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_set.all():
- pricti_body(body_odjakziva, r, hodn.body)
+#########################################################################
+# POZOR! Aktuálně počítá jen za posledních 10 let od zadaného ročníku #
+#########################################################################
+ # Body za posledních 10 let je dobrá aproximace pro naše potřeby (výsledkovka
+ # s aktivními řešiteli)
+
+ body_pred_roky = []
+ rok = rocnik.prvni_rok
+ rocniky = Rocnik.objects.filter(prvni_rok__gt=rok-11)
+ for roc in rocniky:
+ body_pred_roky.append(body_resitelu_za_rocnik(roc, 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é:
+# (důsledek toho, že dotazy na joinování databázových tabulek jsou kvadratické)
+# for res in Reseni.objects.prefetch_related('resitele', 'hodnoceni_set').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_set.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
@@ -514,13 +518,77 @@ def body_resitelu_za_rocnik(rocnik, aktivni_resitele):
pricti_body(body_za_rocnik, resitel, hodn.body)
return body_za_rocnik
-# 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"
-# """
-#
-# #vyberu vsechny vysledky z rocniku
+class RadekVysledkovkyRocniku(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, poradi, resitel, body_cisla_sezn, body_rocnik, body_odjakziva):
+ self.poradi = poradi
+ self.resitel = resitel
+ self.body_rocnik = body_rocnik
+ self.body_celkem_odjakziva = body_odjakziva
+ self.body_cisla_sezn = body_cisla_sezn
+ self.titul = resitel.get_titul(body_odjakziva)
+
+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"
+ """
+
+ ## TODO možná chytřeji vybírat aktivní řešitele
+ # 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=rocnik.druhy_rok()))
+ # TODO: zkusit hodnoceni__rocnik...
+ #.filter(hodnoceni_set__rocnik__eq=cislo_rocnik)
+ cisla = cisla_rocniku(rocnik, jen_verejne)
+ body_cisla_slov = {}
+ print("Jen veřejná: {}, čísla: {}".format(jen_verejne, cisla))
+ for cislo in cisla:
+ # získáme body za číslo
+ _, cislobody = secti_body_za_cislo(cislo, aktivni_resitele)
+ body_cisla_slov[str(cislo.id)] = cislobody
+
+ # získáme body za ročník, seznam obsahuje dvojice (řešitel_id, body) setřízené sestupně
+ resitel_rocnikbody_sezn = secti_body_za_rocnik(rocnik, aktivni_resitele)
+
+ # setřídíme řešitele podle počtu bodů a získáme seznam s body od nejvyšších po nenižší
+ setrizeni_resitele_id = [dvojice[0] for dvojice in resitel_rocnikbody_sezn]
+ setrizeni_resitele = [Resitel.objects.get(id=i) for i in setrizeni_resitele_id]
+ setrizene_body = [dvojice[1] for dvojice in resitel_rocnikbody_sezn]
+ poradi = sloupec_s_poradim(setrizene_body)
+
+ # získáme body odjakživa
+ resitel_odjakzivabody_slov = body_resitelu_odjakziva(rocnik, aktivni_resitele)
+
+ # vytvoříme jednotlivé sloupce výsledkovky
+ radky_vysledkovky = []
+ i = 0
+ for ar_id in setrizeni_resitele_id:
+ # seznam počtu bodů daného řešitele pro jednotlivá čísla
+ body_cisla_sezn = []
+ for cislo in cisla:
+ body_cisla_sezn.append(body_cisla_slov[str(cislo.id)][str(ar_id)])
+
+ # vytáhneme informace pro daného řešitele
+ radek = RadekVysledkovkyRocniku(
+ poradi[i], # pořadí
+ Resitel.objects.get(id=ar_id), # řešitel (z id)
+ body_cisla_sezn, # seznam bodů za čísla
+ setrizene_body[i], # body za ročník (spočítané výše s pořadím)
+ resitel_odjakzivabody_slov[ar_id]) # body odjakživa
+ print("{}: číslobody - {}, ročníkbody - {},"
+ "odjakživabody - {}".format(radek.resitel, radek.body_cisla_sezn,
+ radek.body_rocnik, radek.body_celkem_odjakziva))
+ radky_vysledkovky.append(radek)
+ print("Přikládám {}-tý řádek.".format(i))
+ i += 1
+
+ return radky_vysledkovky
+
+
+ #vyberu vsechny vysledky z rocniku
# cisla_v_rocniku = VysledkyKCisluZaRocnik.objects.filter(cislo__rocnik=rocnik).order_by('cislo')
# if jen_verejne:
# cisla_v_rocniku = cisla_v_rocniku.filter(cislo__verejna_vysledkovka=True)
@@ -594,10 +662,15 @@ class RocnikView(generic.DetailView):
def get_context_data(self, **kwargs):
context = super(RocnikView, self).get_context_data(**kwargs)
- #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"])
- # FIXME: opravit vylistování témat v ročníku
+ # vysledkovka = True zajistí vykreslení,
+ # zkontrolovat, kdy se má a nemá vykreslovat
+ context['vysledkovka'] = True
+ context['cisla_s_neverejnymi'] = cisla_rocniku(context["rocnik"], jen_verejne=False)
+ context['cisla'] = cisla_rocniku(context["rocnik"])
+ context['radky_vysledkovky'] = vysledkovka_rocniku(context["rocnik"])
+ context['radky_vysledkovky_s_neverejnymi'] = vysledkovka_rocniku(context["rocnik"], jen_verejne=False)
+ context['hlavni_problemy_v_rocniku'] = hlavni_problemy_rocniku(context["rocnik"])
+ context['hlavni_problemy_v_rocniku_s_neverejnymi'] = hlavni_problemy_rocniku(context["rocnik"], jen_verejne=False)
return context
@@ -621,7 +694,7 @@ class ProblemView(generic.DetailView):
return context
-class RadekVysledkovky(object):
+class RadekVysledkovkyCisla(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)."""
@@ -647,19 +720,22 @@ def pricti_body(slovnik, resitel, body):
slovnik[str(resitel.id)] += body
-def secti_body_za_rocnik(cislo, aktivni_resitele):
+def secti_body_za_rocnik(rocnik, aktivni_resitele):
# spočítáme všem řešitelům jejich body za ročník
- resitel_rocnikbody_slov = body_resitelu_za_rocnik(cislo.rocnik, aktivni_resitele)
+ resitel_rocnikbody_slov = body_resitelu_za_rocnik(rocnik, aktivni_resitele)
# zeptáme se na dvojice (řešitel, body) za ročník a setřídíme sestupně
resitel_rocnikbody_sezn = sorted(resitel_rocnikbody_slov.items(),
key = lambda x: x[1], reverse = True)
return resitel_rocnikbody_sezn
# spočítá u řešitelů body za číslo a za jednotlivé hlavní problémy (témata)
-def secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy):
+def secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy=None):
# 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ů)
+ if hlavni_problemy is None:
+ hlavni_problemy = hlavni_problemy_cisla(cislo)
+
hlavni_problemy_slovnik = {}
for hp in hlavni_problemy:
hlavni_problemy_slovnik[str(hp.id)] = {}
@@ -697,12 +773,11 @@ def secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy):
return hlavni_problemy_slovnik, cislobody
-def spocti_vysledkovku_cisla(cislo, context=None):
+def vysledkovka_cisla(cislo, context=None):
if context is None:
context = {}
hlavni_problemy = hlavni_problemy_cisla(cislo)
- ## 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
# 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
@@ -715,10 +790,10 @@ def spocti_vysledkovku_cisla(cislo, context=None):
hlavni_problemy_slovnik, cislobody = secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy)
# získáme body za ročník, seznam obsahuje dvojice (řešitel_id, body) setřízené sestupně
- resitel_rocnikbody_sezn = secti_body_za_rocnik(cislo, aktivni_resitele)
+ resitel_rocnikbody_sezn = secti_body_za_rocnik(cislo.rocnik, aktivni_resitele)
# získáme body odjakživa
- resitel_odjakzivabody_slov = body_resitelu_odjakziva(cislo.rocnik.druhy_rok(),
+ resitel_odjakzivabody_slov = body_resitelu_odjakziva(cislo.rocnik,
aktivni_resitele)
# řešitelé setřídění podle bodů za číslo sestupně
@@ -738,7 +813,7 @@ def spocti_vysledkovku_cisla(cislo, context=None):
for hp in hlavni_problemy:
problemy.append(hlavni_problemy_slovnik[str(hp.id)][ar_id])
# vytáhneme informace pro daného řešitele
- radek = RadekVysledkovky(
+ radek = RadekVysledkovkyCisla(
poradi[i], # pořadí
Resitel.objects.get(id=ar_id), # řešitel (z id)
problemy, # seznam bodů za hlavní problémy čísla
@@ -785,7 +860,7 @@ class CisloView(generic.DetailView):
cislo = context['cislo']
# vrátíme context (aktuálně obsahuje jen věci ohledně výsledkovky
- return spocti_vysledkovku_cisla(cislo, context)
+ return vysledkovka_cisla(cislo, context)
# 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
@@ -844,13 +919,13 @@ class ArchivTemataView(generic.ListView):
# content_type = 'text/plain; charset=UTF8'
# #vypise na stranku textovy obsah vyTeXane vysledkovky k okopirovani
#
-#class RocnikVysledkovkaView(RocnikView):
-# model = Rocnik
-# template_name = 'seminar/archiv/rocnik_vysledkovka.tex'
-# #content_type = 'application/x-tex; charset=UTF8'
-# #umozni rovnou stahnout TeXovsky dokument
-# content_type = 'text/plain; charset=UTF8'
-# #vypise na stranku textovy obsah vyTeXane vysledkovky k okopirovani
+class RocnikVysledkovkaView(RocnikView):
+ model = Rocnik
+ template_name = 'seminar/archiv/rocnik_vysledkovka.tex'
+ #content_type = 'application/x-tex; charset=UTF8'
+ #umozni rovnou stahnout TeXovsky dokument
+ content_type = 'text/plain; charset=UTF8'
+ #vypise na stranku textovy obsah vyTeXane vysledkovky k okopirovani
### Generovani obalek
class CisloObalkyStruct:
|