diff --git a/seminar/templates/seminar/odevzdavatko/tabulka.html b/seminar/templates/seminar/odevzdavatko/tabulka.html index 893efa6d..ac628be6 100644 --- a/seminar/templates/seminar/odevzdavatko/tabulka.html +++ b/seminar/templates/seminar/odevzdavatko/tabulka.html @@ -9,11 +9,15 @@ {{ p }} {% endfor %} - {% for resitel, vysledky in radky %} + {% for resitel,hodnoty in radky%} - {{ resitel } - {% for vysl in vysledky %} - {{ vysl.pocet_reseni }} řešení, dohromady za {{ vysl.body }}, nejnovější z {{ vysl.posledni_odevzdani }} + {{ resitel }} + {% for hodn in hodnoty %} + + {% if hodn %} + {{ hodn.pocet_reseni }} řešení
{{ hodn.body }} bodů
{{ hodn.posledni_odevzdani }} + {% endif %} + {% endfor %} {% endfor %} diff --git a/seminar/views/odevzdavatko.py b/seminar/views/odevzdavatko.py index 3f715bee..318b7bae 100644 --- a/seminar/views/odevzdavatko.py +++ b/seminar/views/odevzdavatko.py @@ -26,49 +26,50 @@ class SouhrnReseni: body : float -class TabulkaOdevzdanychReseniView(TemplateView): +class TabulkaOdevzdanychReseniView(ListView): template_name = 'seminar/odevzdavatko/tabulka.html' + model = m.Hodnoceni + akt_rocnik = m.Nastaveni.get_solo().aktualni_rocnik # .get_solo() vrátí tu jedinou instanci, asi... + resitele = resi_v_rocniku(akt_rocnik) + # NOTE: Protože řešení odkazuje přímo na Problém a QuerySet na Hodnocení je nepolymorfní, musíme porovnávat taky s nepolymorfními Problémy. + zadane_problemy = m.Problem.objects.filter(stav=m.Problem.STAV_ZADANY).non_polymorphic() + + def get_queryset(self): + qs = super().get_queryset() + qs = qs.filter(problem__in=self.zadane_problemy).select_related('reseni', 'problem').prefetch_related('reseni__resitele__osoba') + return qs def get_context_data(self, *args, **kwargs): - akt_rocnik = m.Nastaveni.get_solo().aktualni_rocnik # .get_solo() vrátí tu jedinou instanci, asi... - resitele = resi_v_rocniku(akt_rocnik) - zadane_problemy = m.Problem.objects.filter(stav=m.Problem.STAV_ZADANY) - - ctx = dict() - ctx['problemy'] = zadane_problemy - ctx['resitele'] = resitele + ctx = super().get_context_data(*args, **kwargs) + ctx['problemy'] = self.zadane_problemy + ctx['resitele'] = self.resitele + tabulka = dict() + + def pridej_reseni(problem, resitel, body, cas): + if problem not in tabulka: + tabulka[problem] = dict() + if resitel not in tabulka[problem]: + tabulka[problem][resitel] = SouhrnReseni(pocet_reseni=1, posledni_odevzdani=cas, body=body) + else: + tabulka[problem][resitel].posledni_odevzdani = max(tabulka[problem][resitel].posledni_odevzdani, cas) + tabulka[problem][resitel].body = max(tabulka[problem][resitel].body, body) + tabulka[problem][resitel].pocet_reseni += 1 - # Zkonstruujeme jednotlivé řádky - # Řádky budou indexované řešiteli a budou obsahovat SouhrnyReseni - # TODO: Tohle se asi nějak dá urychlit / zpřehlednit... - ctx['radky'] = dict() - for resitel in resitele: - ctx['radky'][resitel] = [] - for problem in zadane_problemy: - reseni_k_tomuto_problemu = m.Reseni.objects.filter( - resitele__in=[resitel], # Snad funguje i takhle - hodnoceni__problem__in=[problem], # ditto - ).order_by('-cas_doruceni') - pocet_reseni = reseni_k_tomuto_problemu.count() - if pocet_reseni > 0: - nejnovejsi = reseni_k_tomuto_problemu.first().cas_doruceni - pocet_bodu = max( - [h.body for h in m.Hodnoceni.objects.filter( - reseni__in=reseni_k_tomuto_problemu, - problem=problem, - ) - ] - ) + for hodnoceni in self.get_queryset(): + for resitel in hodnoceni.reseni.resitele.all(): + pridej_reseni(hodnoceni.problem, resitel, hodnoceni.body, hodnoceni.reseni.cas_doruceni) + + hodnoty = [] + for resitel in self.resitele: + resiteluv_radek = [] + for problem in self.zadane_problemy: + if problem in tabulka and resitel in tabulka[problem]: + resiteluv_radek.append(tabulka[problem][resitel]) else: - nejnovejsi = None - pocet_bodu = None - ctx['radky'][resitel].append( - SouhrnReseni( - pocet_reseni=pocet_reseni, - posledni_odevzdani=nejnovejsi, - body=pocet_bodu, - ) - ) + resiteluv_radek.append(None) + hodnoty.append(resiteluv_radek) + ctx['radky'] = list(zip(self.resitele, hodnoty)) + return ctx class ReseniProblemuView(ListView):