From 4d348ad9c763247615647d05be8857355dd63782 Mon Sep 17 00:00:00 2001 From: Jonas Havelka Date: Tue, 16 Feb 2021 22:42:05 +0100 Subject: [PATCH] =?UTF-8?q?Detailn=C3=AD=20v=C3=BDsledkovka=20(start)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- seminar/templates/seminar/archiv/cislo.html | 41 +++++- seminar/views/views_all.py | 145 ++++++++++++++++++-- 2 files changed, 170 insertions(+), 16 deletions(-) diff --git a/seminar/templates/seminar/archiv/cislo.html b/seminar/templates/seminar/archiv/cislo.html index d191da22..2e912dde 100644 --- a/seminar/templates/seminar/archiv/cislo.html +++ b/seminar/templates/seminar/archiv/cislo.html @@ -74,9 +74,24 @@ # Jméno {% for p in problemy %} - {{ p.kod_v_rocniku }} + {{ p.kod_v_rocniku }} + + {# TODELETE #} + {% for podproblemy in podproblemy_iter.next %} + {{ podproblemy.kod_v_rocniku }} + {% endfor %} + {# TODELETE #} + {% endfor %} {% if ostatni %}Ostatní {% endif %} + + {# TODELETE #} + {% for podproblemy in podproblemy_iter.next %} + {{ podproblemy.kod_v_rocniku }} + {% endfor %} + {# TODELETE #} + + Za číslo Za ročník Odjakživa @@ -90,6 +105,13 @@ {{ rv.resitel.osoba.plne_jmeno }} {% for b in rv.body_problemy_sezn %} {{ b }} + + {# TODELETE #} + {% for body_podproblemu in rv.body_podproblemy_iter.next %} + {{ body_podproblemu }} + {% endfor %} + {# TODELETE #} + {% endfor %} {{ rv.body_cislo }} {{ rv.body_rocnik }} @@ -97,6 +119,23 @@ {% endfor %} + + {# TODELETE #} + + {# TODELETE #} + {% endif %} {% if not cislo.verejna_vysledkovka and user.je_org %} diff --git a/seminar/views/views_all.py b/seminar/views/views_all.py index 24d31ecc..56183114 100644 --- a/seminar/views/views_all.py +++ b/seminar/views/views_all.py @@ -721,15 +721,24 @@ def hlavni_problemy_rocniku(rocnik, jen_verejne=True): return hlavni_problemy -def hlavni_problemy_cisla(cislo): - """ Vrátí seznam všech problémů s body v daném čísle, které již nemají nadproblém. """ - hodnoceni = cislo.hodnoceni.select_related('problem', 'reseni').all() + +def problemy_cisla(cislo): + """ Vrátí seznam všech problémů s body v daném čísle. """ + 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] - problemy_set = set(problemy) # chceme každý problém unikátně, - problemy = (list(problemy_set)) # převedení na množinu a zpět to zaručí + problemy_set = set(problemy) # chceme každý problém unikátně, + problemy = (list(problemy_set)) # převedení na množinu a zpět to zaručí + + return problemy + + +def hlavni_problemy_cisla(cislo, problemy=None): + """ Vrátí seznam všech problémů s body v daném čísle, které již nemají nadproblém. """ + if problemy is None: + problemy = problemy_cisla(cislo) # hlavní problémy čísla # (mají vlastní sloupeček ve výsledkovce, nemají nadproblém) @@ -744,6 +753,27 @@ def hlavni_problemy_cisla(cislo): return hlavni_problemy + +def podproblemy_v_cislu(cislo, problemy=None, hlavni_problemy=None): + """ Vrátí seznam všech problémů s body v daném čísle v poli 'indexovaném' tématy. """ + if problemy is None: + problemy = problemy_cisla(cislo) + if hlavni_problemy is None: + hlavni_problemy = hlavni_problemy_cisla(cislo, problemy) + + podproblemy = dict((hp.id, []) for hp in hlavni_problemy) + hlavni_problemy = set(hlavni_problemy) + podproblemy[-1] = [] + + for problem in problemy: + h_problem = hlavni_problem(problem) + if h_problem in hlavni_problemy: + podproblemy[h_problem.id].append(problem) + else: + podproblemy[-1].append(problem) + + return podproblemy + def body_resitelu(resitele, za, odjakziva=True): """ Funkce počítající počty bodů pro zadané řešitele, buď odjakživa do daného ročníku/čísla anebo za daný ročník/číslo. @@ -940,8 +970,8 @@ 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).""" - def __init__(self, poradi, resitel, body_problemy_sezn, - body_cislo, body_rocnik, body_odjakziva, rok): + def __init__(self, poradi, resitel, body_problemy_sezn, + body_cislo, body_rocnik, body_odjakziva, rok, body_podproblemy, body_podproblemy_iter): self.resitel = resitel self.rocnik_resitele = resitel.rocnik(rok) self.body_cislo = body_cislo @@ -950,7 +980,9 @@ class RadekVysledkovkyCisla(object): self.poradi = poradi self.body_problemy_sezn = body_problemy_sezn self.titul = resitel.get_titul(body_odjakziva) - + self.body_podproblemy = body_podproblemy + self.body_podproblemy_iter = body_podproblemy_iter # TODELETE + def pricti_body(slovnik, resitel, body): """ Přiřazuje danému řešiteli body do slovníku. """ @@ -1039,11 +1071,81 @@ def secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy=None): pricti_body(nadproblem_slovnik, resitel, body) return hlavni_problemy_slovnik, cislobody + +def secti_body_za_cislo_podle_temat(cislo, aktivni_resitele, podproblemy=None, temata=None): + """ Spočítá u řešitelů body za číslo za úlohy v jednotlivých hlavních problémech (témata).""" + if temata is None: + temata = hlavni_problemy_cisla(cislo) + + if podproblemy is None: + podproblemy_v_cislu(cislo, hlavni_problemy=temata) + + body_slovnik = {} + for tema in temata: + body_slovnik[tema.id] = {} + for problem in podproblemy[tema.id]: + body_slovnik[tema.id][problem.id] = {} + body_slovnik[-1] = {} + for problem in podproblemy[-1]: + body_slovnik[-1][problem.id] = {} + + # zakládání prázdných záznamů pro řešitele + for ar in aktivni_resitele: + for tema in temata: + for problem in podproblemy[tema.id]: + body_slovnik[tema.id][problem.id][ar.id] = "" + + for problem in podproblemy[-1]: + body_slovnik[-1][problem.id][ar.id] = "" + + temata = set(t.id for t in temata) + + # vezmeme všechna řešení s body do daného čísla + reseni_do_cisla = Reseni.objects.prefetch_related('problem', 'resitele', + 'hodnoceni_set').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: + + # řešení může řešit více problémů + for prob in list(reseni.problem.all()): + nadproblem = hlavni_problem(prob) + if nadproblem.id in temata: + nadproblem_slovnik = body_slovnik[nadproblem.id] + else: + nadproblem_slovnik = body_slovnik[-1] + + problem_slovnik = nadproblem_slovnik[prob.id] + + # a mít více hodnocení + for hodn in list(reseni.hodnoceni_set.all()): + body = hodn.body + + # a mít více řešitelů + for resitel in list(reseni.resitele.all()): + if resitel not in aktivni_resitele: + print("Skipping {}".format(resitel.id)) + continue + pricti_body(problem_slovnik, resitel, body) + return body_slovnik + + +# TODELETE +class FixedIterator: + def next(self): + return self.niter.__next__() + + def __init__(self, niter): + self.niter = niter +# TODELETE + + def vysledkovka_cisla(cislo, context=None): if context is None: context = {} - - hlavni_problemy = hlavni_problemy_cisla(cislo) + problemy = problemy_cisla(cislo) + hlavni_problemy = hlavni_problemy_cisla(cislo, problemy) ## 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 @@ -1075,6 +1177,10 @@ def vysledkovka_cisla(cislo, context=None): temata_a_spol = list(filter(ne_clanek_ne_konfera, hlavni_problemy)) + # získáme body u jednotlivých témat + podproblemy = podproblemy_v_cislu(cislo, problemy, temata_a_spol) + problemy_slovnik = secti_body_za_cislo_podle_temat(cislo, aktivni_resitele, podproblemy, temata_a_spol) + # def not_empty(value): # return value != '' # @@ -1084,20 +1190,26 @@ def vysledkovka_cisla(cislo, context=None): for ar_id in setrizeni_resitele_id: # získáme seznam bodů za problémy pro daného řešitele - problemy = [] + body_problemy = [] + body_podproblemy = [] for hp in temata_a_spol: - problemy.append(hlavni_problemy_slovnik[hp.id][ar_id]) + body_problemy.append(hlavni_problemy_slovnik[hp.id][ar_id]) + body_podproblemy.append([problemy_slovnik[hp.id][it.id][ar_id] for it in podproblemy[hp.id]]) if je_nejake_ostatni: - problemy.append(hlavni_problemy_slovnik[-1][ar_id]) + body_problemy.append(hlavni_problemy_slovnik[-1][ar_id]) + body_podproblemy.append([problemy_slovnik[-1][it.id][ar_id] for it in podproblemy[-1]]) # vytáhneme informace pro daného řešitele radek = RadekVysledkovkyCisla( poradi[i], # pořadí Resitel.objects.get(id=ar_id), # řešitel (z id) - problemy, # seznam bodů za hlavní problémy čísla + body_problemy, # seznam bodů za hlavní problémy čísla cislobody[ar_id], # body za číslo setrizeni_resitele_body[i], # body za ročník (spočítané výše s pořadím) resitel_odjakzivabody_slov[ar_id], # body odjakživa - cislo.rocnik) # ročník semináře pro zjištění ročníku řešitele + cislo.rocnik, + body_podproblemy, # body všech podproblémů + FixedIterator(body_podproblemy.__iter__()) # TODELETE + ) # ročník semináře pro zjištění ročníku řešitele radky_vysledkovky.append(radek) i += 1 @@ -1106,6 +1218,9 @@ def vysledkovka_cisla(cislo, context=None): context['radky_vysledkovky'] = radky_vysledkovky context['problemy'] = temata_a_spol context['ostatni'] = je_nejake_ostatni + pt = [podproblemy[it.id] for it in temata_a_spol]+[podproblemy[-1]] + context['podproblemy'] = pt + context['podproblemy_iter'] = FixedIterator(pt.__iter__()) # TODELETE #context['v_cisle_zadane'] = TODO #context['resene_problemy'] = resene_problemy return context