Web M&M
https://mam.matfyz.cz
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
323 lines
14 KiB
323 lines
14 KiB
# coding:utf-8
|
|
|
|
from django.shortcuts import get_object_or_404, render
|
|
from django.http import HttpResponseRedirect
|
|
from django.core.urlresolvers import reverse
|
|
from django.views import generic
|
|
from django.utils.translation import ugettext as _
|
|
from django.http import Http404
|
|
|
|
from .models import Problem, Cislo, Reseni, Nastaveni, Rocnik, Soustredeni, Organizator, Resitel, Novinky
|
|
from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva
|
|
from . import utils
|
|
|
|
import datetime
|
|
|
|
|
|
def AktualniZadaniView(request):
|
|
nastaveni = get_object_or_404(Nastaveni)
|
|
problemy = Problem.objects.filter(cislo_zadani=nastaveni.aktualni_cislo).filter(stav = 'zadany')
|
|
ulohy = problemy.filter(typ = 'uloha')
|
|
serialy = problemy.filter(typ = 'serial')
|
|
temata = problemy.filter(typ = 'tema')
|
|
jednorazove_problemy = [ulohy, serialy]
|
|
return render(request, 'seminar/zadani/AktualniZadani.html',
|
|
{'nastaveni': nastaveni,
|
|
'jednorazove_problemy': jednorazove_problemy,
|
|
'temata': temata,
|
|
},
|
|
)
|
|
|
|
def TemataView(request):
|
|
nastaveni = get_object_or_404(Nastaveni)
|
|
return render(request, 'seminar/zadani/Temata.html',
|
|
{
|
|
'temata': Problem.objects.filter(typ=Problem.TYP_TEMA, cislo_zadani__rocnik=nastaveni.aktualni_rocnik),
|
|
}
|
|
)
|
|
|
|
### Titulni strana
|
|
|
|
class TitulniStranaView(generic.ListView):
|
|
model = Novinky
|
|
template_name='seminar/titulnistrana.html'
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super(TitulniStranaView, self).get_context_data(**kwargs)
|
|
context['pred_2_mesici'] = (datetime.date.today() - datetime.timedelta(2*365/12)).isoformat()
|
|
#ulozi datum pred dvema mesici
|
|
#elegantneji mozne pomoci dateutil:
|
|
'''
|
|
from dateutil.relativedelta import relativedelta
|
|
|
|
date.today() + relativedelta(month=-2)
|
|
'''
|
|
return context
|
|
|
|
### Co je M&M
|
|
|
|
## Organizatori
|
|
|
|
class CojemamOrganizatoriView(generic.ListView):
|
|
model = Organizator
|
|
template_name='seminar/cojemam/organizatori.html'
|
|
queryset = Organizator.objects.filter(user__is_active=True).order_by('user__first_name')
|
|
def get_context_data(self, **kwargs):
|
|
context = super(CojemamOrganizatoriView, self).get_context_data(**kwargs)
|
|
context['aktivni'] = True
|
|
return context
|
|
|
|
class CojemamOrganizatoriStariView(generic.ListView):
|
|
model = Organizator
|
|
template_name='seminar/cojemam/organizatori.html'
|
|
queryset = Organizator.objects.filter(user__is_active=False)
|
|
|
|
### Archiv
|
|
|
|
class CislaView(generic.ListView):
|
|
model = Rocnik
|
|
template_name='seminar/archiv/cisla.html'
|
|
|
|
class RocnikView(generic.DetailView):
|
|
model = Rocnik
|
|
template_name = 'seminar/archiv/rocnik.html'
|
|
|
|
# Vlastni ziskavani objektu z databaze podle (Rocnik.rocnik)
|
|
def get_object(self, queryset=None):
|
|
if queryset is None:
|
|
queryset = self.get_queryset()
|
|
rocnik_arg = self.kwargs.get('rocnik')
|
|
queryset = queryset.filter(rocnik=rocnik_arg)
|
|
|
|
try:
|
|
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):
|
|
context = super(RocnikView, self).get_context_data(**kwargs)
|
|
|
|
cisla_v_rocniku = VysledkyKCisluZaRocnik.objects.filter(cislo__verejna_vysledkovka = True).filter(cislo__rocnik = context['rocnik']).order_by('-cislo')
|
|
#vyberu vsechny verejne vysledky z rocniku
|
|
#pokud žádné nejsou, výsledkovka se nezobrazí
|
|
if cisla_v_rocniku:
|
|
vysledky = cisla_v_rocniku.filter(cislo = cisla_v_rocniku[0].cislo).order_by('-body', 'resitel__prijmeni', 'resitel__jmeno').select_related('resitel')
|
|
#vybere vsechny vysledky z posledniho verejneho cisla a setridi sestupne dle bodu
|
|
vysledky_resitele = {}
|
|
stejne_body = {}
|
|
konec_rozmezi = {}
|
|
vysledkovka = []
|
|
posledni_body = 100000
|
|
predchozi_poradi = None
|
|
body_minule = None
|
|
|
|
for vi in range(len(vysledky)):
|
|
v = vysledky[vi]
|
|
rv = RadekVysledkovky()
|
|
rv.resitel = v.resitel
|
|
verejne_vysl_odjakziva = VysledkyKCisluOdjakziva.objects.filter(cislo__verejna_vysledkovka = True).filter(cislo__rocnik = context['rocnik']).filter(cislo = cisla_v_rocniku[0].cislo)
|
|
rv.body_odjakziva = verejne_vysl_odjakziva.filter(resitel = rv.resitel)[0].body
|
|
rv.resitel.titul = rv.resitel.get_titul(rv.body_odjakziva)
|
|
rv.resitel.rocnik = rv.resitel.rocnik(context['rocnik'])
|
|
rv.body = []*len(context['rocnik'].verejna_cisla())
|
|
#pokud pro dany rok a cislo nema resitel vysledky, ma defaultne 0
|
|
for cis in context['rocnik'].verejna_cisla():
|
|
if cis.verejna_vysledkovka:
|
|
print cis
|
|
body_za_cislo = VysledkyZaCislo.objects.filter(cislo__rocnik = context['rocnik']).filter(cislo = cis).filter(resitel = rv.resitel)
|
|
#seznam vysledku se spravnym rocnikem a cislem pro resitele
|
|
#zobrazim jen je-li vysledkovka verejna
|
|
if body_za_cislo:
|
|
rv.body.append(body_za_cislo[0].body)
|
|
#neprazdne vysledky by mely obsahovat prave jeden vysledek
|
|
else:
|
|
rv.body.append(0)
|
|
#resitel nema za cislo body
|
|
rv.poradi = ''
|
|
#defaultni poradi je prazdne - kvuli sdilenym mistum
|
|
rv.body_rocnik = v.body
|
|
rv.body_na_zacatku = rv.body_odjakziva - rv.body_rocnik
|
|
#body za minule rocniky
|
|
if posledni_body > v.body:
|
|
if stejne_body.get(posledni_body):
|
|
#pokud uz jsme predtim narazili na stejny pocet bodu
|
|
konec_rozmezi[posledni_body] = int(predchozi_poradi.poradi) + stejne_body[posledni_body]
|
|
#druha hranice sdilenych pozic - zacatek + pocet lidi se stejnymi body
|
|
predchozi_poradi.poradi = '{0}. -- {1}.'.format(predchozi_poradi.poradi,konec_rozmezi[posledni_body])
|
|
#predchozi radek ktery menil pocty bodu bude mit rozsah, pokud bylo vice radku se stejnym poctem bodu
|
|
elif predchozi_poradi :
|
|
predchozi_poradi.poradi = '{0}.'.format(predchozi_poradi.poradi)
|
|
#pokud nebyl rozsah hodnot, vypisu, pridam tecku za cislo
|
|
posledni_body = v.body
|
|
rv.poradi = vi + 1
|
|
#poradi se meni jen u resitele s rozdilnym poctem bodu nez mel minuly
|
|
predchozi_poradi = rv
|
|
elif posledni_body == v.body:
|
|
if not stejne_body.get(v.body):
|
|
stejne_body[v.body] = 1
|
|
#pokud klic neexistuje, zalozim novy pro tohoto resitele
|
|
else:
|
|
stejne_body[v.body] += 1
|
|
#rozsirim pocet resitelu sdilejici stejnou pozici
|
|
vysledky_resitele[v.resitel.id] = rv
|
|
#odkaz na radek vysledkovky patrici danemu resiteli
|
|
vysledkovka.append(rv)
|
|
|
|
context['vysledkovka'] = vysledkovka
|
|
return context
|
|
|
|
class ProblemView(generic.DetailView):
|
|
model = Problem
|
|
template_name = 'seminar/archiv/problem.html'
|
|
|
|
class RadekVysledkovky(object):
|
|
pass
|
|
|
|
class CisloView(generic.DetailView):
|
|
model = Cislo
|
|
template_name = 'seminar/archiv/cislo.html'
|
|
|
|
# Vlastni ziskavani objektu z databaze podle (Rocnik.rocnik)
|
|
def get_object(self, queryset=None):
|
|
if queryset is None:
|
|
queryset = self.get_queryset()
|
|
rocnik_arg = self.kwargs.get('rocnik')
|
|
cislo_arg = self.kwargs.get('cislo')
|
|
queryset = queryset.filter(rocnik__rocnik=rocnik_arg, cislo=cislo_arg)
|
|
|
|
try:
|
|
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):
|
|
context = super(CisloView, self).get_context_data(**kwargs)
|
|
|
|
vysledky = VysledkyKCisluZaRocnik.objects.filter(cislo = context['cislo']).order_by('-body', 'resitel__prijmeni', 'resitel__jmeno')
|
|
reseni = Reseni.objects.filter(cislo_body = context['cislo']).select_related("resitel")
|
|
|
|
# typy úloh, které se mají zobrazovat u čísla, tj. těch, které byly v čísle skutečně zadány
|
|
typy_skutecne_zadanych = [Problem.TYP_ULOHA, Problem.TYP_SERIAL, Problem.TYP_ORG_CLANEK]
|
|
v_cisle_zadane = Problem.objects.filter(cislo_zadani=context['cislo']).filter(typ__in=typy_skutecne_zadanych).order_by('cislo_reseni__cislo', 'kod')
|
|
|
|
resene_problemy = Problem.objects.filter(cislo_reseni=context['cislo']).filter(typ__in=typy_skutecne_zadanych).order_by('cislo_reseni__cislo', 'kod')
|
|
|
|
problemy = sorted(list(set([r.problem for r in reseni])), key=lambda x:(0 if x.typ==Problem.TYP_ULOHA else 1,x.kod))
|
|
#setridi problemy podle typu a poradi zadani
|
|
problem_index = {}
|
|
for i in range(len(problemy)):
|
|
problem_index[problemy[i].id] = i
|
|
#umoznuje zjistit index podle id problemu
|
|
|
|
vysledky_resitele = {}
|
|
stejne_body = {}
|
|
konec_rozmezi = {}
|
|
vysledkovka = []
|
|
posledni_body = 100000
|
|
predchozi_poradi = None
|
|
body_minule = None
|
|
|
|
for vi in range(len(vysledky)):
|
|
v = vysledky[vi]
|
|
tv = RadekVysledkovky()
|
|
tv.resitel = v.resitel
|
|
tv.resitel.titul = tv.resitel.get_titul(v.body)
|
|
tv.rocnik = tv.resitel.rocnik(context['cislo'].rocnik)
|
|
tv.vysledek = v
|
|
#odkazuje na VysledkyKCislu
|
|
tv.body = ['']*len(problemy)
|
|
#pole bodu za ulohy
|
|
tv.poradi = ''
|
|
#defaultni poradi je prazdne - kvuli sdilenym mistum
|
|
tv.body_celkem_rocnik = v.body
|
|
tv.body_celkem_odjakziva = VysledkyKCisluOdjakziva.objects.get(resitel=v.resitel, cislo=context['cislo']).body
|
|
body_cislo_q = VysledkyZaCislo.objects.filter(resitel=v.resitel, cislo=context['cislo'])
|
|
tv.body_cislo = body_cislo_q[0].body if len(body_cislo_q) > 0 else 0
|
|
tv.body_minule = tv.body_celkem_rocnik - tv.body_cislo
|
|
tv.titul=tv.resitel.get_titul(int(tv.body_celkem_odjakziva))
|
|
#pocet bodu do tohoto cisla
|
|
if posledni_body > tv.body_celkem_rocnik:
|
|
if stejne_body.get(posledni_body):
|
|
konec_rozmezi[posledni_body] = int(predchozi_poradi.poradi) + stejne_body[posledni_body]
|
|
#druha hranice sdilenych pozic - zacatek + pocet lidi se stejnymi body
|
|
predchozi_poradi.poradi = '{0}. -- {1}.'.format(predchozi_poradi.poradi,konec_rozmezi[posledni_body])
|
|
#predchozi radek ktery menil pocty bodu bude mit rozsah, pokud bylo vice radku se stejnym poctem bodu
|
|
elif predchozi_poradi :
|
|
predchozi_poradi.poradi = '{0}.'.format(predchozi_poradi.poradi)
|
|
#pokud nebyl rozsah hodnot, pridam tecku za cislo
|
|
posledni_body = tv.body_celkem_rocnik
|
|
tv.poradi = vi + 1
|
|
#poradi se meni jen u resitele s rozdilnym poctem bodu nez mel minuly
|
|
predchozi_poradi = tv
|
|
elif posledni_body == tv.body_celkem_rocnik:
|
|
if not stejne_body.get(tv.body_celkem_rocnik):
|
|
stejne_body[tv.body_celkem_rocnik] = 1
|
|
#pokud klic neexistuje, zalozim novy pro tohoto resitele
|
|
else:
|
|
stejne_body[tv.body_celkem_rocnik] += 1
|
|
#rozsirim pocet resitelu sdilejici stejnou pozici
|
|
vysledky_resitele[v.resitel.id] = tv
|
|
#odkaz na radek vysledkovky patrici danemu resiteli
|
|
vysledkovka.append(tv)
|
|
|
|
for r in reseni:
|
|
vysledky_resitele[r.resitel.id].body[problem_index[r.problem.id]] = r.body
|
|
|
|
|
|
context['vysledkovka'] = vysledkovka
|
|
context['problemy'] = problemy
|
|
context['v_cisle_zadane'] = v_cisle_zadane
|
|
context['resene_problemy'] = resene_problemy
|
|
return context
|
|
|
|
### Generovani vysledkovky
|
|
|
|
class CisloVysledkovkaView(CisloView):
|
|
model = Cislo
|
|
template_name = 'seminar/archiv/cislo_vysledkovka.tex'
|
|
#content_type = 'application/x-tex; charset=UTF8'
|
|
#umozni rovnou stahnout TeXovsky dokument
|
|
content_type = 'text/plain; charset=UTF8'
|
|
#vypise na stranku textovy obsah vyTeXane vysledkovky k okopirovani
|
|
|
|
class RocnikVysledkovkaView(RocnikView):
|
|
model = Rocnik
|
|
template_name = 'seminar/archiv/rocnik_vysledkovka.tex'
|
|
#content_type = 'application/x-tex; charset=UTF8'
|
|
#umozni rovnou stahnout TeXovsky dokument
|
|
content_type = 'text/plain; charset=UTF8'
|
|
#vypise na stranku textovy obsah vyTeXane vysledkovky k okopirovani
|
|
|
|
|
|
### Soustredeni
|
|
|
|
class SoustredeniListView(generic.ListView):
|
|
model = Soustredeni
|
|
template_name = 'seminar/soustredeni/seznam_soustredeni.html'
|
|
|
|
class SoustredeniView(generic.DetailView):
|
|
model = Soustredeni
|
|
template_name = 'seminar/archiv/soustredeni.html'
|
|
|
|
### Status
|
|
|
|
def StavDatabazeView(request):
|
|
# nastaveni = Nastaveni.objects.get()
|
|
problemy = utils.seznam_problemu()
|
|
muzi = Resitel.objects.filter(pohlavi_muz=True)
|
|
zeny = Resitel.objects.filter(pohlavi_muz=False)
|
|
return render(request, 'seminar/stav_databaze.html',
|
|
{
|
|
# 'nastaveni': nastaveni,
|
|
'problemy': problemy,
|
|
|
|
'resitele': Resitel.objects.all(),
|
|
'muzi': muzi,
|
|
'zeny': zeny,
|
|
'jmena_muzu': utils.histogram([r.jmeno for r in muzi]),
|
|
'jmena_zen': utils.histogram([r.jmeno for r in zeny]),
|
|
})
|
|
|