From 64074d5dc6cbd82daebd3c6591d6e090cae88857 Mon Sep 17 00:00:00 2001 From: Anet Date: Thu, 19 Mar 2020 01:31:00 +0100 Subject: [PATCH] =?UTF-8?q?views:=20skoro=20funk=C4=8Dn=C3=AD=20v=C3=BDsle?= =?UTF-8?q?dkovka,=20probl=C3=A9my=20s=20body=20odjak=C5=BEiva,=20dotazy?= =?UTF-8?q?=20do=20datab=C3=A1ze=20u=C5=BE=20jinak=20rozumn=C4=9B=20rychl?= =?UTF-8?q?=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- seminar/views/views_all.py | 104 +++++++++++++++++++++++++++---------- 1 file changed, 78 insertions(+), 26 deletions(-) diff --git a/seminar/views/views_all.py b/seminar/views/views_all.py index 3065e037..3dcf1331 100644 --- a/seminar/views/views_all.py +++ b/seminar/views/views_all.py @@ -477,6 +477,35 @@ def hlavni_problemy_cisla(cislo): return hlavni_problemy +# 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 = {} @@ -485,11 +514,11 @@ def body_resitelu_za_rocnik(rocnik, 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) + 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(): - body_za_rocnik[str(resitel.id)] += hodn.body + pricti_body(body_za_rocnik, resitel, hodn.body) return body_za_rocnik #def body_resitele_odjakziva(resitel): @@ -635,13 +664,26 @@ 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, poradi, resitel, body_problemy_sezn, body_cislo, body_rocnik): + def __init__(self, poradi, resitel, body_problemy_sezn, + body_cislo, body_rocnik, body_odjakziva): self.resitel = resitel self.body_cislo = body_cislo self.body_rocnik = body_rocnik -# TODO self.body_celkem_odjakziva = odjakziva + 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 @@ -678,8 +720,8 @@ class CisloView(generic.DetailView): ## 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 = Resitel.objects.filter( - rok_maturity__gte=cislo.rocnik.druhy_rok()) + aktivni_resitele = list(Resitel.objects.filter( + rok_maturity__gte=cislo.rocnik.druhy_rok())) # TODO: zkusit hodnoceni__rocnik... #.filter(hodnoceni_set__rocnik__eq=cislo_rocnik) # zakládání prázdných záznamů pro řešitele @@ -692,66 +734,76 @@ class CisloView(generic.DetailView): 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) + reseni_do_cisla = Reseni.objects.prefetch_related('problem', 'hodnoceni', 'resitele').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 + + # ř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]) + 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['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()))