@ -13,6 +13,7 @@ from django.db.models import Q
from dataclasses import dataclass
from dataclasses import dataclass
import datetime
import datetime
from decimal import Decimal
from itertools import groupby
from itertools import groupby
import logging
import logging
@ -37,14 +38,6 @@ logger = logging.getLogger(__name__)
# Taky se může hodit:
# Taky se může hodit:
# - Tabulka všech řešitelů x všech problémů?
# - Tabulka všech řešitelů x všech problémů?
@dataclass
class SouhrnReseni :
""" Dataclass reprezentující data o odevzdaných řešeních pro zobrazení v tabulce. """
pocet_reseni : int
posledni_odevzdani : datetime . datetime
body : float
class TabulkaOdevzdanychReseniView ( ListView ) :
class TabulkaOdevzdanychReseniView ( ListView ) :
template_name = ' odevzdavatko/tabulka.html '
template_name = ' odevzdavatko/tabulka.html '
model = m . Hodnoceni
model = m . Hodnoceni
@ -70,6 +63,7 @@ class TabulkaOdevzdanychReseniView(ListView):
reseni_od = fcd [ " reseni_od " ]
reseni_od = fcd [ " reseni_od " ]
reseni_do = fcd [ " reseni_do " ]
reseni_do = fcd [ " reseni_do " ]
jen_neobodovane = fcd [ " neobodovane " ]
jen_neobodovane = fcd [ " neobodovane " ]
self . barvicky = fcd [ " barvicky " ]
else :
else :
initial = FiltrForm . gen_initial ( self . aktualni_rocnik )
initial = FiltrForm . gen_initial ( self . aktualni_rocnik )
resitele = initial [ ' resitele ' ]
resitele = initial [ ' resitele ' ]
@ -77,6 +71,7 @@ class TabulkaOdevzdanychReseniView(ListView):
reseni_od = initial [ ' reseni_od ' ] [ 0 ]
reseni_od = initial [ ' reseni_od ' ] [ 0 ]
reseni_do = initial [ ' reseni_do ' ] [ 0 ]
reseni_do = initial [ ' reseni_do ' ] [ 0 ]
jen_neobodovane = initial [ " neobodovane " ]
jen_neobodovane = initial [ " neobodovane " ]
self . barvicky = initial [ " barvicky " ]
# Chceme jen letošní problémy
# Chceme jen letošní problémy
@ -120,42 +115,45 @@ class TabulkaOdevzdanychReseniView(ListView):
return qs
return qs
def get_context_data ( self , * args , * * kwargs ) :
def get_context_data ( self , * args , * * kwargs ) :
# TODO: refactor asi. Přepisoval jsem to jen syntakticky, nejspíš půlka kódu přestala dávat smysl…
# self.resitele, self.reseni a self.problemy jsou již nastavené
# self.resitele, self.reseni a self.problemy jsou již nastavené
ctx = super ( ) . get_context_data ( * args , * * kwargs )
ctx = super ( ) . get_context_data ( * args , * * kwargs )
ctx [ ' problemy ' ] = self . problemy
ctx [ ' problemy ' ] = self . problemy
ctx [ ' resitele ' ] = self . resitele
ctx [ ' resitele ' ] = self . resitele
tabulka = dict ( )
tabulka : dict [ m . Problem , dict [ m . Resitel , list [ tuple [ m . Reseni , m . Hodnoceni ] ] ] ] = dict ( )
soucty : dict [ m . Problem , dict [ m . Resitel , Decimal ] ] = dict ( )
def pridej_reseni ( problem , resitel , body , cas ) :
def pridej_reseni ( resitel , hodnoceni ) :
problem = hodnoceni . problem
body = hodnoceni . body
cas = hodnoceni . reseni . cas_doruceni
reseni = hodnoceni . reseni
if problem not in tabulka :
if problem not in tabulka :
tabulka [ problem ] = dict ( )
tabulka [ problem ] = dict ( )
soucty [ problem ] = dict ( )
if resitel not in tabulka [ problem ] :
if resitel not in tabulka [ problem ] :
tabulka [ problem ] [ resitel ] = SouhrnReseni ( pocet_reseni = 1 , posledni_odevzdani = cas , body = body )
tabulka [ problem ] [ resitel ] = [ ( reseni , hodnoceni ) ]
soucty [ problem ] [ resitel ] = hodnoceni . body or 0 # Neobodované neřešíme
else :
else :
tabulka [ problem ] [ resitel ] . posledni_odevzdani = max ( tabulka [ problem ] [ resitel ] . posledni_odevzdani , cas )
tabulka [ problem ] [ resitel ] . append ( ( reseni , hodnoceni ) )
# Zvětšení počtu bodů o aktuální počet, pokud se tam někde nevyskytuje None – pak je součet taky None ("Pozor, nezadané body")
soucty [ problem ] [ resitel ] + = hodnoceni . body or 0 # Neobodované neřešíme
tabulka [ problem ] [ resitel ] . body = tabulka [ problem ] [ resitel ] . body + body if body is not None and tabulka [ problem ] [ resitel ] . body is not None else None
tabulka [ problem ] [ resitel ] . pocet_reseni + = 1
# Pro jednoduchost template si ještě poznamenáme ID problému a řešitele
tabulka [ problem ] [ resitel ] . problem_id = problem . id
tabulka [ problem ] [ resitel ] . resitel_id = resitel . id
for hodnoceni in self . get_queryset ( ) :
for hodnoceni in self . get_queryset ( ) :
for resitel in hodnoceni . reseni . resitele . all ( ) :
for resitel in hodnoceni . reseni . resitele . all ( ) :
pridej_reseni ( hodnoceni . problem , resitel , hodnoceni . body , hodnoceni . reseni . cas_doru ceni )
pridej_reseni ( resitel , hodnoceni )
hodnoty = [ ]
hodnoty : list [ list [ tuple [ Decimal , list [ tuple [ m . Reseni , m . Hodnoceni ] ] ] ] ] = [ ] # Seznam řádků výsledné tabulky podle self.resitele, v každém řádku buňky v pořadí podle self.problemy + jejich součty, v každé buňce seznam řešení k danému řešiteli a problému.
resitele_do_tabulky = [ ]
resitele_do_tabulky : list [ m . Resitel ] = [ ]
for resitel in self . resitele :
for resitel in self . resitele :
dostal_body = False
dostal_body = False
resiteluv_radek = [ ]
resiteluv_radek : list [ tuple [ Decimal , list [ tuple [ m . Reseni , m . Hodnoceni ] ] ] ] = [ ] # podle pořadí v self.problemy
for problem in self . problemy :
for problem in self . problemy :
if problem in tabulka and resitel in tabulka [ problem ] :
if problem in tabulka and resitel in tabulka [ problem ] :
resiteluv_radek . append ( tabulka [ problem ] [ resitel ] )
resiteluv_radek . append ( ( soucty [ problem ] [ resitel ] , tabulka [ problem ] [ resitel ] ) )
dostal_body = True
dostal_body = True
else :
else :
resiteluv_radek . append ( None )
resiteluv_radek . append ( ( Decimal ( 0 ) , [ ] ) )
if self . chteni_resitele != FiltrForm . RESITELE_RELEVANTNI or dostal_body :
if self . chteni_resitele != FiltrForm . RESITELE_RELEVANTNI or dostal_body :
hodnoty . append ( resiteluv_radek )
hodnoty . append ( resiteluv_radek )
resitele_do_tabulky . append ( resitel )
resitele_do_tabulky . append ( resitel )
@ -165,6 +163,7 @@ class TabulkaOdevzdanychReseniView(ListView):
ctx [ ' form ' ] = ctx [ ' filtr ' ]
ctx [ ' form ' ] = ctx [ ' filtr ' ]
# Pro maximum v přesměrovátku ročníků
# Pro maximum v přesměrovátku ročníků
ctx [ ' aktualni_rocnik ' ] = m . Nastaveni . get_solo ( ) . aktualni_rocnik
ctx [ ' aktualni_rocnik ' ] = m . Nastaveni . get_solo ( ) . aktualni_rocnik
ctx [ ' barvicky ' ] = self . barvicky
if ' rocnik ' in self . kwargs :
if ' rocnik ' in self . kwargs :
ctx [ ' rocnik ' ] = self . kwargs [ ' rocnik ' ]
ctx [ ' rocnik ' ] = self . kwargs [ ' rocnik ' ]
else :
else :
@ -174,6 +173,11 @@ class TabulkaOdevzdanychReseniView(ListView):
# Velmi silně inspirováno zdrojáky, FIXME: Nedá se to udělat smysluplněji?
# Velmi silně inspirováno zdrojáky, FIXME: Nedá se to udělat smysluplněji?
class ReseniProblemuView ( MultipleObjectTemplateResponseMixin , MultipleObjectMixin , View ) :
class ReseniProblemuView ( MultipleObjectTemplateResponseMixin , MultipleObjectMixin , View ) :
""" Rozskok mezi více řešeními téhož problému od téhož řešitele.
Asi už bude zastaralý v okamžiku , kdy se tenhle komentář nasadí na produkci : - )
V případě , že takové řešení existuje jen jedno , tak na něj přesměruje . """
model = m . Reseni
model = m . Reseni
template_name = ' odevzdavatko/seznam.html '
template_name = ' odevzdavatko/seznam.html '