From 464cdc29104c0da2627fb0cd7e50cd040ed1474d Mon Sep 17 00:00:00 2001 From: Anet Date: Fri, 26 Jul 2019 00:01:23 +0200 Subject: [PATCH 1/4] =?UTF-8?q?models:=20upravena=20funkce=20get=5Ftitul,?= =?UTF-8?q?=20nevy=C5=BEaduje=20po=C4=8Det=20bod=C5=AF=20a=20funkce=20vsec?= =?UTF-8?q?hny=5Fbody=20na=20po=C4=8D=C3=ADt=C3=A1n=C3=AD=20bod=C5=AF=20od?= =?UTF-8?q?jak=C5=BEiva=20views:=20rozd=C4=9Blan=C3=A1=20pr=C3=A1ce=20na?= =?UTF-8?q?=20zobrazov=C3=A1n=C3=AD=20v=C3=BDsledkovky=20=C4=8D=C3=ADsla?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- seminar/models.py | 15 ++++- seminar/views.py | 137 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 115 insertions(+), 37 deletions(-) diff --git a/seminar/models.py b/seminar/models.py index c57e8a53..a768045d 100644 --- a/seminar/models.py +++ b/seminar/models.py @@ -284,8 +284,18 @@ class Resitel(SeminarModelBase): else: return 'Z' + str(rozdil + 9) - def get_titul(self, celkove_body): - "Vrati titul podle zadaneho poctu bodu." + def vsechny_body(self): + "Spočítá body odjakživa." + vsechna_reseni = self.reseni_set.all() + vsechna_hodnoceni = Hodnoceni.objects.filter( + reseni__in=vsechna_reseni) + return sum(h.body for h in list(vsechna_hodnoceni)) + + + def get_titul(self): + "Vrati titul" + celkove_body = self.vsechny_body() + if celkove_body < 10: return '' elif celkove_body < 20: @@ -1362,7 +1372,6 @@ class Novinky(models.Model): datum = models.DateField(auto_now_add=True) text = models.TextField('Text novinky', blank=True, null=True) - obrazek = models.ImageField('Obrázek', upload_to='image_novinky/%Y/%m/%d/', null=True, blank=True) diff --git a/seminar/views.py b/seminar/views.py index 7ac0701e..226abcb2 100644 --- a/seminar/views.py +++ b/seminar/views.py @@ -14,6 +14,7 @@ from django.contrib.auth import authenticate, login from .models import Problem, Cislo, Reseni, Nastaveni, Rocnik, Soustredeni, Organizator, Resitel, Novinky, Soustredeni_Ucastnici, Pohadka, Tema, Clanek #from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva from . import utils +from .unicodecsv import UnicodeWriter from .forms import NameForm from datetime import timedelta, date, datetime @@ -34,7 +35,7 @@ import csv def verejna_temata(rocnik): """Vrací queryset zveřejněných témat v daném ročníku. """ - return Tema.objects.filter(rocnik=rocnik).order_by('kod') #FIXME Ještě je potřeba zjistit, jestli je tematko verejne. + return Problem.objects.filter(typ=Problem.TYP_TEMA, cislo_zadani__rocnik=rocnik, cislo_zadani__verejne_db=True).order_by('kod') def AktualniZadaniView(request): @@ -377,39 +378,103 @@ class ProblemView(generic.DetailView): return context -class RadekVysledkovky(object): - pass +class VysledkyResitele(object): + #resitel_jmeno = models.CharField('jméno řešitele', max_length=256) + #resitel_prijmeni = CharField('příjmení', max_length=256) -#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') + def __init__(self, jmeno, prijmeni): + resitel_jmeno = jmeno + resitel_prijmeni = prijmeni + body = {} + + def body_za_cislo(self): + return sum(body.values()) + +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 + + # 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, soucet): + # FIXME: správně je nadproblem_(typ problemu), ale to by bylo potřeba nějak + # zjistit, jaký typ nodu to vlastně je a aplikovat to ve volání funkce + + # 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__contains=resitel) + for r in reseni_resitele: + soucet += r.body + + for p in problem.nadproblem_set: + # 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 + + + def vysledky_resitele_problemu(problem, resitel, cislo): + return __soucet_resitele_problemu(problem, resitel, 0) + + + def get_context_data(self, **kwargs): + context = super(CisloView, self).get_context_data(**kwargs) + + ## TODO upravit dle nového modelu + cislo = context['cislo'] + hodnoceni = cislo.hodnoceni_set # hodnocení, která se vážou k danému číslu + + reseni = [h.reseni for h in hodnoceni] + problemy = [h.problem for h in hodnoceni] + problemy_set = set(problemy) # chceme každý problém unikátně, + problemy = (list(problemy_set)) # převedení na množinu a zpět to zaručí + + # hlavní problémy čísla + # (mají vlastní sloupeček ve výsledkovce, nemají nadproblém) + hlavni_problemy = [] + for p in problemy: + while not(p.nadproblem == None): + p = nadproblem + hlavni_problemy.append(p) + + # zunikátnění + hlavni_problemy_set = set(hlavni_problemy) + hlavni_problemy = list(hlavni_problemy_set) + + ## 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=context['rocnik'].druhy_rok()) + #.filter(hodnoceni_set__rocnik__eq=cislo_rocnik) + udaje_vysledkovky = {} + for ar in aktivni_resitele: + vr = VysledkyResitele(ar.jmeno, ar.prijmeni) + for h in hlavni_problemy: + vr.body[h.id] = vysledky_resitele_problemu(h, ar, cislo) + + 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 ú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 = { @@ -465,7 +530,11 @@ class ArchivTemataView(generic.ListView): ### Generovani vysledkovky -#class CisloVysledkovkaView(CisloView): +#class CisloVysledkovkaView(CisloView):i +# poradi | titul. jmeno prijmeni | ulohy | za cislo | celkem | odjakziva +# +# +# # model = Cislo # template_name = 'seminar/archiv/cislo_vysledkovka.tex' # #content_type = 'application/x-tex; charset=UTF8' @@ -628,10 +697,10 @@ def soustredeniUcastniciExportView(request,soustredeni): response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment; filename="ucastnici.csv"' - writer = csv.writer(response) + writer = UnicodeWriter(response) writer.writerow(["jmeno", "prijmeni", "rok_maturity", "telefon", "email", "ulice", "mesto", "psc","stat"]) for u in ucastnici: - writer.writerow([u.osoba.jmeno, u.osoba.prijmeni, str(u.rok_maturity), u.osoba.telefon, u.osoba.email, u.osoba.ulice, u.osoba.mesto, u.osoba.psc, u.osoba.stat.name]) + writer.writerow([u.jmeno, u.prijmeni, str(u.rok_maturity), u.telefon, u.email, u.ulice, u.mesto, u.psc, u.stat.name]) return response @@ -641,7 +710,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__rocnik').order_by('-cislo__rocnik__rocnik', 'kod') + queryset = Clanek.objects.filter(stav=Problem.STAV_ZADANY).select_related('cislo_zadani__rocnik').order_by('-cislo_zadani__rocnik__rocnik', 'kod') # FIXME: pokud chceme orgoclanky, tak nejak zavest do modelu a podle toho odkomentovat a upravit #class ClankyOrganizatorView(generic.ListView): From 1737e807d685836c9e4dfa76a4b029c463021f94 Mon Sep 17 00:00:00 2001 From: Anet Date: Fri, 26 Jul 2019 00:45:27 +0200 Subject: [PATCH 2/4] =?UTF-8?q?Kr=C3=A1tk=C3=A9=20pokra=C4=8Dov=C3=A1n?= =?UTF-8?q?=C3=AD=20ve=20vrt=C3=A1n=C3=AD=20se=20ve=20v=C3=BDsledkovce=20?= =?UTF-8?q?=C4=8D=C3=ADsla.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- seminar/views.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/seminar/views.py b/seminar/views.py index 04a71f64..e7fb0fda 100644 --- a/seminar/views.py +++ b/seminar/views.py @@ -379,13 +379,14 @@ class ProblemView(generic.DetailView): class VysledkyResitele(object): - #resitel_jmeno = models.CharField('jméno řešitele', max_length=256) - #resitel_prijmeni = CharField('příjmení', max_length=256) + "Pro daného řešitele ukládá počet bodů za jednotlivé úlohy a celkový + počet bodů za číslo." def __init__(self, jmeno, prijmeni): resitel_jmeno = jmeno resitel_prijmeni = prijmeni body = {} + body_cislo = 0 def body_za_cislo(self): return sum(body.values()) @@ -460,14 +461,21 @@ class CisloView(generic.DetailView): aktivni_resitele = Resitel.objects.filter( rok_maturity__gte=context['rocnik'].druhy_rok()) #.filter(hodnoceni_set__rocnik__eq=cislo_rocnik) - udaje_vysledkovky = {} + radky_vysledkovky = [] for ar in aktivni_resitele: vr = VysledkyResitele(ar.jmeno, ar.prijmeni) - for h in hlavni_problemy: - vr.body[h.id] = vysledky_resitele_problemu(h, ar, cislo) + for h in hlavni_problemy: + body = vysledky_resitele_problemu(h, ar, cislo) + vr.body[h.kod_v_rocniku] = body + vr.body_cislo = vr.body_cislo + body + radky_vysledkovky.append(vr) + + ## TODO: spočítat počet bodů řešitele v daném ročníku a seřadit je podle toho + ## TODO: možná použít tyto funkce i v RocnikVysledkovkaView (a umístit sem nebo tam)? + - vysledky = VysledkyKCisluZaRocnik.objects.filter(cislo = context['cislo']).\ - order_by('-body', 'resitel__prijmeni', 'resitel__jmeno') +# 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 From e5d67e7608d758d99e343b59b240dd23b20e3b74 Mon Sep 17 00:00:00 2001 From: Anet Date: Fri, 26 Jul 2019 12:15:55 +0200 Subject: [PATCH 3/4] Oprava views. --- seminar/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seminar/views.py b/seminar/views.py index e7fb0fda..57c85b65 100644 --- a/seminar/views.py +++ b/seminar/views.py @@ -379,8 +379,8 @@ class ProblemView(generic.DetailView): class VysledkyResitele(object): - "Pro daného řešitele ukládá počet bodů za jednotlivé úlohy a celkový - počet bodů za číslo." + """Pro daného řešitele ukládá počet bodů za jednotlivé úlohy a celkový + počet bodů za číslo.""" def __init__(self, jmeno, prijmeni): resitel_jmeno = jmeno From b1b7445409155769c12a4a1699d3ff90a8dc6a0d Mon Sep 17 00:00:00 2001 From: Anet Date: Tue, 13 Aug 2019 20:10:31 +0200 Subject: [PATCH 4/4] testutils: pridany komentar k size --- seminar/testutils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/seminar/testutils.py b/seminar/testutils.py index c0c70222..b2d06c4b 100644 --- a/seminar/testutils.py +++ b/seminar/testutils.py @@ -254,7 +254,9 @@ def gen_rocniky(last_rocnik, size): def gen_konfery(size, rnd, organizatori, resitele, soustredeni): konfery = [] - for _ in range(1, size): #FIXME Tu range si změňte jak chcete, nevím, co přesně znamená size (asi Anet?) + for _ in range(1, size): #FIXME Tu range si změňte jak chcete, nevím, co přesně znamená size (asi Anet?) + # Anet: size je parametr udávající velikost testovacích dat a dá se pomocí ní škálovat, + # kolik dat se nageneruje konfera = Konfera.objects.create( nazev=rnd.choice(['Pozorování', 'Zkoumání', 'Modelování', 'Počítání', 'Zkoušení']) + rnd.choice([' vlastností', ' jevů', ' charakteristik']) + rnd.choice([' vektorových prostorů', ' kinetické terorie látek', ' molekulární biologie', ' syntentických stromů']), anotace=lorem.paragraph(),