# coding:utf-8 from django.shortcuts import get_object_or_404, render from django.http import HttpResponseRedirect from django.http import HttpResponse from django.core.urlresolvers import reverse from django.views import generic from django.utils.translation import ugettext as _ from django.http import Http404 from django.db.models import Q from .models import Problem, Cislo, Reseni, Nastaveni, Rocnik, Soustredeni, Organizator, Resitel, Novinky, Soustredeni_Ucastnici from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva from . import utils from datetime import timedelta, date, datetime from itertools import groupby import tempfile import subprocess import shutil import os from django.conf import settings import unicodedata def verejna_temata(rocnik): """Vrací queryset zveřejněných témat v daném ročníku. """ return Problem.objects.filter(typ=Problem.TYP_TEMA, cislo_zadani__rocnik=rocnik, cislo_zadani__verejne_db=True).order_by('kod') 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') jednorazove_problemy = [ulohy, serialy] return render(request, 'seminar/zadani/AktualniZadani.html', {'nastaveni': nastaveni, 'jednorazove_problemy': jednorazove_problemy, 'temata': verejna_temata(nastaveni.aktualni_rocnik), }, ) def ZadaniTemataView(request): nastaveni = get_object_or_404(Nastaveni) return render(request, 'seminar/zadani/Temata.html', { 'temata': verejna_temata(nastaveni.aktualni_rocnik) } ) def ZadaniAktualniVysledkovkaView(request): nastaveni = get_object_or_404(Nastaveni) vysledkovka = vysledkovka_rocniku(nastaveni.aktualni_rocnik) vysledkovka_s_neverejnymi = vysledkovka_rocniku(nastaveni.aktualni_rocnik, jen_verejne=False) return render(request, 'seminar/zadani/AktualniVysledkovka.html', { 'nastaveni': nastaveni, 'vysledkovka': vysledkovka, 'vysledkovka_s_neverejnymi': vysledkovka_s_neverejnymi, } ) ### Titulni strana class TitulniStranaView(generic.ListView): model = Novinky template_name='seminar/titulnistrana.html' queryset = Novinky.objects.order_by('-datum')[:5] def get_context_data(self, **kwargs): context = super(TitulniStranaView, self).get_context_data(**kwargs) nastaveni = get_object_or_404(Nastaveni) cas_deadline = nastaveni.aktualni_cislo.datum_deadline try: rozdil_casu = datetime.combine(cas_deadline, datetime.max.time()) \ - datetime.now() context['cas_do_konce_dni'] = rozdil_casu.days context['cas_do_konce_hodin'] = rozdil_casu.seconds / 3600 context['cas_do_konce_minut'] = (rozdil_casu.seconds / 60) % 60 context['cas_do_konce_sekund'] = rozdil_casu.seconds % 60 context['dead'] = datetime.combine(cas_deadline, datetime.max.time()) context['ted'] = datetime.now() except: context['dead'] = None 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 += [u"{}. – {}.".format(lepsich_resitelu + 1, lepsich_resitelu + len(skupina))] + [""] * (len(skupina)-1) lepsich_resitelu += len(skupina) #pomlcka je opravdu pomlcka v unicode!!dulezite pro vysledkovku v TeXu return poradi_l 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" """ #vyberu vsechny vysledky z rocniku cisla_v_rocniku = VysledkyKCisluZaRocnik.objects.filter(cislo__rocnik=rocnik).order_by('cislo') if jen_verejne: cisla_v_rocniku = cisla_v_rocniku.filter(cislo__verejna_vysledkovka=True) #pokud žádné nejsou, výsledkovka se nezobrazí if not cisla_v_rocniku: return None #vybere vsechny vysledky z posledniho (verejneho) cisla a setridi sestupne dle bodu vysledky = list(cisla_v_rocniku.filter(cislo = cisla_v_rocniku[0].cislo).order_by('-body', 'resitel__prijmeni', 'resitel__jmeno').select_related('resitel')) class Vysledkovka: def __init__(self): self.radky = [] self.cisla = [] vysledkovka = Vysledkovka() vysledkovka.cisla = (rocnik.verejne_vysledkovky_cisla() if jen_verejne else rocnik.cisla.all().order_by('cislo')) # 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(rocnik) verejne_vysl_odjakziva = VysledkyKCisluOdjakziva.objects.filter(cislo__rocnik=rocnik, cislo=cisla_v_rocniku[0].cislo) if jen_verejne: verejne_vysl_odjakziva = verejne_vysl_odjakziva.filter(cislo__verejna_vysledkovka=True) 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 vysledkovka.cisla: if not jen_verejne or cis.verejna_vysledkovka: #seznam vysledku se spravnym rocnikem a cislem pro resitele #zobrazim jen je-li vysledkovka verejna body_za_cislo = VysledkyZaCislo.objects.filter(cislo__rocnik=rocnik).filter(cislo = cis).filter(resitel = v.resitel) if body_za_cislo: #neprazdne vysledky by mely obsahovat prave jeden vysledek v.body_cisla.append(body_za_cislo[0].body) else: #resitel nema za cislo body v.body_cisla.append(0) vysledkovka.radky.append(v) return vysledkovka 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) 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"]) return context class ProblemView(generic.DetailView): model = Problem def _je_clanek(self, problem): return problem.typ in [Problem.TYP_ORG_CLANEK, Problem.TYP_RES_CLANEK] def get_template_names(self, **kwargs): context = super(ProblemView, self).get_context_data(**kwargs) return ['seminar/archiv/problem_' + ('clanek.html' if self._je_clanek(context['problem']) else 'uloha_tema.html')] def get_context_data(self, **kwargs): context = super(ProblemView, self).get_context_data(**kwargs) if context['problem'].typ == Problem.TYP_RES_CLANEK: context['reseni'] = Reseni.objects.filter(problem=context['problem']).select_related('resitel').order_by('resitel__prijmeni') return context 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') poradi_typu = { Problem.TYP_ULOHA: 1, Problem.TYP_SERIAL: 2, Problem.TYP_ORG_CLANEK: 3, Problem.TYP_TEMA: 4, Problem.TYP_RES_CLANEK: 5 } problemy = sorted(set(r.problem for r in reseni), key=lambda x:(poradi_typu[x.typ], 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 ### Generovani obalek class CisloObalkyStruct: rocnik = None cisla = None # Vraci QuerySet aktualnich resitelu = nekdy neco poslali, ale jeste neodmaturovali def aktualniResitele(rocnik): letos = Rocnik.objects.filter(rocnik = rocnik).first() return Resitel.objects.filter(rok_maturity__gt = letos.prvni_rok) # # ALERT: pokud nekdo nema vypleny rok maturity, tak neni aktualni, protoze Karel Tesar a jini # return Resitel.objects.filter(Q(rok_maturity__gt = letos.prvni_rok)|Q(rok_maturity = None)) # 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.filter(rocnik = rocnik).first() loni.rocnik = Rocnik.objects.filter(rocnik = int(rocnik)-1).first() 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 = letos.cisla) else: problemy = Problem.objects.filter(Q(cislo_zadani = letos.cisla)|Q(cislo_zadani=loni.cisla)) resitele = aktualni_resitele.filter(reseni = Reseni.objects.filter(problem=problemy)).distinct() return resitele def cisloObalkyView(request,rocnik,cislo): return obalkyView(request,aktivniResitele(rocnik,cislo)) def obalkyView(request,resitele): tex = render(request,'seminar/archiv/obalky.tex', {'resitele': resitele}).content tempdir = tempfile.mkdtemp() with open(tempdir+"/obalky.tex","w") as texfile: # Pokud TeX chce ISO Latin, tak se da encode nastavit texfile.write(tex.decode("utf-8").encode("iso-8859-2")) shutil.copy(os.path.join(settings.STATIC_ROOT, 'seminar/lisak.eps'),tempdir) subprocess.call(["csplain","obalky.tex"],cwd = tempdir) subprocess.call(["dvipdf","obalky.dvi"],cwd = tempdir) with open(tempdir+"/obalky.pdf","rb") as pdffile: response = HttpResponse(pdffile.read(),content_type='application/pdf') shutil.rmtree(tempdir) return response ### Tituly # TODO udelat neco jako get_objects_or_404 def TitulyView(request, rocnik, cislo): rocnik_obj = Rocnik.objects.filter(rocnik = rocnik).first() resitele = Resitel.objects.filter(rok_maturity__gte = rocnik_obj.prvni_rok) cislo_obj = Cislo.objects.filter(rocnik = rocnik_obj, cislo = cislo).first() for resitel in resitele: vys = VysledkyKCisluOdjakziva.objects.filter(resitel = resitel, cislo = cislo_obj).first() if vys == None: body = 0 else: body = vys.body resitel.titul = resitel.get_titul(body) resitel.ascii = unicodedata.normalize('NFKD',resitel.jmeno+resitel.prijmeni).encode("ascii","ignore").replace(" ","") return render(request, 'seminar/archiv/tituly.tex',{'resitele': resitele}) ### 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' def soustredeniObalkyView(request,soustredeni): soustredeni = Soustredeni.objects.filter(id = soustredeni)[0] return obalkyView(request,soustredeni.ucastnici.all()) ### Články class ClankyResitelView(generic.ListView): model = Problem template_name = 'seminar/clanky/resitelske_clanky.html' queryset = Problem.objects.filter(typ=Problem.TYP_RES_CLANEK, stav=Problem.STAV_ZADANY).select_related('cislo_zadani__rocnik__rocnik').order_by('-cislo_zadani__rocnik__rocnik', 'kod') class ClankyOrganizatorView(generic.ListView): model = Problem template_name = 'seminar/clanky/organizatorske_clanky.html' queryset = Problem.objects.filter(typ=Problem.TYP_ORG_CLANEK, stav=Problem.STAV_ZADANY).select_related('cislo_zadani__rocnik__rocnik').order_by('-cislo_zadani__rocnik__rocnik', 'kod') ### 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]), })