|
@ -463,7 +463,8 @@ def body_resitelu(resitele, za, odjakziva=True): |
|
|
reseni__hodnoceni__cislo_body__poradi__lte=cislo.poradi) )) |
|
|
reseni__hodnoceni__cislo_body__poradi__lte=cislo.poradi) )) |
|
|
elif cislo and not odjakziva: # Body se sčítají za dané číslo. |
|
|
elif cislo and not odjakziva: # Body se sčítají za dané číslo. |
|
|
body_k_zapocteni = Sum('reseni__hodnoceni__body', |
|
|
body_k_zapocteni = Sum('reseni__hodnoceni__body', |
|
|
filter=( Q(reseni__hodnoceni__cislo_body=cislo) )) |
|
|
filter=( Q(reseni__hodnoceni__cislo_body__rocnik__prvni_rok=rok, |
|
|
|
|
|
reseni__hodnoceni__cislo_body__poradi__lte=cislo.poradi) )) |
|
|
elif rocnik and odjakziva: # Spočítáme body za starší ročníky až do zadaného včetně. |
|
|
elif rocnik and odjakziva: # Spočítáme body za starší ročníky až do zadaného včetně. |
|
|
body_k_zapocteni = Sum('reseni__hodnoceni__body', |
|
|
body_k_zapocteni = Sum('reseni__hodnoceni__body', |
|
|
filter= Q(reseni__hodnoceni__cislo_body__rocnik__prvni_rok__lte=rok)) |
|
|
filter= Q(reseni__hodnoceni__cislo_body__rocnik__prvni_rok__lte=rok)) |
|
@ -503,10 +504,7 @@ def vysledkovka_rocniku(rocnik, jen_verejne=True): |
|
|
## 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 |
|
|
aktivni_resitele = list(Resitel.objects.filter( |
|
|
aktivni_resitele = list(resi_v_rocniku(rocnik)) |
|
|
rok_maturity__gte=rocnik.druhy_rok())) |
|
|
|
|
|
# TODO: zkusit hodnoceni__rocnik... |
|
|
|
|
|
#.filter(hodnoceni_set__rocnik__eq=cislo_rocnik) |
|
|
|
|
|
cisla = cisla_rocniku(rocnik, jen_verejne) |
|
|
cisla = cisla_rocniku(rocnik, jen_verejne) |
|
|
body_cisla_slov = {} |
|
|
body_cisla_slov = {} |
|
|
for cislo in cisla: |
|
|
for cislo in cisla: |
|
@ -636,10 +634,15 @@ def pricti_body(slovnik, resitel, body): |
|
|
|
|
|
|
|
|
slovnik[resitel.id] += body |
|
|
slovnik[resitel.id] += body |
|
|
|
|
|
|
|
|
def secti_body_za_rocnik(rocnik, aktivni_resitele): |
|
|
def secti_body_za_rocnik(za, aktivni_resitele): |
|
|
""" Spočítá body za ročník, setřídí je sestupně a vrátí jako seznam.""" |
|
|
""" Spočítá body za ročník (celý nebo do daného čísla), |
|
|
|
|
|
setřídí je sestupně a vrátí jako seznam. |
|
|
|
|
|
Parametry: |
|
|
|
|
|
za (typu Rocnik nebo Cislo) spočítá za ročník, nebo za ročník až do |
|
|
|
|
|
daného čísla |
|
|
|
|
|
""" |
|
|
# spočítáme všem řešitelům jejich body za ročník (False => ne odjakživa) |
|
|
# spočítáme všem řešitelům jejich body za ročník (False => ne odjakživa) |
|
|
resitel_rocnikbody_slov = body_resitelu(aktivni_resitele, rocnik, False) |
|
|
resitel_rocnikbody_slov = body_resitelu(aktivni_resitele, za, False) |
|
|
# zeptáme se na dvojice (řešitel, body) za ročník a setřídíme sestupně |
|
|
# zeptáme se na dvojice (řešitel, body) za ročník a setřídíme sestupně |
|
|
resitel_rocnikbody_sezn = sorted(resitel_rocnikbody_slov.items(), |
|
|
resitel_rocnikbody_sezn = sorted(resitel_rocnikbody_slov.items(), |
|
|
key = lambda x: x[1], reverse = True) |
|
|
key = lambda x: x[1], reverse = True) |
|
@ -685,6 +688,9 @@ def secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy=None): |
|
|
|
|
|
|
|
|
# a mít více řešitelů |
|
|
# a mít více řešitelů |
|
|
for resitel in list(reseni.resitele.all()): |
|
|
for resitel in list(reseni.resitele.all()): |
|
|
|
|
|
if resitel not in aktivni_resitele: |
|
|
|
|
|
print("Skipping {}".format(resitel.id)) |
|
|
|
|
|
continue |
|
|
pricti_body(cislobody, resitel, body) |
|
|
pricti_body(cislobody, resitel, body) |
|
|
pricti_body(nadproblem_slovnik, resitel, body) |
|
|
pricti_body(nadproblem_slovnik, resitel, body) |
|
|
return hlavni_problemy_slovnik, cislobody |
|
|
return hlavni_problemy_slovnik, cislobody |
|
@ -697,16 +703,13 @@ def vysledkovka_cisla(cislo, context=None): |
|
|
## 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 |
|
|
aktivni_resitele = list(Resitel.objects.filter( |
|
|
aktivni_resitele = list(aktivniResitele(cislo.rocnik.rocnik, cislo.poradi)) |
|
|
rok_maturity__gte=cislo.rocnik.druhy_rok())) |
|
|
|
|
|
# TODO: zkusit hodnoceni__rocnik... |
|
|
|
|
|
#.filter(hodnoceni_set__rocnik__eq=cislo_rocnik) |
|
|
|
|
|
|
|
|
|
|
|
# získáme body za číslo |
|
|
# získáme body za číslo |
|
|
hlavni_problemy_slovnik, cislobody = secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy) |
|
|
hlavni_problemy_slovnik, cislobody = secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy) |
|
|
|
|
|
|
|
|
# získáme body za ročník, seznam obsahuje dvojice (řešitel_id, body) setřízené sestupně |
|
|
# získáme body za ročník, seznam obsahuje dvojice (řešitel_id, body) setřízené sestupně |
|
|
resitel_rocnikbody_sezn = secti_body_za_rocnik(cislo.rocnik, aktivni_resitele) |
|
|
resitel_rocnikbody_sezn = secti_body_za_rocnik(cislo, aktivni_resitele) |
|
|
|
|
|
|
|
|
# získáme body odjakživa |
|
|
# získáme body odjakživa |
|
|
resitel_odjakzivabody_slov = body_resitelu(aktivni_resitele, cislo) |
|
|
resitel_odjakzivabody_slov = body_resitelu(aktivni_resitele, cislo) |
|
@ -808,58 +811,73 @@ class RocnikVysledkovkaView(RocnikView): |
|
|
#vypise na stranku textovy obsah vyTeXane vysledkovky k okopirovani |
|
|
#vypise na stranku textovy obsah vyTeXane vysledkovky k okopirovani |
|
|
|
|
|
|
|
|
### Generovani obalek |
|
|
### Generovani obalek |
|
|
|
|
|
def resi_v_rocniku(rocnik, cislo=None): |
|
|
|
|
|
""" Vrátí seznam řešitelů, co vyřešili nějaký problém v daném ročníku, do daného čísla. |
|
|
|
|
|
Parametry: |
|
|
|
|
|
rocnik (typu Rocnik) ročník, ze kterého chci řešitele, co něco odevzdali |
|
|
|
|
|
cislo (typu Cislo) číslo, do kterého včetně se počítá, že v daném |
|
|
|
|
|
ročníku řešitel něco poslal. |
|
|
|
|
|
Pokud není zadané, počítají se všechna řešení z daného ročníku. |
|
|
|
|
|
Výstup: |
|
|
|
|
|
QuerySet objektů typu Resitel """ |
|
|
|
|
|
|
|
|
|
|
|
if cislo is None: |
|
|
|
|
|
# filtrujeme pouze podle ročníku |
|
|
|
|
|
letosni_reseni = Reseni.objects.filter(hodnoceni__cislo_body__rocnik = rocnik) |
|
|
|
|
|
else: # filtrujeme podle ročníku i čísla |
|
|
|
|
|
letosni_reseni = Reseni.objects.filter(hodnoceni__cislo_body__rocnik = rocnik, |
|
|
|
|
|
hodnoceni__cislo_body__poradi__lte=cislo.poradi) |
|
|
|
|
|
|
|
|
class CisloObalkyStruct: |
|
|
# vygenerujeme queryset řešitelů, co letos něco poslali |
|
|
rocnik = None |
|
|
letosni_resitele = Resitel.objects.none() |
|
|
cisla = None |
|
|
for reseni in letosni_reseni: |
|
|
|
|
|
letosni_resitele = letosni_resitele | reseni.resitele.filter(rok_maturity__gte=rocnik.druhy_rok()) |
|
|
|
|
|
return letosni_resitele.distinct() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Vraci QuerySet aktualnich resitelu = nekdy neco poslali, ale jeste neodmaturovali |
|
|
def aktivniResitele(rocnik, cislo): |
|
|
def aktualniResitele(rocnik): |
|
|
""" Vrací QuerySet aktivních řešitelů, což jsou ti, co ještě neodmaturovali |
|
|
|
|
|
a letos něco poslali (anebo loni něco poslali, pokud jde o první tři čísla). |
|
|
|
|
|
Parametry: |
|
|
|
|
|
rocnik (typu int) číslo ročníku, o který se jedná |
|
|
|
|
|
cislo (typu int) pořadí čísla, o které se jedná |
|
|
|
|
|
|
|
|
|
|
|
""" |
|
|
letos = Rocnik.objects.get(rocnik = rocnik) |
|
|
letos = Rocnik.objects.get(rocnik = rocnik) |
|
|
return Resitel.objects.filter(rok_maturity__gt = letos.prvni_rok) |
|
|
#TODO: co se stane, když zadané kombinace neexistují? ošetřit |
|
|
# # ALERT: pokud nekdo nema vypleny rok maturity, tak neni aktualni, protoze Karel Tesar a jini |
|
|
aktualni_cislo = Cislo.objects.get(rocnik = rocnik, poradi = cislo) |
|
|
# return Resitel.objects.filter(Q(rok_maturity__gt = letos.prvni_rok)|Q(rok_maturity = None)) |
|
|
loni = Rocnik.objects.get(rocnik = rocnik - 1) |
|
|
|
|
|
|
|
|
# Vraci QuerySet aktivnich resitelu = |
|
|
|
|
|
# jeste neodmaturovali && |
|
|
|
|
|
# (pokud je aktualni cislo mensi nez 3, pak (letos || loni) neco poslali |
|
|
|
|
|
# jinak letos neco poslali) |
|
|
|
|
|
def aktivniResitele(rocnik,cislo): |
|
|
|
|
|
letos = CisloObalkyStruct() |
|
|
|
|
|
loni = CisloObalkyStruct() |
|
|
|
|
|
|
|
|
|
|
|
aktualni_resitele = aktualniResitele(rocnik) |
|
|
|
|
|
|
|
|
|
|
|
letos.rocnik = Rocnik.objects.get(rocnik = rocnik) |
|
|
|
|
|
loni.rocnik = Rocnik.objects.get(rocnik = int(rocnik)-1) |
|
|
|
|
|
letos.cisla = Cislo.objects.filter(rocnik=letos.rocnik, cislo__lte = cislo) |
|
|
|
|
|
loni.cisla = Cislo.objects.filter(rocnik=loni.rocnik) |
|
|
|
|
|
if int(cislo) > 3: |
|
|
|
|
|
problemy = Problem.objects.filter(cislo_zadani__in = letos.cisla) |
|
|
|
|
|
else: |
|
|
|
|
|
problemy = Problem.objects.filter( |
|
|
|
|
|
Q(cislo_zadani__in = letos.cisla) | Q(cislo_zadani__in = loni.cisla) ) |
|
|
|
|
|
resitele = aktualni_resitele.filter(reseni__in = Reseni.objects.filter( |
|
|
|
|
|
problem__in=problemy)).distinct() |
|
|
|
|
|
return resitele |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# detekujeme, zda jde o první tři čísla či nikoli |
|
|
|
|
|
zacatek_rocniku = True |
|
|
|
|
|
try: |
|
|
|
|
|
if int(aktualni_cislo.poradi) > 3: |
|
|
|
|
|
zacatek_rocniku = False |
|
|
|
|
|
except ValueError: |
|
|
|
|
|
# pravděpodobně se jedná o číslo 7-8 |
|
|
|
|
|
zacatek_rocniku = False |
|
|
|
|
|
|
|
|
|
|
|
if not zacatek_rocniku: |
|
|
|
|
|
return resi_v_rocniku(letos) |
|
|
|
|
|
else: |
|
|
|
|
|
# spojíme querysety s řešiteli loni a letos do daného čísla |
|
|
|
|
|
return (resi_v_rocniku(loni) | resi_v_rocniku(letos, aktualni_cislo)).distinct() |
|
|
|
|
|
|
|
|
def cisloObalkyView(request,rocnik,cislo): |
|
|
def cisloObalkyView(request, rocnik, cislo): |
|
|
return obalkyView(request,aktivniResitele(rocnik,cislo)) |
|
|
return obalkyView(request, aktivniResitele(rocnik, cislo)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def obalkyView(request,resitele): |
|
|
def obalkyView(request, resitele): |
|
|
tex = render(request,'seminar/archiv/obalky.tex', {'resitele': resitele}).content |
|
|
tex = render(request,'seminar/archiv/obalky.tex', {'resitele': resitele}).content |
|
|
|
|
|
|
|
|
tempdir = tempfile.mkdtemp() |
|
|
tempdir = tempfile.mkdtemp() |
|
|
with open(tempdir+"/obalky.tex","w") as texfile: |
|
|
with open(tempdir+"/obalky.tex","w") as texfile: |
|
|
texfile.write(tex) |
|
|
texfile.write(tex.decode()) |
|
|
shutil.copy(os.path.join(settings.STATIC_ROOT, 'seminar/lisak.pdf'),tempdir) |
|
|
shutil.copy(os.path.join(settings.STATIC_ROOT, 'seminar/lisak.pdf'), tempdir) |
|
|
subprocess.call(["pdflatex","obalky.tex"],cwd = tempdir) |
|
|
subprocess.call(["pdflatex","obalky.tex"], cwd = tempdir) |
|
|
|
|
|
|
|
|
with open(tempdir+"/obalky.pdf","rb") as pdffile: |
|
|
with open(tempdir+"/obalky.pdf","rb") as pdffile: |
|
|
response = HttpResponse(pdffile.read(),content_type='application/pdf') |
|
|
response = HttpResponse(pdffile.read(), content_type='application/pdf') |
|
|
shutil.rmtree(tempdir) |
|
|
shutil.rmtree(tempdir) |
|
|
return response |
|
|
return response |
|
|
|
|
|
|
|
|