Browse Source

Merge branch 'data_migrations' of gimli.ms.mff.cuni.cz:/akce/mam/git/mamweb into data_migrations

export_seznamu_prednasek
Kateřina Č 4 years ago
parent
commit
4ed15d16a7
  1. 12
      seminar/models.py
  2. 51
      seminar/utils.py
  3. 24
      seminar/views/views_all.py
  4. 47
      seminar/views/vysledkovka.py

12
seminar/models.py

@ -18,6 +18,7 @@ from django.contrib.contenttypes.models import ContentType
from django.utils.text import get_valid_filename from django.utils.text import get_valid_filename
from imagekit.models import ImageSpecField, ProcessedImageField from imagekit.models import ImageSpecField, ProcessedImageField
from imagekit.processors import ResizeToFit, Transpose from imagekit.processors import ResizeToFit, Transpose
from django.utils.functional import cached_property
from django_countries.fields import CountryField from django_countries.fields import CountryField
from solo.models import SingletonModel from solo.models import SingletonModel
@ -855,10 +856,11 @@ class Problem(SeminarModelBase,PolymorphicModel):
return self.nazev return self.nazev
# Implicitini implementace, jednotlivé dědící třídy si přepíšou # Implicitini implementace, jednotlivé dědící třídy si přepíšou
@cached_property
def kod_v_rocniku(self): def kod_v_rocniku(self):
if self.stav == 'zadany': if self.stav == 'zadany':
if self.nadproblem: if self.nadproblem:
return self.nadproblem.kod_v_rocniku()+".{}".format(self.kod) return self.nadproblem.kod_v_rocniku+".{}".format(self.kod)
return str(self.kod) return str(self.kod)
return '<Není zadaný>' return '<Není zadaný>'
@ -927,10 +929,11 @@ class Tema(Problem):
abstrakt = models.TextField('Abstrakt na rozcestník', blank=True) abstrakt = models.TextField('Abstrakt na rozcestník', blank=True)
obrazek = models.ImageField('Obrázek na rozcestník', null=True) obrazek = models.ImageField('Obrázek na rozcestník', null=True)
@cached_property
def kod_v_rocniku(self): def kod_v_rocniku(self):
if self.stav == 'zadany': if self.stav == 'zadany':
if self.nadproblem: if self.nadproblem:
return self.nadproblem.kod_v_rocniku()+".t{}".format(self.kod) return self.nadproblem.kod_v_rocniku+".t{}".format(self.kod)
return "t{}".format(self.kod) return "t{}".format(self.kod)
return '<Není zadaný>' return '<Není zadaný>'
@ -963,7 +966,7 @@ class Clanek(Problem):
if self.stav == 'zadany': if self.stav == 'zadany':
# Nemělo by být potřeba # Nemělo by být potřeba
# if self.nadproblem: # if self.nadproblem:
# return self.nadproblem.kod_v_rocniku()+".c{}".format(self.kod) # return self.nadproblem.kod_v_rocniku+".c{}".format(self.kod)
return "c{}".format(self.kod) return "c{}".format(self.kod)
return '<Není zadaný>' return '<Není zadaný>'
@ -1020,11 +1023,12 @@ class Uloha(Problem):
# UlohaZadaniNode # UlohaZadaniNode
# UlohaVzorakNode # UlohaVzorakNode
@cached_property
def kod_v_rocniku(self): def kod_v_rocniku(self):
if self.stav == 'zadany': if self.stav == 'zadany':
name="{}.u{}".format(self.cislo_zadani.poradi,self.kod) name="{}.u{}".format(self.cislo_zadani.poradi,self.kod)
if self.nadproblem: if self.nadproblem:
return self.nadproblem.kod_v_rocniku()+name return self.nadproblem.kod_v_rocniku+name
return name return name
return '<Není zadaný>' return '<Není zadaný>'

51
seminar/utils.py

@ -17,10 +17,11 @@ import seminar.treelib as t
org_required = permission_required('auth.org', raise_exception=True) org_required = permission_required('auth.org', raise_exception=True)
resitel_required = permission_required('auth.resitel', raise_exception=True) resitel_required = permission_required('auth.resitel', raise_exception=True)
User = get_user_model() User = get_user_model()
User.je_org = lambda self: self.has_perm('auth.org') # Není to úplně hezké, ale budeme doufat, že to je funkční...
User.je_resitel = lambda self: self.has_perm('auth.resitel') User.je_org = property(lambda self: self.has_perm('auth.org'))
AnonymousUser.je_org = lambda self: False User.je_resitel = property(lambda self: self.has_perm('auth.resitel'))
AnonymousUser.je_resitel = lambda self: False AnonymousUser.je_org = False
AnonymousUser.je_resitel = False
class FirstTagParser(HTMLParser): class FirstTagParser(HTMLParser):
@ -239,47 +240,25 @@ def hlavni_problem(problem):
problem = problem.nadproblem problem = problem.nadproblem
return problem return problem
def hlavni_problemy_rocniku(rocnik, jen_verejne=True): def problemy_rocniku(rocnik, jen_verejne=True):
""" Pro zadaný ročník vrátí hlavní problémy ročníku, return m.Problem.objects.filter(hodnoceni__in = m.Hodnoceni.objects.filter(cislo_body__in = cisla_rocniku(rocnik, jen_verejne))).distinct().select_related('nadproblem').select_related('nadproblem__nadproblem')
tj. ty, které nemají nadproblém."""
hlavni_problemy = []
for cislo in cisla_rocniku(rocnik, jen_verejne):
for problem in hlavni_problemy_cisla(cislo):
hlavni_problemy.append(problem)
hlavni_problemy_set = set(hlavni_problemy)
hlavni_problemy = list(hlavni_problemy_set)
hlavni_problemy.sort(key=lambda k:k.kod_v_rocniku()) # setřídit podle pořadí
return hlavni_problemy
def problemy_cisla(cislo): def problemy_cisla(cislo):
""" Vrátí seznam všech problémů s body v daném čísle. """ """ Vrátí seznam všech problémů s body v daném čísle. """
hodnoceni = cislo.hodnoceni.select_related('problem', 'reseni').all() return m.Problem.objects.filter(hodnoceni__in = m.Hodnoceni.objects.filter(cislo_body = cislo)).distinct().select_related('nadproblem').select_related('nadproblem__nadproblem')
# 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čí
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)
def hlavni_problemy_f(problemy=None):
""" Vrátí seznam všech problémů, které již nemají nadproblém. """
# hlavní problémy čísla # hlavní problémy čísla
# (mají vlastní sloupeček ve výsledkovce, nemají nadproblém) # (mají vlastní sloupeček ve výsledkovce, nemají nadproblém)
hlavni_problemy = [] hlavni_problemy = set()
for p in problemy: for p in problemy:
hlavni_problemy.append(hlavni_problem(p)) hlavni_problemy.add(hlavni_problem(p))
# zunikátnění # zunikátnění
hlavni_problemy_set = set(hlavni_problemy) hlavni_problemy = list(hlavni_problemy)
hlavni_problemy = list(hlavni_problemy_set) hlavni_problemy.sort(key=lambda k: k.kod_v_rocniku) # setřídit podle t1, t2, c3, ...
hlavni_problemy.sort(key=lambda k: k.kod_v_rocniku()) # setřídit podle t1, t2, c3, ...
return hlavni_problemy return hlavni_problemy
@ -289,7 +268,7 @@ def podproblemy_v_cislu(cislo, problemy=None, hlavni_problemy=None):
if problemy is None: if problemy is None:
problemy = problemy_cisla(cislo) problemy = problemy_cisla(cislo)
if hlavni_problemy is None: if hlavni_problemy is None:
hlavni_problemy = hlavni_problemy_cisla(cislo, problemy) hlavni_problemy = hlavni_problemy_f(problemy)
podproblemy = dict((hp.id, []) for hp in hlavni_problemy) podproblemy = dict((hp.id, []) for hp in hlavni_problemy)
hlavni_problemy = set(hlavni_problemy) hlavni_problemy = set(hlavni_problemy)

24
seminar/views/views_all.py

@ -49,7 +49,7 @@ import csv
import logging import logging
import time import time
from seminar.utils import aktivniResitele, resi_v_rocniku, hlavni_problemy_rocniku, cisla_rocniku, hlavni_problemy_cisla from seminar.utils import aktivniResitele, resi_v_rocniku, problemy_rocniku, cisla_rocniku, hlavni_problemy_f
# ze starého modelu # ze starého modelu
#def verejna_temata(rocnik): #def verejna_temata(rocnik):
@ -644,29 +644,25 @@ class RocnikView(generic.DetailView):
def get_object(self, queryset=None): def get_object(self, queryset=None):
if queryset is None: if queryset is None:
queryset = self.get_queryset() queryset = self.get_queryset()
rocnik_arg = self.kwargs.get('rocnik')
queryset = queryset.filter(rocnik=rocnik_arg)
try: return get_object_or_404(queryset,rocnik=self.kwargs.get('rocnik'))
obj = queryset.get()
except queryset.model.DoesNotExist:
raise Http404(_("No %(verbose_name)s found matching the query") %
{'verbose_name': queryset.model._meta.verbose_name})
return obj
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
start = time.time()
context = super(RocnikView, self).get_context_data(**kwargs) context = super(RocnikView, self).get_context_data(**kwargs)
# vysledkovka = True zajistí vykreslení, # vysledkovka = True zajistí vykreslení,
# zkontrolovat, kdy se má a nemá vykreslovat # zkontrolovat, kdy se má a nemá vykreslovat
context['vysledkovka'] = True context['vysledkovka'] = True
if self.request.user.je_org:
context['cisla_s_neverejnymi'] = cisla_rocniku(context["rocnik"], jen_verejne=False) context['cisla_s_neverejnymi'] = cisla_rocniku(context["rocnik"], jen_verejne=False)
context['radky_vysledkovky_s_neverejnymi'] = vysledkovka_rocniku(context["rocnik"], jen_verejne=False)
context['hlavni_problemy_v_rocniku_s_neverejnymi'] = hlavni_problemy_f(problemy_rocniku(context["rocnik"], jen_verejne=False))
context['cisla'] = cisla_rocniku(context["rocnik"]) context['cisla'] = cisla_rocniku(context["rocnik"])
context['radky_vysledkovky'] = vysledkovka_rocniku(context["rocnik"]) context['radky_vysledkovky'] = vysledkovka_rocniku(context["rocnik"])
context['radky_vysledkovky_s_neverejnymi'] = vysledkovka_rocniku( context['hlavni_problemy_v_rocniku'] = hlavni_problemy_f(problemy_rocniku(context["rocnik"]))
context["rocnik"], jen_verejne=False) end = time.time()
context['hlavni_problemy_v_rocniku'] = hlavni_problemy_rocniku(context["rocnik"]) print("Kontext:", end-start)
context['hlavni_problemy_v_rocniku_s_neverejnymi'] = hlavni_problemy_rocniku(context["rocnik"], jen_verejne=False)
return context return context
@ -973,7 +969,7 @@ class ClankyResitelView(generic.ListView):
queryset = [] queryset = []
skupiny_clanku = group_by_rocnik(clanky) skupiny_clanku = group_by_rocnik(clanky)
for skupina in skupiny_clanku: for skupina in skupiny_clanku:
skupina.sort(key=lambda clanek: clanek.kod_v_rocniku()) skupina.sort(key=lambda clanek: clanek.kod_v_rocniku)
for clanek in skupina: for clanek in skupina:
queryset.append(clanek) queryset.append(clanek)
return queryset return queryset

47
seminar/views/vysledkovka.py

