diff --git a/seminar/admin.py b/seminar/admin.py index 3008b3bd..a40a31de 100644 --- a/seminar/admin.py +++ b/seminar/admin.py @@ -7,8 +7,6 @@ from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModel from solo.admin import SingletonModelAdmin from django.utils.safestring import mark_safe -from seminar.utils import hlavni_problem - # Todo: reversion import seminar.models as m @@ -99,7 +97,7 @@ class CisloAdmin(admin.ModelAdmin): ch.stav = m.Problem.STAV_ZADANY ch.save() - hp = hlavni_problem(ch) + hp = ch.hlavni_problem if hp.stav not in (m.Problem.STAV_ZADANY, m.Problem.STAV_VYRESENY): hp.stav = m.Problem.STAV_ZADANY hp.save() diff --git a/seminar/models/tvorba.py b/seminar/models/tvorba.py index 5d35c2ae..9178c511 100644 --- a/seminar/models/tvorba.py +++ b/seminar/models/tvorba.py @@ -24,7 +24,6 @@ from taggit.managers import TaggableManager from reversion import revisions as reversion from seminar.utils import roman -from seminar.utils import hlavni_problem from treenode import treelib from unidecode import unidecode # Používám pro získání ID odkazu (ještě je to někde po někom zakomentované) @@ -98,7 +97,7 @@ class Rocnik(SeminarModelBase): return vc[-1] if vc else None def verejne_vysledkovky_cisla(self): - vc = list(self.cisla.filter(verejna_vysledkovka=True)) + vc = list(self.cisla.filter(deadline_v_cisle__verejna_vysledkovka=True)) vc.sort(key=lambda c: c.poradi) return vc @@ -483,7 +482,10 @@ class Problem(SeminarModelBase,PolymorphicModel): @cached_property def hlavni_problem(self): """ Pro daný problém vrátí jeho nejvyšší nadproblém.""" - return hlavni_problem(self) + problem = self + while not (problem.nadproblem is None): + problem = problem.nadproblem + return problem # FIXME - k úloze def body_v_zavorce(self): diff --git a/seminar/utils.py b/seminar/utils.py index f4a598eb..806b1050 100644 --- a/seminar/utils.py +++ b/seminar/utils.py @@ -248,77 +248,6 @@ def viewMethodSwitch(get, post): return NewView.as_view() -def cisla_rocniku(rocnik, jen_verejne=True): - """ - Vrátí všechna čísla daného ročníku. - Parametry: - rocnik (Rocnik): ročník semináře - jen_verejne (bool): zda se mají vrátit jen veřejná, nebo všechna čísla - Vrátí: - seznam objektů typu Cislo - """ - if jen_verejne: - return rocnik.verejne_vysledkovky_cisla() - else: - return rocnik.cisla.all().order_by('poradi') - -def hlavni_problem(problem): - """ Pro daný problém vrátí jeho nejvyšší nadproblém.""" - while not(problem.nadproblem == None): - problem = problem.nadproblem - return problem - -def problemy_rocniku(rocnik, jen_verejne=True): - return m.Problem.objects.filter(hodnoceni__in = m.Hodnoceni.objects.filter(deadline_body__cislo__in = cisla_rocniku(rocnik, jen_verejne))).distinct().select_related('nadproblem').select_related('nadproblem__nadproblem') - -def problemy_cisla(cislo): - """ Vrátí seznam všech problémů s body v daném čísle. """ - return m.Problem.objects.filter(hodnoceni__in = m.Hodnoceni.objects.filter(deadline_body__cislo = cislo)).distinct().non_polymorphic().select_related('nadproblem').select_related('nadproblem__nadproblem') - - -def hlavni_problemy_f(problemy=None): - """ Vrátí seznam všech problémů, které již nemají nadproblém. """ - # hlavní problémy čísla - # (mají vlastní sloupeček ve výsledkovce, nemají nadproblém) - hlavni_problemy = set() - for p in problemy: - hlavni_problemy.add(hlavni_problem(p)) - - # zunikátnění - hlavni_problemy = list(hlavni_problemy) - hlavni_problemy.sort(key=lambda k: k.kod_v_rocniku) # setřídit podle t1, t2, c3, ... - - 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_f(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) - - for podproblem in podproblemy.keys(): - def int_or_zero(p): - try: - return int(p.kod) - except ValueError: - return 0 - - podproblemy[podproblem] = sorted(podproblemy[podproblem], key=int_or_zero) - - return podproblemy class TypDeadline(Enum): PredDeadline = auto() diff --git a/vysledkovky/utils.py b/vysledkovky/utils.py index b0f34254..9fead9c2 100644 --- a/vysledkovky/utils.py +++ b/vysledkovky/utils.py @@ -3,8 +3,7 @@ from functools import cached_property import seminar.models as m from django.db.models import Q, Sum -from seminar.utils import resi_v_rocniku, cisla_rocniku,\ - hlavni_problemy_f, problemy_cisla, podproblemy_v_cislu +from seminar.utils import resi_v_rocniku ROCNIK_ZRUSENI_TEMAT = 25 @@ -154,7 +153,11 @@ class VysledkovkaRocniku(Vysledkovka): @cached_property def cisla_rocniku(self) -> list[m.Cislo]: - return cisla_rocniku(self.rocnik, self.jen_verejne) + """ Vrátí všechna čísla daného ročníku. """ + if self.jen_verejne: + return self.rocnik.verejne_vysledkovky_cisla() + else: + return self.rocnik.cisla.all().order_by('poradi') @cached_property def body_za_cisla_slovnik(self) -> dict[int, dict[int, int]]: @@ -239,11 +242,26 @@ class VysledkovkaCisla(Vysledkovka): @cached_property def problemy(self) -> list[m.Problem]: - return problemy_cisla(self.cislo) + """ Vrátí seznam všech problémů s body v daném čísle. """ + return m.Problem.objects.filter( + hodnoceni__in=m.Hodnoceni.objects.filter(deadline_body__cislo=self.cislo) + ).distinct().non_polymorphic().select_related('nadproblem').select_related('nadproblem__nadproblem') @cached_property def hlavni_problemy(self) -> list[m.Problem]: - return hlavni_problemy_f(self.problemy) + """ Vrátí seznam všech problémů, které již nemají nadproblém. """ + # hlavní problémy čísla + # (mají vlastní sloupeček ve výsledkovce, nemají nadproblém) + hlavni_problemy = set() + for p in self.problemy: + hlavni_problemy.add(p.hlavni_problem) + + # zunikátnění + hlavni_problemy = list(hlavni_problemy) + hlavni_problemy.sort( + key=lambda k: k.kod_v_rocniku) # setřídit podle t1, t2, c3, ... + + return hlavni_problemy # Není cached, protože si myslím, že queryset lze použít ve for jen jednou. @property @@ -337,7 +355,26 @@ class VysledkovkaCisla(Vysledkovka): @cached_property def podproblemy(self) -> list[list[m.Problem]]: - return podproblemy_v_cislu(self.cislo, self.problemy, self.temata_a_spol) + podproblemy = {hp.id: [] for hp in self.hlavni_problemy} + hlavni_problemy = set(self.hlavni_problemy) + podproblemy[-1] = [] + + for problem in self.problemy: + h_problem = problem.hlavni_problem + if h_problem in hlavni_problemy: + podproblemy[h_problem.id].append(problem) + else: + podproblemy[-1].append(problem) + + for podproblem in podproblemy.keys(): + def int_or_zero(p): + try: + return int(p.kod) + except ValueError: + return 0 + + podproblemy[podproblem] = sorted(podproblemy[podproblem], key=int_or_zero) + return podproblemy @cached_property def podproblemy_seznam(self) -> list[list[m.Problem]]: