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.
291 lines
12 KiB
291 lines
12 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
|
|
|
|
from datetime import timedelta, date
|
|
from itertools import groupby
|
|
|
|
|
|
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').order_by('kod')
|
|
serialy = problemy.filter(typ = 'serial').order_by('kod')
|
|
temata = problemy.filter(typ = 'tema').order_by('kod')
|
|
jednorazove_problemy = [ulohy, serialy]
|
|
return render(request, 'seminar/zadani/AktualniZadani.html',
|
|
{'nastaveni': nastaveni,
|
|
'jednorazove_problemy': jednorazove_problemy,
|
|
'temata': temata,
|
|
},
|
|
)
|
|
|
|
def ZadaniTemataView(request):
|
|
nastaveni = get_object_or_404(Nastaveni)
|
|
return render(request, 'seminar/zadani/Temata.html',
|
|
{
|
|
'temata': Problem.objects.filter(typ=Problem.TYP_TEMA, stav=Problem.STAV_ZADANY, cislo_zadani__rocnik=nastaveni.aktualni_rocnik).order_by('kod'),
|
|
}
|
|
)
|
|
|
|
### Titulni strana
|
|
|
|
class TitulniStranaView(generic.ListView):
|
|
model = Novinky
|
|
template_name='seminar/titulnistrana.html'
|
|
queryset = Novinky.objects.filter(zverejneno=True).order_by('-datum')[:5]
|
|
|
|
#def get_context_data(self, **kwargs):
|
|
# context = super(TitulniStranaView, self).get_context_data(**kwargs)
|
|
# return context
|
|
|
|
class StareNovinkyView(generic.ListView):
|
|
model = Novinky
|
|
template_name = 'seminar/stare_novinky.html'
|
|
queryset = Novinky.objects.filter(zverejneno=True).order_by('-datum')
|
|
|
|
### Co je M&M
|
|
|
|
## Organizatori
|
|
|
|
class CojemamOrganizatoriView(generic.ListView):
|
|
model = Organizator
|
|
template_name='seminar/cojemam/organizatori.html'
|
|
queryset = Organizator.objects.exclude(organizuje_do_roku__isnull=False, organizuje_do_roku__lt=date.today().year).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(organizuje_do_roku__isnull=False, organizuje_do_roku__lt=date.today().year).order_by('-organizuje_do_roku')
|
|
|
|
### Archiv
|
|
|
|
class CislaView(generic.ListView):
|
|
model = Rocnik
|
|
template_name='seminar/archiv/cisla.html'
|
|
|
|
|
|
def sloupec_s_poradim(vysledky):
|
|
# počet řešitelů ve výsledkovce nad aktuálním
|
|
lepsich_resitelu = 0
|
|
|
|
poradi_l = []
|
|
# projdeme skupiny řešitelů se stejným počtem bodů
|
|
for skupina in (list(x) for _, x in groupby(vysledky, lambda x: x.body)):
|
|
|
|
# připravíme si obsahy buněk ve sloupci pořadí pro skupinu
|
|
if len(skupina) == 1:
|
|
poradi_l += ["{}.".format(lepsich_resitelu + 1)]
|
|
# je-li účastníků se stejným počtem bodů víc, pořadí (rozsah X.-Y.) je jen u prvního
|
|
else:
|
|
poradi_l += ["{}.–{}.".format(lepsich_resitelu + 1, lepsich_resitelu + len(skupina))] + [""] * (len(skupina)-1)
|
|
lepsich_resitelu += len(skupina)
|
|
|
|
return poradi_l
|
|
|
|
|
|
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 = list(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
|
|
vysledkovka = []
|
|
|
|
# doplníme některé údaje do řádků výsledkovky pro řešitele ve skupině
|
|
for poradi, v in zip(sloupec_s_poradim(vysledky), vysledky):
|
|
v.poradi = poradi
|
|
v.resitel.rocnik = v.resitel.rocnik(context['rocnik'])
|
|
|
|
verejne_vysl_odjakziva = VysledkyKCisluOdjakziva.objects.filter(cislo__verejna_vysledkovka = True).filter(cislo__rocnik = context['rocnik']).filter(cislo = cisla_v_rocniku[0].cislo)
|
|
|
|
v.body_odjakziva = verejne_vysl_odjakziva.filter(resitel = v.resitel)[0].body
|
|
v.titul = v.resitel.get_titul(v.body_odjakziva)
|
|
v.body_rocnik = v.body
|
|
v.body_cisla = []
|
|
|
|
#pokud pro dany rok a cislo nema resitel vysledky, ma defaultne 0
|
|
for cis in context['rocnik'].verejna_cisla():
|
|
if cis.verejna_vysledkovka:
|
|
body_za_cislo = VysledkyZaCislo.objects.filter(cislo__rocnik = context['rocnik']).filter(cislo = cis).filter(resitel = v.resitel)
|
|
#seznam vysledku se spravnym rocnikem a cislem pro resitele
|
|
#zobrazim jen je-li vysledkovka verejna
|
|
if body_za_cislo:
|
|
v.body_cisla.append(body_za_cislo[0].body)
|
|
#neprazdne vysledky by mely obsahovat prave jeden vysledek
|
|
else:
|
|
v.body_cisla.append(0)
|
|
#resitel nema za cislo body
|
|
|
|
vysledkovka.append(v)
|
|
|
|
temata_v_rocniku = Problem.objects.filter(typ=Problem.TYP_TEMA, cislo_zadani__rocnik=context['rocnik']).order_by('kod')
|
|
|
|
context['vysledkovka'] = vysledkovka
|
|
context['temata_v_rocniku'] = temata_v_rocniku
|
|
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('kod')
|
|
|
|
resene_problemy = Problem.objects.filter(cislo_reseni=context['cislo']).filter(typ__in=typy_skutecne_zadanych).order_by('cislo_zadani__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_v_rocniku))
|
|
#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 = {}
|
|
vysledkovka = []
|
|
|
|
# doplníme některé údaje do řádků výsledkovky pro řešitele ve skupině
|
|
for poradi, v in zip(sloupec_s_poradim(vysledky), vysledky):
|
|
v.poradi = poradi
|
|
v.body_celkem_rocnik = v.body
|
|
v.body_celkem_odjakziva = VysledkyKCisluOdjakziva.objects.get(resitel=v.resitel, cislo=context['cislo']).body
|
|
|
|
# je tady '', aby se nezobrazovala 0, pokud se řešitel o řešení úlohy ani nepokusil
|
|
v.body_ulohy = [''] * len(problemy)
|
|
|
|
v.titul = v.resitel.get_titul(v.body_celkem_odjakziva)
|
|
|
|
body_cislo_q = VysledkyZaCislo.objects.filter(resitel=v.resitel, cislo=context['cislo'])
|
|
v.body_cislo = body_cislo_q[0].body if body_cislo_q else 0
|
|
|
|
vysledkovka.append(v)
|
|
|
|
# připravíme si odkaz na řádek, abychom do něj mohli doplnit body za jednotlivé úlohy
|
|
vysledky_resitele[v.resitel.id] = v
|
|
|
|
# za každé řešení doplníme k příslušnému řešiteli a úloze body
|
|
for r in reseni:
|
|
vysledky_resitele[r.resitel.id].body_ulohy[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
|
|
|
|
class ArchivTemataView(generic.ListView):
|
|
model = Problem
|
|
template_name = 'seminar/archiv/temata.html'
|
|
queryset = Problem.objects.filter(typ=Problem.TYP_TEMA, stav=Problem.STAV_ZADANY).select_related('cislo_zadani__rocnik__rocnik').order_by('-cislo_zadani__rocnik__rocnik', 'kod')
|
|
|
|
### 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]),
|
|
})
|
|
|