@ -1,6 +1,7 @@
import seminar.models as m import seminar.models as m
from django.db.models import Q, Sum, Count from django.db.models import Q, Sum, Count
from seminar.utils import aktivniResitele, resi_v_rocniku, cisla_rocniku, hlavni_problemy_rocniku, hlavni_problem, hlavni_problemy_cisla, problemy_cisla, podproblemy_v_cislu from seminar.utils import aktivniResitele, resi_v_rocniku, cisla_rocniku, hlavni_problem, hlavni_problemy_f, problemy_cisla, podproblemy_v_cislu
import time
### Výsledky ### Výsledky
def sloupec_s_poradim(setrizene_body): def sloupec_s_poradim(setrizene_body):
@ -126,15 +127,16 @@ class RadekVysledkovkyRocniku(object):
def setrid_resitele_a_body(slov_resitel_body): def setrid_resitele_a_body(slov_resitel_body):
setrizeni_resitele_id = [dvojice[0] for dvojice in slov_resitel_body] setrizeni_resitele_id = [dvojice[0] for dvojice in slov_resitel_body]
setrizeni_resitele = [m.Resitel.objects.get(id=i) for i in setrizeni_resitele_id]
setrizene_body = [dvojice[1] for dvojice in slov_resitel_body] setrizene_body = [dvojice[1] for dvojice in slov_resitel_body]
return setrizeni_resitele_id, setrizeni_resitele, setrizene_body return setrizeni_resitele_id, setrizene_body
def vysledkovka_rocniku(rocnik, jen_verejne=True): def vysledkovka_rocniku(rocnik, jen_verejne=True):
""" Přebírá ročník (např. context["rocnik"]) a vrací výsledkovou listinu ve """ Přebírá ročník (např. context["rocnik"]) a vrací výsledkovou listinu ve
formě vhodné pro šablonu "seminar/vysledkovka_rocniku.html" formě vhodné pro šablonu "seminar/vysledkovka_rocniku.html"
""" """
start = time.time()
## TODO možná chytřeji vybírat aktivní řešitele ## 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í # 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 # u alespoň jedné hodnoty něco jiného než NULL
@ -150,7 +152,7 @@ def vysledkovka_rocniku(rocnik, jen_verejne=True):
resitel_rocnikbody_sezn = secti_body_za_rocnik(rocnik, aktivni_resitele) resitel_rocnikbody_sezn = secti_body_za_rocnik(rocnik, aktivni_resitele)
# setřídíme řešitele podle počtu bodů a získáme seznam s body od nejvyšších po nenižší # setřídíme řešitele podle počtu bodů a získáme seznam s body od nejvyšších po nenižší
setrizeni_resitele_id, setrizeni_resitele, setrizene_body = setrid_resitele_a_body(resitel_rocnikbody_sezn) setrizeni_resitele_id, setrizene_body = setrid_resitele_a_body(resitel_rocnikbody_sezn)
poradi = sloupec_s_poradim(setrizene_body) poradi = sloupec_s_poradim(setrizene_body)
# získáme body odjakživa # získáme body odjakživa
@ -159,6 +161,10 @@ def vysledkovka_rocniku(rocnik, jen_verejne=True):
# vytvoříme jednotlivé sloupce výsledkovky # vytvoříme jednotlivé sloupce výsledkovky
radky_vysledkovky = [] radky_vysledkovky = []
i = 0 i = 0
setrizeni_resitele_dict = {} # Tento slovnik se vyrab
for r in m.Resitel.objects.filter(id__in=setrizeni_resitele_id).select_related('osoba'):
setrizeni_resitele_dict[r.id] = r
for ar_id in setrizeni_resitele_id: for ar_id in setrizeni_resitele_id:
# seznam počtu bodů daného řešitele pro jednotlivá čísla # seznam počtu bodů daného řešitele pro jednotlivá čísla
body_cisla_sezn = [] body_cisla_sezn = []
@ -168,7 +174,7 @@ def vysledkovka_rocniku(rocnik, jen_verejne=True):
# vytáhneme informace pro daného řešitele # vytáhneme informace pro daného řešitele
radek = RadekVysledkovkyRocniku( radek = RadekVysledkovkyRocniku(
poradi[i], # pořadí poradi[i], # pořadí
m.Resitel.objects.get(id=ar_id), # řešitel (z id) setrizeni_resitele_dict[ar_id], # řešitel (z id)
body_cisla_sezn, # seznam bodů za čísla body_cisla_sezn, # seznam bodů za čísla
setrizene_body[i], # body za ročník (spočítané výše s pořadím) setrizene_body[i], # body za ročník (spočítané výše s pořadím)
resitel_odjakzivabody_slov[ar_id], # body odjakživa resitel_odjakzivabody_slov[ar_id], # body odjakživa
@ -176,7 +182,11 @@ def vysledkovka_rocniku(rocnik, jen_verejne=True):
radky_vysledkovky.append(radek) radky_vysledkovky.append(radek)
i += 1 i += 1
end = time.time()
print("Vysledkovka rocniku",end-start)
return radky_vysledkovky return radky_vysledkovky
class RadekVysledkovkyCisla(object): class RadekVysledkovkyCisla(object):
"""Obsahuje věci, které se hodí vědět při konstruování výsledkovky. """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).""" Umožňuje snazší práci v templatu (lepší, než seznam)."""
@ -225,17 +235,18 @@ def secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy=None):
# TODO setřídit hlavní problémy čísla podle id, ať jsou ve stejném pořadí pokaždé # TODO setřídit hlavní problémy čísla podle id, ať jsou ve stejném pořadí pokaždé
# pro každý hlavní problém zavedeme slovník s body za daný hlavní problém # pro každý hlavní problém zavedeme slovník s body za daný hlavní problém
# pro jednotlivé řešitele (slovník slovníků hlavních problémů) # pro jednotlivé řešitele (slovník slovníků hlavních problémů)
print("Scitam cislo",cislo)
if hlavni_problemy is None: if hlavni_problemy is None:
hlavni_problemy = hlavni_problemy_cisla(cislo) hlavni_problemy = hlavni_problemy_f(problemy_cisla(cislo))
def ne_clanek_ne_konfera(problem): def ne_clanek_ne_konfera(problem):
return not(isinstance(problem.get_real_instance(), m.Clanek) or isinstance(problem.get_real_instance(), m.Konfera)) inst = problem.get_real_instance()
return not(isinstance(inst, m.Clanek) or isinstance(inst, m.Konfera))
temata_a_spol = list(filter(ne_clanek_ne_konfera, hlavni_problemy)) temata_a_spol = list(filter(ne_clanek_ne_konfera, hlavni_problemy))
def cosi(problem):
return problem.id
hlavni_problemy_slovnik = {} hlavni_problemy_slovnik = {}
for hp in temata_a_spol: for hp in temata_a_spol:
hlavni_problemy_slovnik[hp.id] = {} hlavni_problemy_slovnik[hp.id] = {}
@ -257,6 +268,7 @@ def secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy=None):
reseni_do_cisla = m.Reseni.objects.prefetch_related('problem', 'resitele', reseni_do_cisla = m.Reseni.objects.prefetch_related('problem', 'resitele',
'hodnoceni_set').filter(hodnoceni__cislo_body=cislo) 'hodnoceni_set').filter(hodnoceni__cislo_body=cislo)
start = time.time()
# projdeme všechna řešení do čísla a přičteme body každému řešiteli do celkových # 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 # bodů i do bodů za problém
for reseni in reseni_do_cisla: for reseni in reseni_do_cisla:
@ -280,13 +292,15 @@ def secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy=None):
continue continue
pricti_body(cislobody, resitel, body) pricti_body(cislobody, resitel, body)
pricti_body(nadproblem_slovnik, resitel, body) pricti_body(nadproblem_slovnik, resitel, body)
end = time.time()
print("for cykly:", end-start)
return hlavni_problemy_slovnik, cislobody return hlavni_problemy_slovnik, cislobody
def secti_body_za_cislo_podle_temat(cislo, aktivni_resitele, podproblemy=None, temata=None): 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).""" """ Spočítá u řešitelů body za číslo za úlohy v jednotlivých hlavních problémech (témata)."""
if temata is None: if temata is None:
temata = hlavni_problemy_cisla(cislo) temata = hlavni_problemy_f(problemy_cisla(cislo))
if podproblemy is None: if podproblemy is None:
podproblemy_v_cislu(cislo, hlavni_problemy=temata) podproblemy_v_cislu(cislo, hlavni_problemy=temata)
@ -356,7 +370,7 @@ def vysledkovka_cisla(cislo, context=None):
if context is None: if context is None:
context = {} context = {}
problemy = problemy_cisla(cislo) problemy = problemy_cisla(cislo)
hlavni_problemy = hlavni_problemy_cisla(cislo, problemy) hlavni_problemy = hlavni_problemy_f(problemy)
## TODO možná chytřeji vybírat aktivní řešitele ## 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í # 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 # u alespoň jedné hodnoty něco jiného než NULL
@ -373,7 +387,6 @@ def vysledkovka_cisla(cislo, context=None):
# řešitelé setřídění podle bodů za číslo sestupně # řešitelé setřídění podle bodů za číslo sestupně
setrizeni_resitele_id = [dvojice[0] for dvojice in resitel_rocnikbody_sezn] setrizeni_resitele_id = [dvojice[0] for dvojice in resitel_rocnikbody_sezn]
setrizeni_resitele = [m.Resitel.objects.get(id=i) for i in setrizeni_resitele_id]
# spočítáme pořadí řešitelů # spočítáme pořadí řešitelů
setrizeni_resitele_body = [dvojice[1] for dvojice in resitel_rocnikbody_sezn] setrizeni_resitele_body = [dvojice[1] for dvojice in resitel_rocnikbody_sezn]
@ -384,6 +397,7 @@ def vysledkovka_cisla(cislo, context=None):
i = 0 i = 0
def ne_clanek_ne_konfera(problem): def ne_clanek_ne_konfera(problem):
return not(isinstance(problem.get_real_instance(), m.Clanek) or isinstance(problem.get_real_instance(), m.Konfera)) return not(isinstance(problem.get_real_instance(), m.Clanek) or isinstance(problem.get_real_instance(), m.Konfera))
temata_a_spol = list(filter(ne_clanek_ne_konfera, hlavni_problemy)) temata_a_spol = list(filter(ne_clanek_ne_konfera, hlavni_problemy))
@ -399,6 +413,11 @@ def vysledkovka_cisla(cislo, context=None):
je_nejake_ostatni = len(hlavni_problemy) - len(temata_a_spol) > 0 je_nejake_ostatni = len(hlavni_problemy) - len(temata_a_spol) > 0
setrizeni_resitele_slovnik = {}
setrizeni_resitele = m.Resitel.objects.filter(id__in=setrizeni_resitele_id).select_related('osoba')
for r in setrizeni_resitele:
setrizeni_resitele_slovnik[r.id] = r
for ar_id in setrizeni_resitele_id: for ar_id in setrizeni_resitele_id:
# získáme seznam bodů za problémy pro daného řešitele # získáme seznam bodů za problémy pro daného řešitele
body_problemy = [] body_problemy = []
@ -412,7 +431,7 @@ def vysledkovka_cisla(cislo, context=None):
# vytáhneme informace pro daného řešitele # vytáhneme informace pro daného řešitele
radek = RadekVysledkovkyCisla( radek = RadekVysledkovkyCisla(
poradi[i], # pořadí poradi[i], # pořadí
m.Resitel.objects.get(id=ar_id), # řešitel (z id) setrizeni_resitele_slovnik[ar_id], # řešitel (z id)
body_problemy, # seznam bodů za hlavní problémy čísla body_problemy, # seznam bodů za hlavní problémy čísla
cislobody[ar_id], # body za číslo cislobody[ar_id], # body za číslo
setrizeni_resitele_body[i], # body za ročník (spočítané výše s pořadím) setrizeni_resitele_body[i], # body za ročník (spočítané výše s pořadím)

Loading…
Cancel
Save