@ -9,20 +9,19 @@ from django.utils.translation import ugettext as _
from django . http import Http404 , HttpResponseBadRequest , HttpResponseRedirect
from django . db . models import Q , Sum , Count
from django . views . decorators . csrf import ensure_csrf_cookie
from django . views . generic . edit import FormView
from django . views . generic . edit import FormView , CreateView
from django . contrib . auth import authenticate , login , get_user_model , logout
from django . contrib . auth import views as auth_views
from django . contrib . auth . models import User
from django . contrib . auth . mixins import LoginRequiredMixin
from django . db import transaction
from dal import autocomplete
import seminar . models as s
from . models import Problem , Cislo , Reseni , Nastaveni , Rocnik , Soustredeni , Organizator , Resitel , Novinky , Soustredeni_Ucastnici , Pohadka , Tema , Clanek , Osoba , Skola # Tohle je stare a chceme se toho zbavit. Pouzivejte s.ToCoChci
from seminar . models import Problem , Cislo , Reseni , Nastaveni , Rocnik , Soustredeni , Organizator , Resitel , Novinky , Soustredeni_Ucastnici , Pohadka , Tema , Clanek , Osoba , Skola # Tohle je stare a chceme se toho zbavit. Pouzivejte s.ToCoChci
#from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva
from . import utils
from seminar import utils , treelib
from . unicodecsv import UnicodeWriter
from . forms import PrihlaskaForm , LoginForm , ProfileEditForm
from seminar . forms import PrihlaskaForm , LoginForm , ProfileEditForm
import seminar . forms as f
from datetime import timedelta , date , datetime
@ -84,131 +83,106 @@ class ObalkovaniView(generic.ListView):
context [ ' cislo ' ] = self . cislo
return context
class TNLData ( object ) :
def __init__ ( self , anode ) :
self . node = anode
self . children = [ ]
def treenode_strom_na_seznamy ( node ) :
out = TNLData ( node )
for ch in treelib . all_children ( node ) :
outitem = treenode_strom_na_seznamy ( ch )
out . children . append ( outitem )
return out
def AktualniZadaniView ( request ) :
nastaveni = get_object_or_404 ( Nastaveni )
verejne = nastaveni . aktualni_cislo . verejne ( )
problemy = Problem . objects . filter ( cislo_zadani = nastaveni . aktualni_cislo ) . filter ( stav = ' zadany ' )
ulohy = problemy . filter ( typ = ' uloha ' ) . order_by ( ' kod ' )
serialy = problemy . filter ( typ = ' serial ' ) . order_by ( ' kod ' )
jednorazove_problemy = [ ulohy , serialy ]
return render ( request , ' seminar/zadani/AktualniZadani.html ' ,
{ ' nastaveni ' : nastaveni ,
' jednorazove_problemy ' : jednorazove_problemy ,
' temata ' : verejna_temata ( nastaveni . aktualni_rocnik ) ,
' verejne ' : verejne ,
} ,
)
class TreeNodeView ( generic . DetailView ) :
model = s . TreeNode
template_name = ' seminar/treenode.html '
def ZadaniTemataView ( request ) :
nastaveni = get_object_or_404 ( Nastaveni )
temata = verejna_temata ( nastaveni . aktualni_rocnik )
for t in temata :
if request . user . is_staff :
t . prispevky = t . prispevek_set . filter ( problem = t )
else :
t . prispevky = t . prispevek_set . filter ( problem = t , zverejnit = True )
return render ( request , ' seminar/zadani/Temata.html ' ,
{
' temata ' : temata ,
}
)
def get_context_data ( self , * * kwargs ) :
context = super ( ) . get_context_data ( * * kwargs )
context [ ' tnldata ' ] = treenode_strom_na_seznamy ( self . object )
return context
# TODO Napsat tuto funkci znovu rekurzivně podle Jethrorad. Potom se podívat, jak lehce se dá modifikovat pro Rozcestník. Pokud lehce, rozšířit ji. Pokud složitě - použít tuhle
def vytahniZLesaSeznam ( tematko , koren , pouze_zajimave = False ) :
returnVal = [ ]
stack = [ ]
stack . append ( ( koren . first_child , 0 , False ) ) #Tuple of node, depth and relevance
while len ( stack ) > 0 :
wn , wd , wr = stack . pop ( )
if wn . succ != None :
stack . append ( ( wn . succ , wd , wr ) )
if isinstance ( wn , s . TemaVCisleNode ) :
print ( " TEMA " )
print ( wn . tema . id )
print ( tematko . id )
if wn . tema . id == tematko . id :
returnVal . append ( ( posledni_cislo , 0 ) )
print ( " PRIDANO " )
wr = True
wd = 1
if wn . srolovatelne :
tagOpen = s . Text ( na_web = " Otevírací srolovací tag " )
tagOpenNode = s . TextNode ( text = tagOpen )
tagClose = s . Text ( na_web = " Zavírací srolovací tag " )
tagCloseNode = s . TextNode ( text = tagClose )
stack . append ( ( tagCloseNode , wd , True ) )
if wn . first_child != None :
stack . append ( ( wn . first_child , wd + 1 , wr ) )
if isinstance ( wn , s . CisloNode ) :
posledni_cislo = wn
print ( wn )
if wr :
print ( " ZAJIMAVE " )
if pouze_zajimave :
if not wn . zajimave :
continue
returnVal . append ( ( wn , wd ) )
return returnVal
def TematkoView ( request , rocnik , tematko ) :
nastaveni = s . Nastaveni . objects . first ( )
rocnik_object = s . Rocnik . objects . filter ( rocnik = rocnik )
tematko_object = s . Tema . objects . filter ( rocnik = rocnik_object [ 0 ] , kod = tematko )
seznam = vytahniZLesaSeznam ( tematko_object [ 0 ] , nastaveni . aktualni_rocnik ( ) . rocniknode )
for node , depth in seznam :
if node . isinstance ( node , s . KonferaNode ) :
raise Exception ( " Not implemented yet " )
if node . isinstance ( node , s . PohadkaNode ) : # Mohu ignorovat, má pod sebou
pass
return render ( request , ' seminar/tematka/toaletak.html ' , { } )
def TemataRozcestnikView ( request ) :
print ( " ============================================= " )
nastaveni = s . Nastaveni . objects . first ( )
tematka_objects = s . Tema . objects . filter ( rocnik = nastaveni . aktualni_rocnik ( ) )
tematka = [ ] #List tematka obsahuje pro kazde tematko object a list vsech TemaVCisleNodu - implementované pomocí slovníku
for tematko_object in tematka_objects :
print ( " AKTUALNI TEMATKO " )
print ( tematko_object . id )
odkazy = vytahniZLesaSeznam ( tematko_object , nastaveni . aktualni_rocnik ( ) . rocniknode , pouze_zajimave = True ) #Odkazy jsou tuply (node, depth) v listu
print ( odkazy )
cisla = [ ] # List tuplů (nazev cisla, list odkazů)
vcisle = [ ]
cislo = None
for odkaz in odkazy :
if odkaz [ 1 ] == 0 :
if cislo != None :
cisla . append ( ( cislo , vcisle ) )
cislo = ( odkaz [ 0 ] . getOdkazStr ( ) , odkaz [ 0 ] . getOdkaz ( ) )
vcisle = [ ]
else :
print ( odkaz [ 0 ] . getOdkaz ( ) )
vcisle . append ( ( odkaz [ 0 ] . getOdkazStr ( ) , odkaz [ 0 ] . getOdkaz ( ) ) )
if cislo != None :
cisla . append ( ( cislo , vcisle ) )
print ( cisla )
tematka . append ( {
" kod " : tematko_object . kod ,
" nazev " : tematko_object . nazev ,
" abstrakt " : tematko_object . abstrakt ,
" obrazek " : tematko_object . obrazek ,
" cisla " : cisla
} )
return render ( request , ' seminar/tematka/rozcestnik.html ' , { " tematka " : tematka , " rocnik " : nastaveni . aktualni_rocnik ( ) . rocnik } )
class AktualniZadaniView ( TreeNodeView ) :
def get_object ( self ) :
nastaveni = get_object_or_404 ( Nastaveni )
return nastaveni . aktualni_cislo . cislonode
def get_context_data ( self , * * kwargs ) :
nastaveni = get_object_or_404 ( Nastaveni )
context = super ( ) . get_context_data ( * * kwargs )
verejne = nastaveni . aktualni_cislo . verejne ( )
context [ ' verejne ' ] = verejne
return context
#def ZadaniTemataView(request):
# nastaveni = get_object_or_404(Nastaveni)
# temata = verejna_temata(nastaveni.aktualni_rocnik)
# for t in temata:
# if request.user.is_staff:
# t.prispevky = t.prispevek_set.filter(problem=t)
# else:
# t.prispevky = t.prispevek_set.filter(problem=t, zverejnit=True)
# return render(request, 'seminar/zadani/Temata.html',
# {
# 'temata': temata,
# }
# )
#
#
#
#def TematkoView(request, rocnik, tematko):
# nastaveni = s.Nastaveni.objects.first()
# rocnik_object = s.Rocnik.objects.filter(rocnik=rocnik)
# tematko_object = s.Tema.objects.filter(rocnik=rocnik_object[0], kod=tematko)
# seznam = vytahniZLesaSeznam(tematko_object[0], nastaveni.aktualni_rocnik().rocniknode)
# for node, depth in seznam:
# if node.isinstance(node, s.KonferaNode):
# raise Exception("Not implemented yet")
# if node.isinstance(node, s.PohadkaNode): # Mohu ignorovat, má pod sebou
# pass
#
# return render(request, 'seminar/tematka/toaletak.html', {})
#
#
#def TemataRozcestnikView(request):
# print("=============================================")
# nastaveni = s.Nastaveni.objects.first()
# tematka_objects = s.Tema.objects.filter(rocnik=nastaveni.aktualni_rocnik())
# tematka = [] #List tematka obsahuje pro kazde tematko object a list vsech TemaVCisleNodu - implementované pomocí slovníku
# for tematko_object in tematka_objects:
# print("AKTUALNI TEMATKO")
# print(tematko_object.id)
# odkazy = vytahniZLesaSeznam(tematko_object, nastaveni.aktualni_rocnik().rocniknode, pouze_zajimave = True) #Odkazy jsou tuply (node, depth) v listu
# print(odkazy)
# cisla = [] # List tuplů (nazev cisla, list odkazů)
# vcisle = []
# cislo = None
# for odkaz in odkazy:
# if odkaz[1] == 0:
# if cislo != None:
# cisla.append((cislo, vcisle))
# cislo = (odkaz[0].getOdkazStr(), odkaz[0].getOdkaz())
# vcisle = []
# else:
# print(odkaz[0].getOdkaz())
# vcisle.append((odkaz[0].getOdkazStr(), odkaz[0].getOdkaz()))
# if cislo != None:
# cisla.append((cislo, vcisle))
#
# print(cisla)
# tematka.append({
# "kod" : tematko_object.kod,
# "nazev" : tematko_object.nazev,
# "abstrakt" : tematko_object.abstrakt,
# "obrazek": tematko_object.obrazek,
# "cisla" : cisla
# })
# return render(request, 'seminar/tematka/rozcestnik.html', {"tematka": tematka, "rocnik" : nastaveni.aktualni_rocnik().rocnik})
#
#def ZadaniAktualniVysledkovkaView(request):
# nastaveni = get_object_or_404(Nastaveni)
@ -429,27 +403,34 @@ def sloupec_s_poradim(seznam_s_body):
aktualni_poradi = aktualni_poradi + velikost_skupiny
return sloupec_s_poradim
# spočítá součet bodů získaných daným řešitelem za zadaný problém a všechny jeho podproblémy
def __soucet_resitele_problemu ( problem , resitel , cislo , soucet ) :
# sečteme body za daný problém přes všechna řešení daného problému
# od daného řešitele
reseni_resitele = problem . hodnoceni_set . filter ( reseni__resitele = resitel ,
cislo_body = cislo )
# XXX chyba na řádku výše - řešení může mít více řešitelů, asi chceme contains
# nebo in
for r in reseni_resitele :
soucet + = r . body
# a přičteme k tomu hodnocení všech podproblémů
for p in problem . podproblem . all ( ) :
# i přes jméno by to měla být množina jeho podproblémů
soucet + = __soucet_resitele_problemu ( p , resitel , soucet )
return soucet
# spočítá součet všech bodů ze všech podproblémů daného problému daného řešitele
def body_resitele_problemu_v_cisle ( problem , resitel , cislo ) :
# probably FIXED: nezohledňuje číslo, do kterého se body počítají
return __soucet_resitele_problemu ( problem , resitel , cislo , 0 )
## spočítá součet bodů získaných daným řešitelem za zadaný problém a všechny jeho podproblémy
#def __soucet_resitele_problemu(problem, resitel, cislo, soucet):
# # sečteme body za daný problém přes všechna řešení daného problému
# # od daného řešitele
# reseni_resitele = s.Reseni_Resitele.objects.filter(resitele=resitel)
# hodnoceni_resitele = problem.hodnoceni.filter(reseni__in=reseni_resitele,
# cislo_body=cislo)
# # XXX chyba na řádku výše - řešení může mít více řešitelů, asi chceme contains
# # nebo in
# for r in hodnoceni_resitele:
# soucet += r.body
#
# # a přičteme k tomu hodnocení všech podproblémů
# for p in problem.podproblem.all():
# # i přes jméno by to měla být množina jeho podproblémů
# soucet += __soucet_resitele_problemu(p, resitel, soucet)
# return soucet
## spočítá součet všech bodů ze všech podproblémů daného problému daného řešitele
#def body_resitele_problemu_v_cisle(problem, resitel, cislo):
# # probably FIXED: nezohledňuje číslo, do kterého se body počítají
# return __soucet_resitele_problemu(problem, resitel, cislo, 0)
# pro daný problém vrátí jeho nejvyšší nadproblém
def hlavni_problem ( problem ) :
while not ( problem . nadproblem == None ) :
problem = problem . nadproblem
return problem
# vrátí list všech problémů s body v daném čísle, které již nemají nadproblém
def hlavni_problemy_cisla ( cislo ) :
@ -464,9 +445,7 @@ def hlavni_problemy_cisla(cislo):
# (mají vlastní sloupeček ve výsledkovce, nemají nadproblém)
hlavni_problemy = [ ]
for p in problemy :
while not ( p . nadproblem == None ) :
p = p . nadproblem
hlavni_problemy . append ( p )
hlavni_problemy . append ( hlavni_problem ( p ) )
# zunikátnění
hlavni_problemy_set = set ( hlavni_problemy )
@ -475,38 +454,83 @@ def hlavni_problemy_cisla(cislo):
return hlavni_problemy
def body_resitele_odjakziva ( resitel ) :
body = 0
resitelova_hodnoceni = Hodnoceni . objects . select_related ( ' body ' ) . all ( ) . filter ( reseni_resitele = resitel )
# TODO: v radku nahore chceme _in nebo _contains
for hodnoceni in resitelova_hodnoceni :
body = body + hodnoceni . body
return body
# vrátí slovník řešitel:body obsahující počty bodů zadaných řešitelů za daný ročník
# POZOR! Aktuálně počítá jen za posledních 10 let od zadaného ročníku
def body_resitelu_odjakziva ( rocnik , resitele ) :
body_odjakziva = { }
for r in resitele :
body_odjakziva [ str ( r . id ) ] = 0
# # Body za posledních 10 let je dobrá aproximace pro naše potřeby (výsledkovka
# # s aktivními řešiteli)
#
# body_pred_roky = []
# for i in range(0, 10):
# body_pred_roky.append(body_resitelu_za_rocnik(rocnik-i, resitele))
#
# for r in resitele:
# for i in range(0,10):
# body_odjakziva[str(r.id)] += body_pred_roky[i][str(r.id)]
# Nasledující řešení je sice správné, ale moc pomalé:
for res in Reseni . objects . prefetch_related ( ' resitele ' , ' hodnoceni_set ' ) . all ( ) :
for r in res . resitele . all ( ) :
# daný řešitel nemusí být v naší podmnožině
if r not in resitele : continue
for hodn in res . hodnoceni_set . all ( ) :
pricti_body ( body_odjakziva , r , hodn . body )
return body_odjakziva
# vrátí slovník řešitel:body obsahující počty bodů zadaných řešitelů za daný ročník
def body_resitelu_za_rocnik ( rocnik , aktivni_resitele ) :
body_za_rocnik = { }
# inicializujeme na 0 pro všechny aktivní řešitele
for ar in aktivni_resitele :
body_za_rocnik [ str ( ar . id ) ] = 0
# spočítáme body řešitelům přes všechna řešení s hodnocením v daném ročníku
reseni = Reseni . objects . prefetch_related ( ' resitele ' , ' hodnoceni_set ' ) . filter ( hodnoceni__cislo_body__rocnik = rocnik )
for res in reseni :
for resitel in res . resitele . all ( ) :
for hodn in res . hodnoceni_set . all ( ) :
pricti_body ( body_za_rocnik , resitel , hodn . body )
return body_za_rocnik
#def body_resitele_odjakziva(resitel):
# body = 0
# resitelova_hodnoceni = Hodnoceni.objects.select_related('body').all().filter(reseni_resitele=resitel)
# # TODO: v radku nahore chceme _in nebo _contains
# for hodnoceni in resitelova_hodnoceni:
# body = body + hodnoceni.body
# return body
# spočítá součet všech bodů řešitele za dané číslo
def body_resitele_v_cisle ( resitel , cislo ) :
hlavni_problemy = hlavni_problemy_cisla ( cislo )
body_resitele = 0
for h in hlavni_problemy :
body_resitele = body_resitele + body_resitele_problemu_v_cisle ( h , resitel , cislo )
# TODO: je rozdíl mezi odevzdanou úlohou za 0 a tím, když řešitel nic neodevzdal
# řešit přes kontrolu velikosti množiny řešení daného problému do daného čísla?
# Tady to ale nevadí, tady se počítá součet za číslo.
return body_resitele
#def body_resitele_v_cisle(resitel, cislo) :
# hlavni_problemy = hlavni_problemy_cisla(cislo )
# body_resitele = 0
# for h in hlavni_problemy :
# body_resitele = body_resitele + body_resitele_problemu_v_cisle(h, resitel, cislo )
# # TODO: je rozdíl mezi odevzdanou úlohou za 0 a tím, když řešitel nic neodevzdal
# # řešit přes kontrolu velikosti množiny řešení daného problému do daného čísla?
# # Tady to ale nevadí, tady se počítá součet za číslo.
# return body_resitele
# spočítá součet všech bodů řešitele za daný rok (nebo jen do daného čísla včetně)
def body_resitele_v_rocniku ( resitel , rocnik , do_cisla = None ) :
# pokud do_cisla=None, tak do posledního čísla v ročníku
# do_cisla je objekt Cislo
cisla = rocnik . cisla . all ( ) # funkce vrátí pole objektů
# Cislo už lexikograficky setřízené, viz models
body = 0
for cislo in cisla :
if cislo . poradi == do_cisla . poradi : break
# druhá část zaručuje, že máme výsledky do daného čísla včetně
body = body + body_resitele_v_cisle ( resitel , cislo )
return body
#def body_resitele_v_rocniku(resitel, rocnik, do_cisla=None):
# # pokud do_cisla=None, tak do posledního čísla v ročníku
# # do_cisla je objekt Cislo
# cisla = rocnik.cisla.all() # funkce vrátí pole objektů
# # Cislo už lexikograficky setřízené, viz models
# body = 0
# for cislo in cisla:
# if cislo.poradi == do_cisla.poradi: break
# # druhá část zaručuje, že máme výsledky do daného čísla včetně
# body = body + body_resitele_v_cisle(resitel, cislo)
# return body
# TODO: předělat na nový model
#def vysledkovka_rocniku(rocnik, jen_verejne=True):
# """Přebírá ročník (např. context["rocnik"]) a vrací výsledkovou listinu ve
# formě vhodné pro šablonu "seminar/vysledkovka_rocniku.html"
@ -588,7 +612,8 @@ class RocnikView(generic.DetailView):
#context['vysledkovka'] = vysledkovka_rocniku(context["rocnik"])
#context['vysledkovka_s_neverejnymi'] = vysledkovka_rocniku(context["rocnik"], jen_verejne=False)
context [ ' temata_v_rocniku ' ] = verejna_temata ( context [ " rocnik " ] )
#context['temata_v_rocniku'] = verejna_temata(context["rocnik"])
# FIXME: opravit vylistování témat v ročníku
return context
@ -612,19 +637,31 @@ class ProblemView(generic.DetailView):
return context
class VysledkyResitele ( object ) :
""" Pro daného řešitele ukládá počet bodů za jednotlivé úlohy a celkový
počet bodů za konkrétní ročník do daného čísla a za dané číslo . """
class Radek Vysledkov ky( object ) :
""" 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 ) . """
def __init__ ( self , resitel , cislo , rocnik ) :
def __init__ ( self , poradi , resitel , body_problemy_sezn ,
body_cislo , body_rocnik , body_odjakziva ) :
self . resitel = resitel
self . cislo = cislo
self . body_cislo = body_resitele_v_cisle ( resitel , cislo )
self . body = [ ]
self . rocnik = rocnik
self . body_rocnik = body_resitele_v_rocniku ( resitel , rocnik , cislo )
self . body_celkem_odjakziva = resitel . vsechny_body ( )
self . poradi = 0
self . body_cislo = body_cislo
self . body_rocnik = body_rocnik
self . body_celkem_odjakziva = body_odjakziva
self . poradi = poradi
self . body_problemy_sezn = body_problemy_sezn
self . titul = resitel . get_titul ( body_odjakziva )
# přiřazuje danému řešiteli body do slovníku
def pricti_body ( slovnik , resitel , body ) :
# testujeme na None (""), pokud je to první řešení
# daného řešitele, předěláme na 0
# (v dalším kroku přičteme reálný počet bodů),
# rozlišujeme tím mezi 0 a neodevzdaným řešením
if slovnik [ str ( resitel . id ) ] == " " :
slovnik [ str ( resitel . id ) ] = 0
slovnik [ str ( resitel . id ) ] + = body
class CisloView ( generic . DetailView ) :
model = Cislo
@ -648,48 +685,101 @@ class CisloView(generic.DetailView):
def get_context_data ( self , * * kwargs ) :
context = super ( CisloView , self ) . get_context_data ( * * kwargs )
## TODO upravit dle nového modelu
cislo = context [ ' cislo ' ]
hlavni_problemy = hlavni_problemy_cisla ( cislo )
# 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 jednotlivé řešitele (slovník slovníků hlavních problémů)
hlavni_problemy_slovnik = { }
for hp in hlavni_problemy :
hlavni_problemy_slovnik [ str ( hp . id ) ] = { }
## TODO dostat pro tyto problémy součet v daném čísle pro daného řešitele
## TODO možná chytřeji vybírat aktivní řešitele
## chceme letos něco poslal
aktivni_resitele = Resitel . objects . filter (
rok_maturity__gte = cislo . rocnik . druhy_rok ( ) )
# 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
aktivni_resitele = list ( Resitel . objects . filter (
rok_maturity__gte = cislo . rocnik . druhy_rok ( ) ) )
# TODO: zkusit hodnoceni__rocnik...
#.filter(hodnoceni_set__rocnik__eq=cislo_rocnik)
radky_vysledkovky = [ ]
# zakládání prázdných záznamů pro řešitele
cislobody = { }
for ar in aktivni_resitele :
# získáme výsledky řešitele - součty přes číslo a ročník
vr = VysledkyResitele ( ar , cislo , cislo . rocnik )
# řešitele převedeme na řetězec pomocí unikátního id
cislobody [ str ( ar . id ) ] = " "
for hp in hlavni_problemy :
vr . body . append (
body_resitele_problemu_v_cisle ( hp , ar , cislo ) )
radky_vysledkovky . append ( vr )
slovnik = hlavni_problemy_slovnik [ str ( hp . id ) ]
slovnik [ str ( ar . id ) ] = " "
# vezmeme všechna řešení s body do daného čísla
reseni_do_cisla = Reseni . objects . prefetch_related ( ' problem ' , ' resitele ' , ' hodnoceni_set ' ) . filter ( hodnoceni__cislo_body = cislo )
# 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
for reseni in reseni_do_cisla :
# řešení může řešit více problémů
for prob in list ( reseni . problem . all ( ) ) :
nadproblem = hlavni_problem ( prob )
nadproblem_slovnik = hlavni_problemy_slovnik [ str ( nadproblem . id ) ]
# a více hodnocení
for hodn in list ( reseni . hodnoceni_set . all ( ) ) :
body = hodn . body
# a více řešitelů
for resitel in list ( reseni . resitele . all ( ) ) :
pricti_body ( cislobody , resitel , body )
pricti_body ( nadproblem_slovnik , resitel , body )
# setřídíme řádky výsledkovky/objekty VysledkyResitele podle bodů
radky_vysledkovky . sort ( key = lambda vr : vr . body_rocnik , reverse = True )
# zeptáme se na dvojice (řešitel, body) za ročník a setřídíme sestupně
resitel_rocnikbody_slov = body_resitelu_za_rocnik ( cislo . rocnik , aktivni_resitele )
resitel_rocnikbody_sezn = sorted ( resitel_rocnikbody_slov . items ( ) ,
key = lambda x : x [ 1 ] , reverse = True )
# generujeme sloupec s pořadím pomocí stejně zvané funkce
pocty_bodu = [ rv . body_rocnik for rv in radky_vysledkovky ]
sloupec_poradi = sloupec_s_poradim ( pocty_bodu )
# získáme body odjakživa
resitel_odjakzivabody_slov = body_resitelu_odjakziva ( cislo . rocnik . druhy_rok ( ) ,
aktivni_resitele )
# každému řádku výsledkovky přidáme jeho pořadí
i = 0
for rv in radky_vysledkovky :
rv . poradi = sloupec_poradi [ i ]
i = i + 1
# řešitelé setřídění podle bodů za číslo sestupně
setrizeni_resitele_id = [ dvojice [ 0 ] for dvojice in resitel_rocnikbody_sezn ]
setrizeni_resitele = [ Resitel . objects . get ( id = i ) for i in setrizeni_resitele_id ]
# vytvoříme jednotlivé sloupce výsledkovky
radky_vysledkovky = [ ]
odjakziva_body = [ ]
rocnik_body = [ ]
cislo_body = [ ]
hlavni_problemy_body = [ ]
for ar_id in setrizeni_resitele_id :
# vytáhneme ze slovníků body pro daného řešitele
odjakziva_body . append ( resitel_odjakzivabody_slov [ ar_id ] )
rocnik_body . append ( resitel_rocnikbody_slov [ ar_id ] )
cislo_body . append ( cislobody [ ar_id ] )
problemy = [ ]
for hp in hlavni_problemy :
problemy . append ( hlavni_problemy_slovnik [ str ( hp . id ) ] [ ar_id ] )
hlavni_problemy_body . append ( problemy )
print ( " {} : body za problémy - {} , číslobody - {} , ročníkbody - {} , odjakživabody - " . format ( ar_id , problemy , cislobody [ ar_id ] , resitel_rocnikbody_slov [ ar_id ] ) )
# pořadí určíme pomocí funkce, které dáme celkové body za ročník vzestupně
poradi = sloupec_s_poradim ( rocnik_body )
radky_vysledkovky = [ ]
for i in range ( 0 , len ( setrizeni_resitele_id ) ) :
radek = RadekVysledkovky ( poradi [ i ] , setrizeni_resitele [ i ] ,
hlavni_problemy_body [ i ] , cislo_body [ i ] , rocnik_body [ i ] ,
odjakziva_body [ i ] )
radky_vysledkovky . append ( radek )
print ( " Přikládám {} -tý řádek. " . format ( i ) )
print ( " Následuje předávání do kontextu. " )
# vytahané informace předáváme do kontextu
context [ ' cislo ' ] = cislo
context [ ' radky_vysledkovky ' ] = radky_vysledkovky
context [ ' problemy ' ] = hlavni_problemy
# context['v_cisle_zadane'] = TODO
# context['resene_problemy'] = resene_problemy
#XXX testovat
#XXX opravit to, že se nezobrazují body za jednotlivé úlohy
print ( " Předávám kontext. " )
return context
# problemy = sorted(set(r.problem for r in reseni), key=lambda x:(poradi_typu[x.typ], x.kod_v_rocniku()))
@ -917,7 +1007,7 @@ def soustredeniUcastniciExportView(request,soustredeni):
class ClankyResitelView ( generic . ListView ) :
model = Problem
template_name = ' seminar/clanky/resitelske_clanky.html '
queryset = Clanek . objects . filter ( stav = Problem . STAV_ZADANY ) . select_related ( ' cislo_zadani __rocnik ' ) . order_by ( ' -cislo_zadani __rocnik__rocnik ' , ' kod ' )
queryset = Clanek . objects . filter ( stav = Problem . STAV_ZADANY , resitelsky = True ) . select_related ( ' cislo__rocnik ' ) . order_by ( ' -cislo__rocnik__rocnik ' , ' kod ' )
# FIXME: pokud chceme orgoclanky, tak nejak zavest do modelu a podle toho odkomentovat a upravit
#class ClankyOrganizatorView(generic.ListView)<F12>:
@ -1160,6 +1250,42 @@ class AddSolutionView(LoginRequiredMixin, FormView):
form_class = f . VlozReseniForm
success_url = ' / '
class SubmitSolutionView ( LoginRequiredMixin , CreateView ) :
model = s . Reseni
template_name = ' seminar/nahraj_reseni.html '
form_class = f . NahrajReseniForm
success_url = ' / '
def get_context_data ( self , * * kwargs ) :
data = super ( ) . get_context_data ( * * kwargs )
if self . request . POST :
data [ ' prilohy ' ] = f . ReseniSPrilohamiFormSet ( self . request . POST , self . request . FILES )
else :
data [ ' prilohy ' ] = f . ReseniSPrilohamiFormSet ( )
return data
# FIXME prepsat tak, aby form_valid se volalo jen tehdy, kdyz je form i formset validni
# Inspirace: https://stackoverflow.com/questions/41599809/using-a-django-filefield-in-an-inline-formset
def form_valid ( self , form ) :
context = self . get_context_data ( )
prilohy = context [ ' prilohy ' ]
if not prilohy . is_valid ( ) :
return super ( ) . form_invalid ( form )
with transaction . atomic ( ) :
self . object = form . save ( )
self . object . resitele . add ( Resitel . objects . get ( osoba__user = self . request . user ) )
self . object . cas_doruceni = timezone . now ( )
self . object . forma = s . Reseni . FORMA_UPLOAD
self . object . save ( )
prilohy . instance = self . object
prilohy . save ( )
return HttpResponseRedirect ( self . get_success_url ( ) )
def resetPasswordView ( request ) :
pass
@ -1321,58 +1447,9 @@ def prihlaskaView(request):
return render ( request , ' seminar/prihlaska.html ' , { ' form ' : form } )
class SkolaAutocomplete ( autocomplete . Select2QuerySetView ) :
def get_queryset ( self ) :
# Don't forget to filter out results depending on the visitor !
qs = Skola . objects . all ( )
if self . q :
qs = qs . filter (
Q ( nazev__istartswith = self . q ) |
Q ( kratky_nazev__istartswith = self . q ) |
Q ( ulice__istartswith = self . q ) |
Q ( mesto__istartswith = self . q ) )
return qs
class LoginRequiredAjaxMixin ( object ) :
def dispatch ( self , request , * args , * * kwargs ) :
#if request.is_ajax() and not request.user.is_authenticated: # Pokud to otevřu jako stránku, tak se omezení neuplatní, takže to asi nechceme
if not request . user . is_authenticated :
return JsonResponse ( data = { ' results ' : [ ] , ' pagination ' : { } } , status = 401 )
return super ( LoginRequiredAjaxMixin , self ) . dispatch ( request , * args , * * kwargs )
class ResitelAutocomplete ( LoginRequiredAjaxMixin , autocomplete . Select2QuerySetView ) :
def get_queryset ( self ) :
qs = Resitel . objects . all ( )
if self . q :
qs = qs . filter (
Q ( osoba__jmeno__startswith = self . q ) |
Q ( osoba__prijmeni__startswith = self . q ) |
Q ( osoba__prezdivka__startswith = self . q )
)
return qs
# Ceka na autocomplete v3
# class OrganizatorAutocomplete(autocomplete.Select2QuerySetView):
# def get_queryset(self):
# if not self.request.user.is_authenticated():
# return Organizator.objects.none()
#
# qs = aktivniOrganizatori()
#
# if self.q:
# if self.q[0] == "!":
# qs = Organizator.objects.all()
# query = self.q[1:]
# else:
# query = self.q
# qs = qs.filter(
# Q(prezdivka__isstartswith=query)|
# Q(user__first_name__isstartswith=query)|
# Q(user__last_name__isstartswith=query))
#
# return qs
# FIXME: Tohle asi vlastně vůbec nepatří do aplikace 'seminar'
class LoginView ( auth_views . LoginView ) :