Rozstřílení seminářové aplikace #60
split
into master
1 week ago
@ -0,0 +1,3 @@ |
|||||
|
""" |
||||
|
Obsahuje vše okolo novinek (zpráv „Co je nového?“ na titulní straně). |
||||
|
""" |
@ -0,0 +1,27 @@ |
|||||
|
import logging |
||||
|
|
||||
|
from .models import Novinky |
||||
|
|
||||
|
logger = logging.getLogger(__name__) |
||||
|
|
||||
|
|
||||
|
def gen_novinky(rnd, organizatori): |
||||
|
logger.info('Generuji novinky...') |
||||
|
|
||||
|
jake = ["zábavné", "veselé", "dobrodružné", "skvělé"] |
||||
|
co = ["soustředění", "Fyziklání", "víkendové setkání"] |
||||
|
kde = ["na Šumavě", "v Praze", "u Plzně", "na Marsu"] |
||||
|
kdy = ["Zítra bude", "10. 10. 2020 bude", "V prosinci bude", "V létě bude"] |
||||
|
|
||||
|
for i in range(5): |
||||
|
text_novinky = " ".join([ |
||||
|
rnd.choice(kdy), rnd.choice(kde), |
||||
|
rnd.choice(jake), rnd.choice(co), |
||||
|
]) |
||||
|
novinka = Novinky.objects.create( |
||||
|
id=i, autor=rnd.choice(organizatori), |
||||
|
text=(text_novinky+", těšíme se na vás!"), |
||||
|
zverejneno=rnd.choice([True, False]), |
||||
|
) |
||||
|
novinka.save() |
||||
|
return |
@ -0,0 +1,7 @@ |
|||||
|
from django.urls import path |
||||
|
|
||||
|
from .views import StareNovinkyView |
||||
|
|
||||
|
urlpatterns = [ |
||||
|
path('stare-novinky/', StareNovinkyView.as_view(), name='stare_novinky'), |
||||
|
] |
@ -0,0 +1,23 @@ |
|||||
|
from django.views import generic |
||||
|
|
||||
|
from .models import Novinky |
||||
|
|
||||
|
|
||||
|
def spravne_novinky(request): |
||||
|
""" |
||||
|
Vrátí správný QuerySet novinek, tedy ten, který daný uživatel smí vidět. |
||||
|
Tj. Organizátorům všechny, ostatním jen veřejné |
||||
|
""" |
||||
|
user = request.user |
||||
|
# Využíváme líné vyhodnocování QuerySetů |
||||
|
qs = Novinky.objects.all() |
||||
|
if not user.je_org: |
||||
|
qs = qs.filter(zverejneno=True) |
||||
|
return qs.order_by('-datum') |
||||
|
|
||||
|
|
||||
|
class StareNovinkyView(generic.ListView): |
||||
|
template_name = 'novinky/stare_novinky.html' |
||||
|
|
||||
|
def get_queryset(self): |
||||
|
return spravne_novinky(self.request) |
@ -0,0 +1,40 @@ |
|||||
|
import datetime |
||||
|
import random |
||||
|
|
||||
|
from seminar.models.odevzdavatko import Reseni, Hodnoceni |
||||
|
|
||||
|
|
||||
|
def gen_reseni_ulohy(rnd, cisla, uloha, pocet_resitelu, poradi_cisla, resitele_cisla, resitele): |
||||
|
pocet_reseni = rnd.randint(pocet_resitelu//4, pocet_resitelu * 4) |
||||
|
# generujeme náhodný počet řešení vzhledem k počtu řešitelů čísla |
||||
|
for _ in range(pocet_reseni): |
||||
|
#print("Generuji {}-té řešení".format(reseni)) |
||||
|
if rnd.randint(1, 10) == 1: |
||||
|
# cca desetina řešení od více řešitelů |
||||
|
res_vyber = rnd.sample(resitele_cisla, rnd.randint(2, 5)) |
||||
|
else: |
||||
|
res_vyber = rnd.sample(resitele_cisla, 1) |
||||
|
if resitele[0] in res_vyber: # speciální řešitel, který nemá žádné body |
||||
|
res_vyber.remove(resitele[0]) |
||||
|
|
||||
|
# Vytvoření řešení. |
||||
|
if uloha.cislo_zadani.zlomovy_deadline_pro_papirove_cislo() is not None: |
||||
|
# combine, abychom dostali plný čas a ne jen datum |
||||
|
cas_doruceni = uloha.cislo_zadani.deadline_v_cisle.first().deadline - datetime.timedelta(days=random.randint(0, 40)) - datetime.timedelta(minutes=random.randint(0, 60*24)) |
||||
|
# astimezone, protože jinak vyhazuje warning o nenastavené TZ |
||||
|
res = Reseni.objects.create(forma=rnd.choice(Reseni.FORMA_CHOICES)[0], cas_doruceni=cas_doruceni.astimezone(datetime.timezone.utc)) |
||||
|
else: |
||||
|
res = Reseni.objects.create(forma=rnd.choice(Reseni.FORMA_CHOICES)[0]) |
||||
|
# Problém a řešitele přiřadíme později, ManyToManyField |
||||
|
# se nedá vyplnit v create(). |
||||
|
res.resitele.set(res_vyber) |
||||
|
res.save() |
||||
|
|
||||
|
# Vytvoření hodnocení. |
||||
|
hod = Hodnoceni.objects.create( |
||||
|
body=rnd.randint(0, uloha.max_body), |
||||
|
cislo_body=cisla[poradi_cisla - 1], |
||||
|
reseni=res, |
||||
|
problem=uloha |
||||
|
) |
||||
|
return |
@ -0,0 +1,11 @@ |
|||||
|
import decimal |
||||
|
|
||||
|
|
||||
|
def vzorecek_na_prepocet(body, resitelu): |
||||
|
""" Vzoreček na přepočet plných bodů na parciálni, když má řešení více řešitelů. """ |
||||
|
return body * 3 / (resitelu + 2) |
||||
|
|
||||
|
|
||||
|
def inverze_vzorecku_na_prepocet(body: decimal.Decimal, resitelu) -> decimal.Decimal: |
||||
|
""" Vzoreček na přepočet parciálních bodů na plné, když má řešení více řešitelů. """ |
||||
|
return round(body * (resitelu + 2) / 3, 1) |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
@ -0,0 +1,235 @@ |
|||||
|
import datetime |
||||
|
import logging |
||||
|
import unidecode |
||||
|
|
||||
|
from django.contrib.auth.models import Permission |
||||
|
from django.contrib.auth.models import Group |
||||
|
import django.contrib.auth |
||||
|
|
||||
|
from .models import Osoba, Skola, Organizator, Resitel, Prijemce |
||||
|
|
||||
|
logger = logging.getLogger(__name__) |
||||
|
|
||||
|
User = django.contrib.auth.get_user_model() |
||||
|
|
||||
|
zlinska = None # tohle bude speciální škola, které později dodáme kontaktní osobu |
||||
|
|
||||
|
|
||||
|
# testuje unikátnost vygenerovaného jména |
||||
|
def __unikatni_jmeno(osoby, jmeno, prijmeni): |
||||
|
for os in osoby: |
||||
|
if os.jmeno == jmeno and os.prijmeni == prijmeni: |
||||
|
return 0 |
||||
|
else: |
||||
|
return 1 |
||||
|
|
||||
|
|
||||
|
def gen_osoby(rnd, size): |
||||
|
logger.info('Generuji osoby (size={})...'.format(size)) |
||||
|
|
||||
|
jmena_m = ['Aleš', 'Tomáš', 'Martin', 'Jakub', 'Petr', 'Lukáš', 'Cyril', 'Pavel Karel'] |
||||
|
jmena_f = ['Eva', 'Karolína', 'Zuzana', 'Sylvie', 'Iva', 'Jana', 'Marie', 'Marta Iva', 'Shu Shan'] |
||||
|
prijmeni_m = ['Novotný', 'Svoboda', 'Pecha', 'Kořen', 'Holan', 'Uhlíř', 'Chytráček', 'Pokora', 'Koch', 'Szegedy', 'Rudý', "von Neumann", "d'Este"] |
||||
|
prijmeni_f = ['Novotná', 'Svobodová', 'Machová', 'Zelená', 'Yu-Xin', 'Mlsná', 'Dubná', 'Mrkvová', 'Suchá', 'Lovelace', 'Holcová', 'Rui', "Nováčková Tydlitátová"] |
||||
|
prezdivky = ['Kaki', 'Hurdur', 'Maracuja', 'Bobbo', "", "", "", "", "", "", "", 'Riki', 'Sapa', "", '', '---', 'Koko'] |
||||
|
domain = ['example.com', 'dolujeme.eu', 'mff.cuni.cz', 'strcprstskrzkrk.cz', 'british.co.uk', 'splachni.to', 'haha.org'] |
||||
|
seznam_ulic = ['Krátká', 'Vlhká', 'Jungmanova', '17. listopadu', '4. října', 'Roztocká', 'Forstova', 'Generála Františka Janouška', 'Náměstí Války', 'Svratecké náměstí', 'Zelená lhota', 'Z Plynu', 'K Jezeru', 'U Kocourkova', 'Uštěpačná', 'Ostrorepská', 'Zubří'] |
||||
|
seznam_mest = ['Praha', 'Brno', 'Ostrava', 'Horní Jelení', 'Dolní Zábrdovice', 'Prdelkov', 'Stará myslivna', 'Kocourkov', 'Šalingrad', 'Medvědí hora', 'Basilej', 'Unterschiedlich', 'Old York', 'Lancastershire', 'Vóloďháza'] |
||||
|
|
||||
|
osoby = [] |
||||
|
# 30 je náhodná konstanta, size je použité na víc místech a |
||||
|
# říká, jak velká asi chceme testovací data |
||||
|
for i in range(30 * size): |
||||
|
pohlavi_idx = rnd.randint(0, 2) # 2 = nebinární |
||||
|
osloveni = [Osoba.OSLOVENI_MUZSKE, Osoba.OSLOVENI_ZENSKE, Osoba.OSLOVENI_ZADNE][pohlavi_idx] |
||||
|
jmeno = rnd.choice([jmena_m, jmena_f, jmena_m + jmena_f][pohlavi_idx]) |
||||
|
prijmeni = rnd.choice([prijmeni_m, prijmeni_f, prijmeni_m + prijmeni_f][pohlavi_idx]) |
||||
|
if pohlavi_idx == 2: logger.debug(f'Testdata: nebinární osoba: {jmeno} {prijmeni}.') |
||||
|
pokusy = 0 |
||||
|
max_pokusy = 120*size |
||||
|
while not __unikatni_jmeno and pokusy < max_pokusy: |
||||
|
# pokud jméno a příjmení není unikátní, zkoušíme generovat nová |
||||
|
# do daného limitu (abychom se nezacyklili do nekonečna při málo jménech a příjmeních |
||||
|
# ze kterých se generuje) |
||||
|
jmeno = rnd.choice([jmena_m, jmena_f, jmena_m + jmena_f][pohlavi_idx]) |
||||
|
prijmeni = rnd.choice([prijmeni_m, prijmeni_f, prijmeni_m + prijmeni_f][pohlavi_idx]) |
||||
|
pokusy += 1 |
||||
|
if pokusy >= max_pokusy: |
||||
|
print("Chyba, na danou velikost testovacích dat příliš málo možných jmen a příjmení") |
||||
|
exit() |
||||
|
prezdivka = rnd.choice(prezdivky) |
||||
|
email = "@".join([unidecode.unidecode(jmeno), rnd.choice(domain)]) |
||||
|
telefon = "".join([str(rnd.choice([k for k in range(10)])) for _ in range(9)]) |
||||
|
narozeni = datetime.date( |
||||
|
rnd.randint(1980, datetime.datetime.now().year), |
||||
|
rnd.randint(1, 12), |
||||
|
rnd.randint(1, 28) |
||||
|
) |
||||
|
ulic = rnd.choice(seznam_ulic) |
||||
|
cp = rnd.randint(1, 99) |
||||
|
ulice = " ".join([ulic, str(cp)]) |
||||
|
mesto = rnd.choice(seznam_mest) |
||||
|
psc = "".join([str(rnd.choice([k for k in range(10)])) for _ in range(5)]) |
||||
|
|
||||
|
osoby.append(Osoba.objects.create( |
||||
|
jmeno=jmeno, prijmeni=prijmeni, |
||||
|
prezdivka=prezdivka, osloveni=osloveni, |
||||
|
email=email, telefon=telefon, |
||||
|
datum_narozeni=narozeni, |
||||
|
ulice=ulice, mesto=mesto, psc=psc, |
||||
|
datum_registrace=datetime.date( |
||||
|
rnd.randint(2019, 2029), rnd.randint(1, 12), rnd.randint(1, 28) |
||||
|
) |
||||
|
)) |
||||
|
|
||||
|
# TODO pridat foto male a velke. Jak? |
||||
|
# Pavel tvrdí, že to necháme a přidáme až do adminu |
||||
|
|
||||
|
return osoby |
||||
|
|
||||
|
|
||||
|
def gen_skoly(): # TODO někdy to přepsat, aby jich bylo více |
||||
|
logger.info('Generuji školy...') |
||||
|
|
||||
|
skoly = [] |
||||
|
prvnizs = Skola.objects.create( |
||||
|
mesto='Praha', stat='CZ', psc='101 00', |
||||
|
ulice='Krátká 5', nazev='První ZŠ', je_zs=True, je_ss=False, |
||||
|
) |
||||
|
skoly.append(prvnizs) |
||||
|
skoly.append(Skola.objects.create( |
||||
|
mesto='Praha', stat='CZ', psc='101 00', |
||||
|
ulice='Krátká 5', nazev='První SŠ', je_zs=False, je_ss=True, |
||||
|
)) |
||||
|
skoly.append(Skola.objects.create( |
||||
|
mesto='Praha', stat='CZ', psc='102 00', |
||||
|
ulice='Dlouhá 5', nazev='Druhá SŠ', je_zs=False, je_ss=True, |
||||
|
)) |
||||
|
skoly.append(Skola.objects.create( |
||||
|
mesto='Praha', stat='CZ', psc='103 00', |
||||
|
ulice='Široká 3', nazev='Třetí SŠ a ZŠ', je_zs=True, je_ss=True, |
||||
|
)) |
||||
|
skoly.append(Skola.objects.create( |
||||
|
mesto='Ostrava', stat='CZ', psc='700 00', |
||||
|
ulice='Hluboká 42', nazev='Hutní gympl', je_zs=False, je_ss=True, |
||||
|
)) |
||||
|
skoly.append(Skola.objects.create( |
||||
|
mesto='Humenné', stat='SK', psc='012 34', |
||||
|
ulice='Pltká 1', nazev='Sredná škuola', je_zs=False, je_ss=True, |
||||
|
)) |
||||
|
global zlinska |
||||
|
zlinska = Skola.objects.create( |
||||
|
mesto='Zlín', stat='CZ', psc='76001', |
||||
|
ulice='náměstí T.G. Masaryka 2734-9', |
||||
|
nazev='Gymnázium a Střední jazyková škola s právem SJZ', |
||||
|
kratky_nazev="GaSJŠspSJZ", je_zs=True, je_ss=True, |
||||
|
) |
||||
|
skoly.append(zlinska) |
||||
|
return skoly |
||||
|
|
||||
|
|
||||
|
def gen_resitele(rnd, osoby, skoly): |
||||
|
logger.info('Generuji řešitele...') |
||||
|
|
||||
|
resitele = [] |
||||
|
x = 0 |
||||
|
resitel_perm = Permission.objects.filter(codename__exact='resitel').first() |
||||
|
resitel_group = Group.objects.filter(name__exact='resitel').first() |
||||
|
for os in osoby: |
||||
|
rand = rnd.randint(0, 8) |
||||
|
if not (rand % 8 == 0): |
||||
|
if not os.user: |
||||
|
if x: |
||||
|
user = User.objects.create_user( |
||||
|
username='r'+str(x), email=os.email, password='r', |
||||
|
) |
||||
|
else: |
||||
|
user = User.objects.create_user( |
||||
|
username='r', email=os.email, password='r', |
||||
|
) |
||||
|
x += 1 |
||||
|
os.user = user |
||||
|
os.save() |
||||
|
os.user.user_permissions.add(resitel_perm) |
||||
|
os.user.groups.add(resitel_group) |
||||
|
resitele.append(Resitel.objects.create( |
||||
|
osoba=os, skola=rnd.choice(skoly), |
||||
|
rok_maturity=os.datum_narozeni.year + rnd.randint(18, 21), |
||||
|
zasilat=rnd.choice(Resitel.ZASILAT_CHOICES)[0], |
||||
|
)) |
||||
|
return resitele |
||||
|
|
||||
|
|
||||
|
def gen_prijemci(rnd, osoby, kolik=10): |
||||
|
logger.info('Generuji příjemce (kolik={})...'.format(kolik)) |
||||
|
prijemci = [] |
||||
|
for i in rnd.sample(osoby, kolik): |
||||
|
prijemci.append(Prijemce.objects.create(osoba=i)) |
||||
|
|
||||
|
global zlinska |
||||
|
if zlinska is not None: |
||||
|
zlinska.kontaktni_osoba=rnd.choice(osoby) |
||||
|
zlinska.save() |
||||
|
|
||||
|
return prijemci |
||||
|
|
||||
|
|
||||
|
def gen_organizatori(rnd, osoby, last_rocnik): |
||||
|
logger.info('Generuji organizátory...') |
||||
|
organizatori = [] |
||||
|
|
||||
|
|
||||
|
seznam_konicku = ["vařím", "jezdím na kole", "řeším diferenciální rovnice", "koukám z okna", "tancuji", "programuji", "jezdím vlakem", "nedělám nic"] |
||||
|
seznam_oboru = ["matematiku", "matematiku", "matematiku", "fyziku", "literaturu", "informatiku", "informatiku", "běhání dokolečka"] |
||||
|
|
||||
|
x = 0 |
||||
|
org_perm = Permission.objects.filter(codename__exact='org').first() |
||||
|
org_group = Group.objects.filter(name__exact='org').first() |
||||
|
for os in osoby: |
||||
|
rand = rnd.randint(0, 8) |
||||
|
if rand % 8 == 0: |
||||
|
pusobnost = rnd.randint(1, last_rocnik) |
||||
|
od = datetime.datetime( |
||||
|
year=1993 + pusobnost, |
||||
|
month=rnd.randint(1, 12), |
||||
|
day=rnd.randint(1, 28), |
||||
|
tzinfo=datetime.timezone.utc, |
||||
|
) |
||||
|
do = datetime.datetime( |
||||
|
year=od.year + rnd.randint(1, 6), |
||||
|
month=rnd.randint(1, 12), |
||||
|
day=rnd.randint(1, 28), |
||||
|
tzinfo=datetime.timezone.utc, |
||||
|
) |
||||
|
# aktualni organizatori jeste nemaji vyplnene organizuje_do |
||||
|
|
||||
|
# popis orga |
||||
|
konicek1 = rnd.choice(seznam_konicku) |
||||
|
konicek2 = rnd.choice(seznam_konicku) |
||||
|
obor = rnd.choice(seznam_oboru) |
||||
|
popis_orga = "Ve volném čase " + konicek1 + " a také " + konicek2 + ". Studuji " + obor + " a moc mě to baví." |
||||
|
|
||||
|
if do.year > datetime.datetime.now().year: |
||||
|
do = None |
||||
|
if not os.user: |
||||
|
if x: |
||||
|
user = User.objects.create_user( |
||||
|
username='o'+str(x), email=os.email, password='o', |
||||
|
) |
||||
|
else: |
||||
|
user = User.objects.create_user( |
||||
|
username='o', email=os.email, password='o', |
||||
|
) |
||||
|
x += 1 |
||||
|
os.user = user |
||||
|
os.save() |
||||
|
os.user.user_permissions.add(org_perm) |
||||
|
os.user.groups.add(org_group) |
||||
|
os.user.is_staff = True |
||||
|
os.user.save() |
||||
|
organizatori.append(Organizator.objects.create( |
||||
|
osoba=os, |
||||
|
organizuje_od=od, organizuje_do=do, |
||||
|
strucny_popis_organizatora=popis_orga, |
||||
|
)) |
||||
|
return organizatori |
@ -1,16 +0,0 @@ |
|||||
{% extends 'base.html' %} |
|
||||
|
|
||||
{% load humanize %} |
|
||||
{% load static %} |
|
||||
|
|
||||
|
|
||||
{% block content %} |
|
||||
|
|
||||
<div class=jakresit> |
|
||||
|
|
||||
{% include 'seminar/jakresit/jakresit_1.svg' %} |
|
||||
{% include 'seminar/jakresit/jakresit_2.svg' %} |
|
||||
{% include 'seminar/jakresit/jakresit_3.svg' %} |
|
||||
|
|
||||
</div> |
|
||||
{% endblock %} |
|
@ -1,19 +0,0 @@ |
|||||
from django import template |
|
||||
from django.utils.safestring import mark_safe |
|
||||
from datetime import datetime, timedelta |
|
||||
from mamweb.settings import TIME_ZONE |
|
||||
import logging |
|
||||
register = template.Library() |
|
||||
|
|
||||
logger = logging.getLogger(__name__) |
|
||||
|
|
||||
@register.filter(name='kratke_datum', expects_localtime=True) |
|
||||
def kratke_datum(dt): |
|
||||
# None dává None, ne-datum dává False, aby se daly použít filtry typu "default". |
|
||||
if dt is None: |
|
||||
return None |
|
||||
if not isinstance(dt, datetime): |
|
||||
logger.warning(f"Špatné volání filtru {__name__}: {dt}") |
|
||||
return False |
|
||||
out = f'<time datetime="{dt.isoformat()}" title="{dt.strftime("%d. %m. %Y %H:%M")}">{dt.day}.{dt.month}.<span style="text-decoration:overline">{dt.year%100}</time>' |
|
||||
return mark_safe(out) |
|
@ -1,910 +0,0 @@ |
|||||
import datetime |
|
||||
|
|
||||
from django.contrib.auth.models import Permission |
|
||||
from django.contrib.auth.models import Group |
|
||||
import random |
|
||||
import lorem |
|
||||
import django.contrib.auth |
|
||||
from django.db import transaction |
|
||||
import unidecode |
|
||||
import logging |
|
||||
|
|
||||
from korektury.testutils import create_test_pdf |
|
||||
from seminar.models import Skola, Resitel, Rocnik, Cislo, Deadline, Problem, Reseni, PrilohaReseni, Nastaveni, Soustredeni, Soustredeni_Ucastnici, Soustredeni_Organizatori, Osoba, Organizator, Prijemce, Tema, Uloha, Konfera, TextNode, UlohaVzorakNode, RocnikNode, CisloNode, TemaVCisleNode, Text, Hodnoceni, UlohaZadaniNode, Novinky, TreeNode |
|
||||
import seminar.models as m |
|
||||
|
|
||||
from django.contrib.flatpages.models import FlatPage |
|
||||
from django.contrib.sites.models import Site |
|
||||
from treenode.treelib import all_children, insert_last_child, all_children_of_type, create_node_after |
|
||||
|
|
||||
|
|
||||
User = django.contrib.auth.get_user_model() |
|
||||
zlinska = None # tohle bude speciální škola, které později dodáme kontaktní osobu |
|
||||
|
|
||||
logger = logging.getLogger(__name__) |
|
||||
|
|
||||
# testuje unikátnost vygenerovaného jména |
|
||||
def __unikatni_jmeno(osoby, jmeno, prijmeni): |
|
||||
for os in osoby: |
|
||||
if os.jmeno == jmeno and os.prijmeni == prijmeni: |
|
||||
return 0 |
|
||||
else: return 1 |
|
||||
|
|
||||
def gen_osoby(rnd, size): |
|
||||
logger.info('Generuji osoby (size={})...'.format(size)) |
|
||||
|
|
||||
jmena_m = ['Aleš', 'Tomáš', 'Martin', 'Jakub', 'Petr', 'Lukáš', 'Cyril', 'Pavel Karel'] |
|
||||
jmena_f = ['Eva', 'Karolína', 'Zuzana', 'Sylvie', 'Iva', 'Jana', 'Marie', |
|
||||
'Marta Iva', 'Shu Shan'] |
|
||||
prijmeni_m = ['Novotný', 'Svoboda', 'Pecha', 'Kořen', 'Holan', 'Uhlíř', 'Chytráček', |
|
||||
'Pokora', 'Koch', 'Szegedy', 'Rudý', "von Neumann", "d'Este"] |
|
||||
prijmeni_f = ['Novotná', 'Svobodová', 'Machová', 'Zelená', 'Yu-Xin', 'Mlsná', 'Dubná', |
|
||||
'Mrkvová', 'Suchá', 'Lovelace', 'Holcová', 'Rui', "Nováčková Tydlitátová"] |
|
||||
prezdivky = ['Kaki', 'Hurdur', 'Maracuja', 'Bobbo', "", "", "", "", "", |
|
||||
"", "", 'Riki', 'Sapa', "", '', '---', 'Koko'] |
|
||||
domain = ['example.com', 'dolujeme.eu', 'mff.cuni.cz', 'strcprstskrzkrk.cz', |
|
||||
'british.co.uk', 'splachni.to', 'haha.org'] |
|
||||
seznam_ulic = ['Krátká', 'Vlhká', 'Jungmanova', '17. listopadu', '4. října', 'Roztocká', |
|
||||
'Forstova', 'Generála Františka Janouška', 'Náměstí Války', |
|
||||
'Svratecké náměstí', 'Zelená lhota', 'Z Plynu', 'K Jezeru', 'U Kocourkova', |
|
||||
'Uštěpačná', 'Ostrorepská', 'Zubří'] |
|
||||
seznam_mest = ['Praha', 'Brno', 'Ostrava', 'Horní Jelení', 'Dolní Zábrdovice', 'Prdelkov', |
|
||||
'Stará myslivna', 'Kocourkov', 'Šalingrad', 'Medvědí hora', 'Basilej', |
|
||||
'Unterschiedlich', 'Old York', 'Lancastershire', 'Vóloďháza'] |
|
||||
|
|
||||
osoby = [] |
|
||||
# 30 je náhodná konstanta, size je použité na víc místech a |
|
||||
# říká, jak velká asi chceme testovací data |
|
||||
for i in range(30 * size): |
|
||||
pohlavi_idx = rnd.randint(0,2) # 2 = nebinární |
|
||||
osloveni = [Osoba.OSLOVENI_MUZSKE, Osoba.OSLOVENI_ZENSKE, Osoba.OSLOVENI_ZADNE][pohlavi_idx] |
|
||||
jmeno = rnd.choice([jmena_m, jmena_f, jmena_m + jmena_f][pohlavi_idx]) |
|
||||
prijmeni = rnd.choice([prijmeni_m, prijmeni_f, prijmeni_m + prijmeni_f][pohlavi_idx]) |
|
||||
if pohlavi_idx == 2: logger.debug(f'Testdata: nebinární osoba: {jmeno} {prijmeni}.') |
|
||||
pokusy = 0 |
|
||||
max_pokusy = 120*size |
|
||||
while (not __unikatni_jmeno and pokusy < max_pokusy): |
|
||||
# pokud jméno a příjmení není unikátní, zkoušíme generovat nová |
|
||||
# do daného limitu (abychom se nezacyklili do nekonečna při málo jménech a příjmeních |
|
||||
# ze kterých se generuje) |
|
||||
jmeno = rnd.choice([jmena_m, jmena_f, jmena_m + jmena_f][pohlavi_idx]) |
|
||||
prijmeni = rnd.choice([prijmeni_m, prijmeni_f, prijmeni_m + prijmeni_f][pohlavi_idx]) |
|
||||
pokusy = pokusy + 1 |
|
||||
if pokusy >= max_pokusy: |
|
||||
print("Chyba, na danou velikost testovacích dat příliš málo možných" |
|
||||
" jmen a příjmení") |
|
||||
exit() |
|
||||
prezdivka = rnd.choice(prezdivky) |
|
||||
email = "@".join([unidecode.unidecode(jmeno), rnd.choice(domain)]) |
|
||||
telefon = "".join([str(rnd.choice([k for k in range(10)])) for i in range(9)]) |
|
||||
narozeni = datetime.date(rnd.randint(1980, datetime.datetime.now().year), |
|
||||
rnd.randint(1, 12), rnd.randint(1, 28)) |
|
||||
ulic = rnd.choice(seznam_ulic) |
|
||||
cp = rnd.randint(1, 99) |
|
||||
ulice = " ".join([ulic, str(cp)]) |
|
||||
mesto = rnd.choice(seznam_mest) |
|
||||
psc = "".join([str(rnd.choice([k for k in range(10)])) for i in range(5)]) |
|
||||
|
|
||||
osoby.append(Osoba.objects.create(jmeno = jmeno, prijmeni = prijmeni, |
|
||||
prezdivka = prezdivka, osloveni = osloveni, email = email, |
|
||||
telefon = telefon, datum_narozeni = narozeni, ulice = ulice, |
|
||||
mesto = mesto, psc = psc, |
|
||||
datum_registrace = datetime.date(rnd.randint(2019, 2029), |
|
||||
rnd.randint(1, 12), rnd.randint(1, 28)))) |
|
||||
#TODO pridat foto male a velke. Jak? |
|
||||
# Pavel tvrdí, že to necháme a přidáme až do adminu |
|
||||
|
|
||||
return osoby |
|
||||
|
|
||||
|
|
||||
|
|
||||
def gen_skoly(): #TODO někdy to přepsat, aby jich bylo více |
|
||||
logger.info('Generuji školy...') |
|
||||
|
|
||||
skoly = [] |
|
||||
prvnizs = Skola.objects.create(mesto='Praha', stat='CZ', psc='101 00', |
|
||||
ulice='Krátká 5', nazev='První ZŠ', je_zs=True, je_ss=False) |
|
||||
skoly.append(prvnizs) |
|
||||
skoly.append(Skola.objects.create(mesto='Praha', stat='CZ', psc='101 00', |
|
||||
ulice='Krátká 5', nazev='První SŠ', je_zs=False, je_ss=True)) |
|
||||
skoly.append(Skola.objects.create(mesto='Praha', stat='CZ', psc='102 00', |
|
||||
ulice='Dlouhá 5', nazev='Druhá SŠ', je_zs=False, je_ss=True)) |
|
||||
skoly.append(Skola.objects.create(mesto='Praha', stat='CZ', psc='103 00', |
|
||||
ulice='Široká 3', nazev='Třetí SŠ a ZŠ', je_zs=True, je_ss=True)) |
|
||||
skoly.append(Skola.objects.create(mesto='Ostrava', stat='CZ', psc='700 00', |
|
||||
ulice='Hluboká 42', nazev='Hutní gympl', je_zs=False, je_ss=True)) |
|
||||
skoly.append(Skola.objects.create(mesto='Humenné', stat='SK', psc='012 34', |
|
||||
ulice='Pltká 1', nazev='Sredná škuola', je_zs=False, je_ss=True)) |
|
||||
global zlinska |
|
||||
zlinska = Skola.objects.create(mesto = 'Zlín', stat='CZ', psc='76001', |
|
||||
ulice='náměstí T.G. Masaryka 2734-9', |
|
||||
nazev='Gymnázium a Střední jazyková škola s právem SJZ', |
|
||||
kratky_nazev="GaSJŠspSJZ", je_zs=True, je_ss=True) |
|
||||
skoly.append(zlinska) |
|
||||
return skoly |
|
||||
|
|
||||
def gen_resitele(rnd, osoby, skoly): |
|
||||
logger.info('Generuji řešitele...') |
|
||||
|
|
||||
resitele = [] |
|
||||
x = 0 |
|
||||
resitel_perm = Permission.objects.filter(codename__exact='resitel').first() |
|
||||
resitel_group = Group.objects.filter(name__exact='resitel').first() |
|
||||
for os in osoby: |
|
||||
rand = rnd.randint(0, 8) |
|
||||
if not (rand % 8 == 0): |
|
||||
if not os.user: |
|
||||
if x: |
|
||||
user = User.objects.create_user(username='r'+str(x), email=os.email, password='r') |
|
||||
else: |
|
||||
user = User.objects.create_user(username='r', email=os.email, password='r') |
|
||||
x += 1 |
|
||||
os.user = user |
|
||||
os.save() |
|
||||
os.user.user_permissions.add(resitel_perm) |
|
||||
os.user.groups.add(resitel_group) |
|
||||
resitele.append(Resitel.objects.create(osoba=os, skola=rnd.choice(skoly), |
|
||||
rok_maturity=os.datum_narozeni.year + rnd.randint(18, 21), |
|
||||
zasilat=rnd.choice(Resitel.ZASILAT_CHOICES)[0])) |
|
||||
return resitele |
|
||||
|
|
||||
def gen_prijemci(rnd, osoby, kolik=10): |
|
||||
logger.info('Generuji příjemce (kolik={})...'.format(kolik)) |
|
||||
prijemci = [] |
|
||||
for i in rnd.sample(osoby, kolik): |
|
||||
prijemci.append(Prijemce.objects.create(osoba=i)) |
|
||||
return prijemci |
|
||||
|
|
||||
def gen_organizatori(rnd, osoby, last_rocnik): |
|
||||
logger.info('Generuji organizátory...') |
|
||||
organizatori = [] |
|
||||
|
|
||||
|
|
||||
seznam_konicku = ["vařím", "jezdím na kole", "řeším diferenciální rovnice", "koukám z okna", |
|
||||
"tancuji", "programuji", "jezdím vlakem", "nedělám nic"] |
|
||||
seznam_oboru = ["matematiku", "matematiku", "matematiku", "fyziku", "literaturu", |
|
||||
"informatiku", "informatiku", "běhání dokolečka"] |
|
||||
|
|
||||
x = 0 |
|
||||
org_perm = Permission.objects.filter(codename__exact='org').first() |
|
||||
org_group = Group.objects.filter(name__exact='org').first() |
|
||||
for os in osoby: |
|
||||
rand = rnd.randint(0, 8) |
|
||||
if (rand % 8 == 0): |
|
||||
pusobnost = rnd.randint(1, last_rocnik) |
|
||||
od = datetime.datetime( |
|
||||
year=1993 + pusobnost, |
|
||||
month=rnd.randint(1, 12), |
|
||||
day=rnd.randint(1, 28), |
|
||||
tzinfo=datetime.timezone.utc, |
|
||||
) |
|
||||
do = datetime.datetime( |
|
||||
year=od.year + rnd.randint(1, 6), |
|
||||
month=rnd.randint(1, 12), |
|
||||
day=rnd.randint(1, 28), |
|
||||
tzinfo=datetime.timezone.utc, |
|
||||
) |
|
||||
#aktualni organizatori jeste nemaji vyplnene organizuje_do |
|
||||
|
|
||||
#popis orga |
|
||||
konicek1 = rnd.choice(seznam_konicku) |
|
||||
konicek2 = rnd.choice(seznam_konicku) |
|
||||
obor = rnd.choice(seznam_oboru) |
|
||||
popis_orga = "Ve volném čase " + konicek1 + " a také " + konicek2 + ". Studuji " + obor + " a moc mě to baví." |
|
||||
|
|
||||
if do.year > datetime.datetime.now().year: |
|
||||
do = None |
|
||||
if not os.user: |
|
||||
if x: |
|
||||
user = User.objects.create_user(username='o'+str(x), email=os.email, password='o') |
|
||||
else: |
|
||||
user = User.objects.create_user(username='o', email=os.email, password='o') |
|
||||
x += 1 |
|
||||
os.user = user |
|
||||
os.save() |
|
||||
os.user.user_permissions.add(org_perm) |
|
||||
os.user.groups.add(org_group) |
|
||||
os.user.is_staff = True |
|
||||
os.user.save() |
|
||||
organizatori.append(Organizator.objects.create(osoba=os, |
|
||||
organizuje_od=od, organizuje_do=do, strucny_popis_organizatora = popis_orga)) |
|
||||
return organizatori |
|
||||
|
|
||||
def gen_zadani_ulohy(rnd, cisla, organizatori, pocet_oboru, poradi_cisla, poradi_problemu): |
|
||||
|
|
||||
# Proměnné pro náhodné generování názvů a zadání. |
|
||||
jaka = ["Šachová", "Černá", "Větrná", "Dlouhá", "Křehká", "Rychlá", |
|
||||
"Zákeřná", "Fyzikální"] |
|
||||
co = ["kostka", "smršť", "díra", "zrada", "toulka", "tyč", |
|
||||
"úloha", "blecha"] |
|
||||
sloveso = ["Najděte", "Spočítejte", "Zapište", "Změřte", "Odhadněte"] |
|
||||
koho = ["délku", "počet", "množství", "dílky"] |
|
||||
ceho = ["všech", "správných", "konstatních", "zelených"] |
|
||||
jmeno = ["řešení", "tahů", "čísel", "kalhot", "koulí", "hadů"] |
|
||||
kde = ["na zemi", "ve vesmíru", "ve vzduchu", "na šňůře", "v letadle"] |
|
||||
obory = ["M", "F", "I", "O", "B"] |
|
||||
|
|
||||
p = Uloha.objects.create( |
|
||||
# atributy třídy Problem |
|
||||
nazev=" ".join([rnd.choice(jaka), rnd.choice(co)]), |
|
||||
stav=Problem.STAV_ZADANY, |
|
||||
zamereni=rnd.sample(obory, pocet_oboru), |
|
||||
autor=rnd.choice(organizatori), |
|
||||
garant=rnd.choice(organizatori), |
|
||||
kod=str(poradi_problemu), |
|
||||
# atributy třídy Uloha |
|
||||
cislo_zadani=cisla[poradi_cisla-2-1], |
|
||||
cislo_reseni=cisla[poradi_cisla-1], |
|
||||
cislo_deadline=cisla[poradi_cisla-1], |
|
||||
max_body = rnd.randint(1, 8) |
|
||||
) |
|
||||
|
|
||||
text = " ".join( |
|
||||
[rnd.choice(sloveso), |
|
||||
rnd.choice(koho), |
|
||||
rnd.choice(ceho), |
|
||||
rnd.choice(jmeno), |
|
||||
rnd.choice(kde)] |
|
||||
) |
|
||||
text_zadani = Text.objects.create( |
|
||||
na_web = text, |
|
||||
do_cisla = text, |
|
||||
) |
|
||||
zad = TextNode.objects.create(text = text_zadani, root = p.cislo_zadani.rocnik.rocniknode) |
|
||||
uloha_zadani = UlohaZadaniNode.objects.create(uloha = p, first_child = zad, root = p.cislo_zadani.rocnik.rocniknode) |
|
||||
p.ulohazadaninode = uloha_zadani |
|
||||
otec_syn(cisla[poradi_cisla-2-1].cislonode, uloha_zadani) |
|
||||
|
|
||||
return p |
|
||||
|
|
||||
def gen_vzoroveho_reseni_ulohy(rnd, organizatori, uloha, pocet_opravovatelu): |
|
||||
reseni = ["to je přece jasné", "triviální", "omlouváme se," |
|
||||
"otevřený problém", "neřešitelné", "triviálně triviální", |
|
||||
"použitím věty z prvního semestru na matfyzu", |
|
||||
"jednoduše pomocí látky z druhého semestru na matfyzu", |
|
||||
"netriviální aplikace diferenciálních rovnic", "zadání je vnitřně" |
|
||||
"sporné", "nepopsatelně jednoduché", "pokud jste na to nepřišli," |
|
||||
"tak jste fakt hloupí"] |
|
||||
|
|
||||
# Generování vzorového řešení. |
|
||||
obsah = rnd.choice(reseni) |
|
||||
text_vzoraku = Text.objects.create( |
|
||||
na_web = obsah, |
|
||||
do_cisla = obsah |
|
||||
) |
|
||||
vzorak = TextNode.objects.create(text = text_vzoraku, root = uloha.cislo_zadani.rocnik.rocniknode) |
|
||||
uloha_vzorak = UlohaVzorakNode.objects.create(uloha = uloha, first_child = vzorak, root = uloha.cislo_zadani.rocnik.rocniknode) |
|
||||
uloha.ulohavzoraknode = uloha_vzorak |
|
||||
|
|
||||
uloha.opravovatele.set(rnd.sample(organizatori, pocet_opravovatelu)) |
|
||||
uloha.save() |
|
||||
return uloha_vzorak |
|
||||
|
|
||||
def gen_reseni_ulohy(rnd, cisla, uloha, pocet_resitelu, poradi_cisla, resitele_cisla, resitele): |
|
||||
|
|
||||
pocet_reseni = rnd.randint(pocet_resitelu//4, pocet_resitelu * 4) |
|
||||
# generujeme náhodný počet řešení vzhledem k počtu řešitelů čísla |
|
||||
for _ in range(pocet_reseni): |
|
||||
#print("Generuji {}-té řešení".format(reseni)) |
|
||||
if rnd.randint(1, 10) == 1: |
|
||||
# cca desetina řešení od více řešitelů |
|
||||
res_vyber = rnd.sample(resitele_cisla, |
|
||||
rnd.randint(2, 5)) |
|
||||
else: |
|
||||
res_vyber = rnd.sample(resitele_cisla, 1) |
|
||||
if resitele[0] in res_vyber: # speciální řešitel, který nemá žádné body |
|
||||
res_vyber.remove(resitele[0]) |
|
||||
|
|
||||
# Vytvoření řešení. |
|
||||
if uloha.cislo_zadani.zlomovy_deadline_pro_papirove_cislo() is not None: |
|
||||
# combine, abychom dostali plný čas a ne jen datum |
|
||||
cas_doruceni = uloha.cislo_zadani.deadline_v_cisle.first().deadline - datetime.timedelta(days=random.randint(0, 40)) - datetime.timedelta(minutes=random.randint(0, 60*24)) |
|
||||
# astimezone, protože jinak vyhazuje warning o nenastavené TZ |
|
||||
res = Reseni.objects.create(forma=rnd.choice(Reseni.FORMA_CHOICES)[0], cas_doruceni=cas_doruceni.astimezone(datetime.timezone.utc)) |
|
||||
else: |
|
||||
res = Reseni.objects.create(forma=rnd.choice(Reseni.FORMA_CHOICES)[0]) |
|
||||
# Problém a řešitele přiřadíme později, ManyToManyField |
|
||||
# se nedá vyplnit v create(). |
|
||||
res.resitele.set(res_vyber) |
|
||||
res.save() |
|
||||
|
|
||||
# Vytvoření hodnocení. |
|
||||
hod = Hodnoceni.objects.create( |
|
||||
body=rnd.randint(0, uloha.max_body), |
|
||||
cislo_body=cisla[poradi_cisla - 1], |
|
||||
reseni=res, |
|
||||
problem=uloha |
|
||||
) |
|
||||
return |
|
||||
|
|
||||
def gen_ulohy_do_cisla(rnd, organizatori, resitele, rocnik_cisla, rocniky, size): |
|
||||
logger.info('Generuji úlohy do čísla (size={})...'.format(size)) |
|
||||
|
|
||||
k = 0 |
|
||||
for rocnik in rocniky: |
|
||||
k += 1 |
|
||||
print("Generuji {}. číslo.".format(k)) |
|
||||
cisla = rocnik_cisla[k - 1] |
|
||||
for ci in range(3, len(cisla) + 1): # pro všechna čísla |
|
||||
resitele_size = round(7/8 * 30 * size) # očekáváný celkový počet řešitelů |
|
||||
poc_res = rnd.randint(resitele_size//8, resitele_size//4) |
|
||||
# dané číslo řeší něco mezi osminou a čtvrtinou všech řešitelů |
|
||||
# (náhodná hausnumera, možno změnit) |
|
||||
# účelem je, aby se řešení generovala z menší množiny řešitelů a tedy |
|
||||
# bylo více řešení od jednoho řešitele daného čísla |
|
||||
resitele_cisla = rnd.sample(resitele, poc_res) |
|
||||
for pi in range(1, ((size + 1) // 2) + 1): # počet problémů |
|
||||
|
|
||||
poc_op = rnd.randint(1, 4) # počet opravovatelů |
|
||||
poc_oboru = rnd.randint(1, 2) |
|
||||
|
|
||||
# Generování zadání úlohy a UlohaZadaniNode, |
|
||||
# přivěšení pod dané číslo |
|
||||
p = gen_zadani_ulohy(rnd, cisla, organizatori, poc_oboru, ci, pi) |
|
||||
# Generování vzorového řešení |
|
||||
uloha_vzorak = gen_vzoroveho_reseni_ulohy(rnd, organizatori, |
|
||||
p, poc_op) |
|
||||
insert_last_child(cisla[ci-1].cislonode, uloha_vzorak) |
|
||||
|
|
||||
# Generování řešení a hodnocení k úloze |
|
||||
gen_reseni_ulohy(rnd, cisla, p, poc_res, ci, |
|
||||
resitele_cisla, resitele) |
|
||||
|
|
||||
return |
|
||||
|
|
||||
def gen_soustredeni(rnd, resitele, organizatori): |
|
||||
logger.info('Generuji soustředění...') |
|
||||
|
|
||||
soustredeni = [] |
|
||||
for _ in range(1, 10): #FIXME Tu range si změňte jak chcete, nevím, co přesně znamená size (asi Anet?) |
|
||||
datum_zacatku=datetime.date(rnd.randint(2000, 2020), rnd.randint(1, 12), rnd.randint(1, 28)) |
|
||||
working_sous = Soustredeni.objects.create( |
|
||||
rocnik=Rocnik.objects.order_by('?').first(), |
|
||||
verejne_db=rnd.choice([True, False]), |
|
||||
misto=rnd.choice(['Kremrolovice', 'Indiánov', 'U zmzliny', 'Vafláreň', 'Větrník', 'Horní Rakvička', 'Dolní cheesecake']), |
|
||||
typ=rnd.choice(['jarni', 'podzimni', 'vikend']), |
|
||||
datum_zacatku=datum_zacatku, |
|
||||
datum_konce=datum_zacatku + datetime.timedelta(days=7)) |
|
||||
ucastnici = rnd.sample(resitele, min(len(resitele), 20)) |
|
||||
working_sous.ucastnici.set(ucastnici) |
|
||||
#for res in rnd.sample(resitele, min(len(resitele), 20)): |
|
||||
# Soustredeni_Ucastnici.objects.create(resitel=res, soutredeni=working_sous) |
|
||||
orgove_vyber = rnd.sample(organizatori, min(len(organizatori), 20)) |
|
||||
working_sous.organizatori.set(orgove_vyber) |
|
||||
#for org in rnd.sample(organizatori, min(len(organizatori), 20)): |
|
||||
# Soustredeni_Organizatori.objects.create(organizator=org, soutredeni=working_sous) |
|
||||
working_sous.save() |
|
||||
soustredeni.append(working_sous) |
|
||||
return soustredeni |
|
||||
|
|
||||
def gen_rocniky(last_rocnik, size): |
|
||||
logger.info('Generuji ročníky (size={})...'.format(size)) |
|
||||
|
|
||||
rocniky = [] |
|
||||
node = None |
|
||||
for ri in range(min(last_rocnik - size, 1), last_rocnik + 1): |
|
||||
rocnik = Rocnik.objects.create(prvni_rok = 1993 + ri, rocnik = ri) |
|
||||
node2 = RocnikNode.objects.create(rocnik = rocnik, succ = node) |
|
||||
rocnik.save() |
|
||||
node = node2 |
|
||||
rocniky.append(rocnik) |
|
||||
return rocniky |
|
||||
|
|
||||
def gen_konfery(size, rnd, organizatori, resitele, soustredeni): |
|
||||
logger.info('Generuji konfery (size={})...'.format(size)) |
|
||||
|
|
||||
konfery = [] |
|
||||
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(), |
|
||||
abstrakt=lorem.paragraph(), |
|
||||
garant=rnd.choice(organizatori), |
|
||||
soustredeni=rnd.choice(soustredeni), |
|
||||
typ_prezentace=rnd.choice(['veletrh', 'prezentace'])) |
|
||||
ucastnici_sous = list(konfera.soustredeni.ucastnici.all()) |
|
||||
ucastnici = rnd.sample(ucastnici_sous, min(len(ucastnici_sous), rnd.randint(3, 6))) |
|
||||
konfera.ucastnici.set(ucastnici) |
|
||||
#for res in rnd.sample(ucastnici, min(len(ucastnici), rnd.randint(3, 6))): |
|
||||
# Konfery_Ucastnici.objects.create(resitel=res, konfera=konfera) |
|
||||
konfera.save() |
|
||||
konfery.append(konfera) |
|
||||
return konfery |
|
||||
|
|
||||
def gen_cisla(rnd, rocniky): |
|
||||
logger.info('Generuji čísla...') |
|
||||
|
|
||||
rocnik_cisla = [] |
|
||||
for rocnik in rocniky: |
|
||||
otec = True |
|
||||
cisla = [] |
|
||||
cisel = rnd.randint(4, 8) |
|
||||
node = None |
|
||||
for ci in range(1, cisel + 1): |
|
||||
# první číslo vydáváme typicky okolo prázdnin |
|
||||
# (ci - 1)*2 zaručuje první číslo v červnu a všechna |
|
||||
# další po dvou měsících (což je rozumná aproximace) |
|
||||
mesic_vydani = (ci - 1)*2 + 6 |
|
||||
# celociselné dělení mi řekne, jestli to je první nebo druhý rok ročníku |
|
||||
vydano = datetime.date(rocnik.prvni_rok + mesic_vydani // 12, |
|
||||
(mesic_vydani - 1) % 12 + 1, |
|
||||
rnd.randint(1, 28)) |
|
||||
deadline = datetime.date(rocnik.prvni_rok + (mesic_vydani + 2) // 12, |
|
||||
(mesic_vydani + 1) % 12 + 1, |
|
||||
rnd.randint(1, 28)) |
|
||||
|
|
||||
cislo = Cislo.objects.create( |
|
||||
rocnik = rocnik, |
|
||||
poradi = str(ci), |
|
||||
datum_vydani=vydano, |
|
||||
verejne_db=True, |
|
||||
) |
|
||||
node2 = CisloNode.objects.get(cislo = cislo) |
|
||||
node2.succ = node |
|
||||
node2.root = rocnik.rocniknode |
|
||||
cislo.save() |
|
||||
deadline = Deadline.objects.create( |
|
||||
cislo=cislo, |
|
||||
deadline=deadline, |
|
||||
typ=Deadline.TYP_CISLA, |
|
||||
verejna_vysledkovka=True, |
|
||||
) |
|
||||
deadline.save() |
|
||||
node = node2 |
|
||||
if otec: |
|
||||
otec = False |
|
||||
rocnik.rocniknode.first_child = node |
|
||||
rocnik.save() |
|
||||
|
|
||||
cisla.append(cislo) |
|
||||
rocnik_cisla.append(cisla) |
|
||||
return rocnik_cisla |
|
||||
|
|
||||
def add_first_child(node, child): |
|
||||
node.first_child = child |
|
||||
node.save() |
|
||||
return |
|
||||
|
|
||||
def get_text(): |
|
||||
odstavec = lorem.paragraph() |
|
||||
return Text.objects.create(na_web = odstavec, do_cisla = odstavec) |
|
||||
|
|
||||
def gen_dlouhe_tema(rnd, organizatori, rocnik, nazev, obor, kod): |
|
||||
tema = Tema.objects.create( |
|
||||
nazev=nazev, |
|
||||
stav=Problem.STAV_ZADANY, |
|
||||
zamereni="M", |
|
||||
autor=rnd.choice(organizatori), |
|
||||
garant=rnd.choice(organizatori), |
|
||||
kod=str(kod), |
|
||||
tema_typ=rnd.choice(Tema.TEMA_CHOICES)[0], |
|
||||
rocnik=rocnik, |
|
||||
abstrakt = lorem.paragraph() |
|
||||
) |
|
||||
|
|
||||
# Generování struktury k tématu |
|
||||
cisla = sorted(rocnik.cisla.all(), key=lambda cislo: cislo.poradi) |
|
||||
for cislo in cisla: |
|
||||
# Přidáme TemaVCisleNode do daného čísla |
|
||||
cislo_node = cislo.cislonode |
|
||||
tema_cislo_node = TemaVCisleNode.objects.create(tema = tema, root = cislo_node.root) |
|
||||
insert_last_child(cislo_node, tema_cislo_node) |
|
||||
|
|
||||
# Přidávání obsahu do čísla |
|
||||
cast_node = m.CastNode.objects.create(nadpis = "Příspěvek k číslu {}".format(cislo.kod), root=cislo_node.root) |
|
||||
add_first_child(tema_cislo_node, cast_node) |
|
||||
|
|
||||
text_node = TextNode.objects.create(text = get_text(), root=cislo_node.root) |
|
||||
add_first_child(cast_node, text_node) |
|
||||
|
|
||||
cast_node2 = m.CastNode.objects.create(nadpis = "První podproblém", root=cislo_node.root) |
|
||||
add_first_child(text_node, cast_node2) |
|
||||
|
|
||||
text_node2 = TextNode.objects.create(text = get_text(), root=cislo_node.root) |
|
||||
add_first_child(cast_node2, text_node2) |
|
||||
|
|
||||
cast_node3 = m.CastNode.objects.create(nadpis = "Druhý podproblém", root=cislo_node.root) |
|
||||
add_first_child(text_node2, cast_node3) |
|
||||
|
|
||||
text_node3 = TextNode.objects.create(text = get_text(), root=cislo_node.root) |
|
||||
add_first_child(cast_node3, text_node3) |
|
||||
|
|
||||
cast_node4 = m.CastNode.objects.create(nadpis = "Třetí podproblém", root=cislo_node.root) |
|
||||
add_first_child(text_node3, cast_node4) |
|
||||
|
|
||||
text_node4 = TextNode.objects.create(text = get_text(), root=cislo_node.root) |
|
||||
add_first_child(cast_node3, text_node4) |
|
||||
|
|
||||
cast_node3a = m.CastNode.objects.create(nadpis = "Podproblém paralelní s " |
|
||||
"druhým podproblémem", root=cislo_node.root) |
|
||||
cast_node3.succ = cast_node3a |
|
||||
cast_node3.save() |
|
||||
|
|
||||
text_node3a = TextNode.objects.create(text = get_text(), root=cislo_node.root) |
|
||||
add_first_child(cast_node3a, text_node3a) |
|
||||
|
|
||||
# Občas přidáme mezičíslo |
|
||||
if rnd.randint(1, 3) == 1: |
|
||||
create_node_after(cislo_node, m.MezicisloNode, root=cislo_node.root) |
|
||||
mezicislo_node = cislo_node.succ |
|
||||
|
|
||||
cast_node_mezicislo = m.CastNode.objects.create( |
|
||||
nadpis = "Příspěvek k mezičíslu".format(cislo.kod), root=cislo_node.root) |
|
||||
add_first_child(mezicislo_node, cast_node_mezicislo) |
|
||||
|
|
||||
odstavec = lorem.paragraph() |
|
||||
text_mezicislo = Text.objects.create(na_web = odstavec, do_cisla = odstavec) |
|
||||
text_node_mezicislo = TextNode.objects.create(text = text_mezicislo, root=cislo_node.root) |
|
||||
add_first_child(cast_node_mezicislo, text_node_mezicislo) |
|
||||
|
|
||||
return tema |
|
||||
|
|
||||
def gen_temata(rnd, rocniky, rocnik_cisla, organizatori): |
|
||||
logger.info('Generuji témata...') |
|
||||
|
|
||||
jake = ["Hravé", "Fyzikální", "Nejlepší", "Totálně masakrální", |
|
||||
"Šokující", "Magnetické", "Modré", "Překvapivé", |
|
||||
"Plasmatické", "Novoroční"] |
|
||||
co = ["téma", "záření", "stavení", "jiskření", "jelito", |
|
||||
"drama", "kuře", "moře", "klání", "proudění", "čekání"] |
|
||||
poc_oboru = rnd.randint(1, 2) |
|
||||
|
|
||||
rocnik_temata = [] |
|
||||
# Věříme, že rocnik_cisla je pole polí čísel podle ročníků, tak si necháme dát |
|
||||
# vždycky jeden ročník a k němu příslušná čísla. |
|
||||
for rocnik, cisla in zip(rocniky, rocnik_cisla): |
|
||||
kod = 1 |
|
||||
letosni_temata = [] |
|
||||
# Do každého ročníku vymyslíme tři (zatím) témata, v každém z prvních čísel jedno |
|
||||
for zacatek_tematu in range(1, 3): |
|
||||
# Vygenerujeme téma |
|
||||
t = Tema.objects.create( |
|
||||
# atributy třídy Problem |
|
||||
nazev=" ".join([rnd.choice(jake), rnd.choice(co)]), |
|
||||
stav=Problem.STAV_ZADANY, |
|
||||
zamereni=rnd.sample(["M", "F", "I", "O", "B"], poc_oboru), |
|
||||
autor=rnd.choice(organizatori), |
|
||||
garant=rnd.choice(organizatori), |
|
||||
kod=str(kod), |
|
||||
# atributy třídy Téma |
|
||||
tema_typ=rnd.choice(Tema.TEMA_CHOICES)[0], |
|
||||
rocnik=rocnik, |
|
||||
abstrakt = "Abstrakt tematka {}".format(kod) |
|
||||
) |
|
||||
kod += 1 |
|
||||
|
|
||||
# Vymyslíme, kdy skončí |
|
||||
konec_tematu = min(rnd.randint(zacatek_tematu, 7), len(cisla)) |
|
||||
|
|
||||
# Vyrobíme TemaVCisleNody pro obsah |
|
||||
for i in range(zacatek_tematu, konec_tematu+1): |
|
||||
node = TemaVCisleNode.objects.create(tema = t,root=rocnik.rocniknode) |
|
||||
# FIXME: Není to off-by-one? |
|
||||
otec = cisla[i-1].cislonode |
|
||||
otec_syn(otec, node) |
|
||||
|
|
||||
# Vymyslíme, kdo to bude opravovat |
|
||||
poc_opravovatelu = rnd.randint(1, 3) |
|
||||
t.opravovatele.set(rnd.sample(organizatori, poc_opravovatelu)) |
|
||||
|
|
||||
# Uložíme všechno |
|
||||
t.save() |
|
||||
letosni_temata.append((zacatek_tematu, konec_tematu, t)) |
|
||||
rocnik_temata.append(letosni_temata) |
|
||||
return rocnik_temata |
|
||||
|
|
||||
def gen_ulohy_tematu(rnd, organizatori, resitele, tema, kod, cislo, cislo_se_vzorakem): |
|
||||
""" Generování úlohy k danému tématu. """ |
|
||||
|
|
||||
# Proměnné pro náhodné generování názvů a zadání. |
|
||||
jaka = ["Šachová", "Černá", "Větrná", "Dlouhá", "Křehká", "Rychlá", |
|
||||
"Zákeřná", "Fyzikální"] |
|
||||
co = ["kostka", "smršť", "díra", "zrada", "toulka", "tyč", |
|
||||
"úloha", "blecha"] |
|
||||
sloveso = ["Najděte", "Spočítejte", "Zapište", "Změřte", "Odhadněte"] |
|
||||
koho = ["délku", "počet", "množství", "dílky"] |
|
||||
ceho = ["všech", "správných", "konstatních", "zelených"] |
|
||||
jmeno = ["řešení", "tahů", "čísel", "kalhot", "koulí", "hadů"] |
|
||||
kde = ["na zemi", "ve vesmíru", "ve vzduchu", "na šňůře", "v letadle"] |
|
||||
obory = ["M", "F", "I", "O", "B"] |
|
||||
|
|
||||
uloha = Uloha.objects.create( |
|
||||
nazev=": ".join([tema.nazev, |
|
||||
"úloha {}.".format(kod)]), |
|
||||
nadproblem=tema, |
|
||||
stav=Problem.STAV_ZADANY, |
|
||||
zamereni=tema.zamereni, |
|
||||
autor=tema.autor, |
|
||||
garant=tema.garant, |
|
||||
kod=str(kod), |
|
||||
cislo_zadani=cislo, |
|
||||
cislo_reseni=cislo_se_vzorakem, |
|
||||
cislo_deadline=cislo_se_vzorakem, |
|
||||
max_body = rnd.randint(1, 8) |
|
||||
) |
|
||||
|
|
||||
# Samotný obsah následně vzniklého Textu zadání |
|
||||
obsah = " ".join( |
|
||||
[rnd.choice(sloveso), |
|
||||
rnd.choice(koho), |
|
||||
rnd.choice(ceho), |
|
||||
rnd.choice(jmeno), |
|
||||
rnd.choice(kde)] |
|
||||
) |
|
||||
text_zadani = Text.objects.create( |
|
||||
na_web = obsah, |
|
||||
do_cisla = obsah, |
|
||||
) |
|
||||
zad = TextNode.objects.create(text = text_zadani, root=tema.temavcislenode_set.first().root) |
|
||||
uloha_zadani = UlohaZadaniNode.objects.create(uloha=uloha, first_child = zad, root=tema.temavcislenode_set.first().root) |
|
||||
uloha.ulohazadaninode = uloha_zadani |
|
||||
|
|
||||
# Generování řešení a hodnocení k úloze |
|
||||
gen_reseni_ulohy(rnd, [cislo], uloha, len(resitele)//4, 1, |
|
||||
resitele, resitele) |
|
||||
|
|
||||
return uloha, uloha_zadani |
|
||||
|
|
||||
|
|
||||
def gen_ulohy_k_tematum(rnd, rocniky, rocnik_cisla, rocnik_temata, organizatori, resitele): |
|
||||
logger.info('Generuji úlohy k tématům...') |
|
||||
|
|
||||
# Ke každému ročníku si vezmeme příslušná čísla a témata |
|
||||
for rocnik, cisla, temata in zip(rocniky, rocnik_cisla, rocnik_temata): |
|
||||
# Do každého čísla nagenerujeme ke každému témátku pár úložek |
|
||||
for cislo in cisla: |
|
||||
print("Generuji úložky do {}-tého čísla".format(cislo.poradi)) |
|
||||
# Vzorák bude o dvě čísla dál |
|
||||
cislo_se_vzorakem = Cislo.objects.filter( |
|
||||
rocnik=rocnik, |
|
||||
poradi=str(int(cislo.poradi) + 2), |
|
||||
) |
|
||||
# Pokud není číslo pro vzorák, tak se dá do posledního čísla |
|
||||
# (i kdyby tam mělo být zadání i řešení...) |
|
||||
# Tohle sice umožňuje vygenerovat vzorák do čísla dávno po konci témátka, |
|
||||
# ale to nám pro jednoduchost nevadí. |
|
||||
if len(cislo_se_vzorakem) == 0: |
|
||||
cislo_se_vzorakem = cisla[-1] |
|
||||
else: |
|
||||
cislo_se_vzorakem = cislo_se_vzorakem.first() |
|
||||
|
|
||||
for tema_node in all_children_of_type(cislo.cislonode, TemaVCisleNode): |
|
||||
tema = tema_node.tema |
|
||||
|
|
||||
# Pokud už témátko skončilo, žádné úložky negenerujeme |
|
||||
# FIXME: Bylo by hezčí, kdyby se čísla předávala jako Cislo a ne |
|
||||
# jako int v té trojici (start, konec, tema) |
|
||||
if not temata[int(tema.kod)-1][1] >= int(cislo_se_vzorakem.poradi): |
|
||||
continue |
|
||||
|
|
||||
# Generujeme 1 až 4 úložky k tomuto témátku do tohoto čísla. |
|
||||
for kod in range(1, rnd.randint(1, 4)): |
|
||||
u, uz = gen_ulohy_tematu(rnd, organizatori, resitele, tema, kod, |
|
||||
cislo, cislo_se_vzorakem) |
|
||||
|
|
||||
insert_last_child(tema_node, uz) |
|
||||
|
|
||||
poc_op = rnd.randint(1, 4) |
|
||||
uvz = gen_vzoroveho_reseni_ulohy(rnd, organizatori, |
|
||||
u, poc_op) |
|
||||
|
|
||||
# Najdeme správný TemaVCisleNode pro vložení vzoráku |
|
||||
res_tema_node = None; |
|
||||
for node in all_children(cislo_se_vzorakem.cislonode): |
|
||||
if isinstance(node, TemaVCisleNode): |
|
||||
if node.tema == tema: |
|
||||
res_tema_node = node |
|
||||
if res_tema_node is None: |
|
||||
raise LookupError("Nenalezen Node pro vložení vzoráku") |
|
||||
insert_last_child(res_tema_node, uvz) |
|
||||
u.save() |
|
||||
return |
|
||||
|
|
||||
def gen_novinky(rnd, organizatori): |
|
||||
logger.info('Generuji novinky...') |
|
||||
|
|
||||
|
|
||||
jake = ["zábavné", "veselé", "dobrodružné", "skvělé"] |
|
||||
co = ["soustředění", "Fyziklání", "víkendové setkání"] |
|
||||
kde = ["na Šumavě", "v Praze", "u Plzně", "na Marsu"] |
|
||||
kdy = ["Zítra bude", "10. 10. 2020 bude", "V prosinci bude", "V létě bude"] |
|
||||
|
|
||||
for i in range(5): |
|
||||
text_novinky = " ".join([rnd.choice(kdy), rnd.choice(kde), rnd.choice(jake), |
|
||||
rnd.choice(co)]) |
|
||||
novinka = Novinky.objects.create(id=i,autor=rnd.choice(organizatori), |
|
||||
text=(text_novinky+", těšíme se na vás!"),zverejneno=rnd.choice([True,False])) |
|
||||
novinka.save() |
|
||||
return |
|
||||
|
|
||||
def otec_syn(otec, syn): |
|
||||
bratr = otec.first_child |
|
||||
syn.succ = bratr |
|
||||
otec.first_child = syn |
|
||||
syn.save() |
|
||||
otec.save() |
|
||||
|
|
||||
def gen_clanek(rnd, organizatori, resitele): |
|
||||
logger.info("Generuji článek do čísla 22.2") |
|
||||
clanek = m.Clanek.objects.create( |
|
||||
nazev="Článek o Lorem ipsum", |
|
||||
nadproblem=None, |
|
||||
stav='vyreseny', |
|
||||
zamereni=['I'], |
|
||||
garant=rnd.choice(organizatori), |
|
||||
kod='cl', |
|
||||
) |
|
||||
clanek.save() |
|
||||
|
|
||||
reseni = m.Reseni.objects.create( |
|
||||
zverejneno=True, |
|
||||
) |
|
||||
reseni.resitele.add(rnd.choice(resitele)) |
|
||||
reseni.save() |
|
||||
|
|
||||
cislo = m.Cislo.objects.get(rocnik__rocnik=22, poradi=2) |
|
||||
cislonode = cislo.cislonode |
|
||||
|
|
||||
hodnoceni = m.Hodnoceni.objects.create( |
|
||||
body=15.0, |
|
||||
cislo_body=cislo, |
|
||||
reseni=reseni, |
|
||||
problem=clanek, |
|
||||
) |
|
||||
hodnoceni.save() |
|
||||
|
|
||||
reseninode = m.ReseniNode.objects.create( |
|
||||
reseni=reseni |
|
||||
) |
|
||||
reseninode.save() |
|
||||
|
|
||||
# Bude to celý text |
|
||||
reseni.text_cely = reseninode |
|
||||
reseni.save() |
|
||||
|
|
||||
from treenode.treelib import insert_last_child, create_child |
|
||||
insert_last_child(cislonode, reseninode) |
|
||||
|
|
||||
# Vyrobíme nějaký obsah |
|
||||
# FIXME: Ten, kdo vymyslel TreeLib (mj. týž, kdo psal tenhle kód), |
|
||||
# nevyrobil vhodnou funkci, takže to postavíme pozpátku pomocí create_child |
|
||||
# (které vyrábí _prvního_ syna) |
|
||||
create_child(reseninode, m.CastNode, nadpis="Lorem ipsum") |
|
||||
# Taky ten člověk nevyrobil vracení nových věcí... |
|
||||
castnode = reseninode.first_child |
|
||||
|
|
||||
# Úvodní odstaveček |
|
||||
obsah = "Tohle je zamyšlení o textu lorem ipsum. Začneme a skončíme ukázkou." |
|
||||
text = m.Text.objects.create( |
|
||||
na_web=obsah, |
|
||||
do_cisla=obsah, |
|
||||
) |
|
||||
text.save() |
|
||||
create_child(reseninode, m.TextNode, text=text) |
|
||||
|
|
||||
# Několik odstavců lorem ipsum |
|
||||
for _ in range(rnd.randint(3, 7)): |
|
||||
lipsum = lorem.paragraph() |
|
||||
text = m.Text.objects.create( |
|
||||
na_web=lipsum, |
|
||||
do_cisla=lipsum, |
|
||||
) |
|
||||
text.save() |
|
||||
create_child(castnode, m.TextNode, text=text) |
|
||||
logger.info(f"Článek vygenerován (reseni={reseni.id}, treenode={reseninode.id})") |
|
||||
|
|
||||
|
|
||||
|
|
||||
@transaction.atomic |
|
||||
def create_test_data(size = 6, rnd = None): |
|
||||
logger.info('Vyrábím testovací data (size={})...'.format(size)) |
|
||||
|
|
||||
assert size >= 1 |
|
||||
# pevna pseudo-nahodnost |
|
||||
rnd = rnd or random.Random(x=42) |
|
||||
|
|
||||
# static URL stranky |
|
||||
# FIXME: nakopirovat sem vsechny z produkcni databaze |
|
||||
s = Site.objects.filter(name="example.com") |
|
||||
f = FlatPage.objects.create(url="/", title="Seminář M&M", |
|
||||
content = "<p>Vítejte na stránce semináře MaM!</p>") |
|
||||
print(s) |
|
||||
f.sites.add(s[0]) |
|
||||
f.save() |
|
||||
|
|
||||
# users |
|
||||
admin = User.objects.create_superuser(username='admin', email='', password='admin') |
|
||||
os_admin = Osoba.objects.create( |
|
||||
user=admin, jmeno='admin', prijmeni='admin', |
|
||||
prezdivka='admin', osloveni='', email='admin@admin.admin', |
|
||||
telefon='123 456 789', datum_narozeni=datetime.date(2000, 1, 1), |
|
||||
ulice='admin', mesto='admin', psc='100 00', |
|
||||
datum_registrace=datetime.date(2020, 9, 6) |
|
||||
) |
|
||||
or_admin = Organizator.objects.create( |
|
||||
osoba=os_admin, organizuje_od=None, organizuje_do=None, |
|
||||
strucny_popis_organizatora="Organizátor k uživateli Admin" |
|
||||
) |
|
||||
|
|
||||
usernames = ['anet', 'bara', 'cyril', 'david', 'eva', 'filip'] |
|
||||
users = [] |
|
||||
for usr in usernames[:size]: |
|
||||
u = User.objects.create_user(username=usr, password=usr) |
|
||||
u.first_name = usr.capitalize() |
|
||||
u.save() |
|
||||
users.append(u) |
|
||||
print(users) |
|
||||
|
|
||||
# skoly |
|
||||
skoly = gen_skoly() |
|
||||
|
|
||||
# osoby |
|
||||
osoby = gen_osoby(rnd, size) |
|
||||
|
|
||||
# resitele a organizatori |
|
||||
last_rocnik = 25 |
|
||||
organizatori = gen_organizatori(rnd, osoby, last_rocnik) |
|
||||
resitele = gen_resitele(rnd, osoby, skoly) |
|
||||
|
|
||||
#generování novinek |
|
||||
novinky = gen_novinky(rnd, organizatori) |
|
||||
|
|
||||
# prijemci |
|
||||
prijemci = gen_prijemci(rnd, osoby) |
|
||||
|
|
||||
global zlinska |
|
||||
zlinska.kontaktni_osoba=rnd.choice(osoby) |
|
||||
zlinska.save() |
|
||||
|
|
||||
# rocniky |
|
||||
rocniky = gen_rocniky(last_rocnik, size) |
|
||||
|
|
||||
# cisla |
|
||||
# rocnik_cisla je pole polí čísel (typ Cislo), vnitřní pole odpovídají jednotlivým ročníkům. |
|
||||
rocnik_cisla = gen_cisla(rnd, rocniky) |
|
||||
|
|
||||
# generování obyčejných úloh do čísel |
|
||||
gen_ulohy_do_cisla(rnd, organizatori, resitele, rocnik_cisla, rocniky, size) |
|
||||
|
|
||||
# generování témat, zatím v prvních třech číslech po jednom |
|
||||
# FIXME: více témat |
|
||||
# rocnik_temata je pole polí trojic (první číslo :int, poslední číslo :int, téma:Tema), přičemž každé vnitřní pole odpovídá ročníku a FIXME: je to takhle fuj a když to někdo vidí poprvé, tak je z toho smutný, protože vůbec neví, co se děje a co má čekat. |
|
||||
rocnik_temata = gen_temata(rnd, rocniky, rocnik_cisla, organizatori) |
|
||||
|
|
||||
rocnik = Rocnik.objects.filter(rocnik = 23).first() |
|
||||
dlouhe_tema = gen_dlouhe_tema(rnd, organizatori, rocnik, "Strašně dlouhé téma", |
|
||||
"MFI", 8) |
|
||||
|
|
||||
# generování úloh k tématům ve všech číslech |
|
||||
gen_ulohy_k_tematum(rnd, rocniky, rocnik_cisla, rocnik_temata, organizatori, resitele) |
|
||||
|
|
||||
#generování soustředění |
|
||||
soustredeni = gen_soustredeni(rnd, resitele, organizatori) |
|
||||
|
|
||||
#generování konfer |
|
||||
konfery = gen_konfery(size, rnd, organizatori, resitele, soustredeni) |
|
||||
|
|
||||
# vytvoreni pdf ke korekturam |
|
||||
create_test_pdf(rnd, organizatori) |
|
||||
|
|
||||
# TODO: nastavi správně, kolik se čeho generuje, aby rozsahy přibližně odpovídaly |
|
||||
# FIXME: misto typu ruzne typy objektu a vnoreni do sebe (Tom nechápe, co je tímto fixme míněno) |
|
||||
# TODO: vytvorit temata s ruznymi vlakny |
|
||||
# TODO: nagenerovat starsim rocnikum pohadku |
|
||||
# TODO: nagenerovat články |
|
||||
# TODO: vecpat obrázky všude, kde to jde |
|
||||
# TODO: mezičíslo node |
|
||||
# TODO: přidat ke konferám řešení a dát je do čísel |
|
||||
|
|
||||
# Dohackované vytvoření jednoho článku |
|
||||
gen_clanek(rnd, organizatori, resitele) |
|
||||
|
|
||||
# TODO: přidat články včetně zařazení do struktury treenodů, |
|
||||
# a následně otestovat konsistency check databáze z utils.py |
|
||||
# pomocí stránky /stav |
|
||||
|
|
||||
# obecné nastavení semináře, musí být už přidané ročníky a čísla, jinak se nastaví divně |
|
||||
nastaveni = Nastaveni.objects.create( |
|
||||
aktualni_cislo = Cislo.objects.all()[1]) |
|
@ -1,387 +0,0 @@ |
|||||
import datetime |
|
||||
import decimal |
|
||||
|
|
||||
from django.contrib.auth import get_user_model |
|
||||
from django.contrib.auth.decorators import permission_required, \ |
|
||||
user_passes_test |
|
||||
from django import views as DjangoViews |
|
||||
|
|
||||
from django.db import transaction |
|
||||
|
|
||||
from django.contrib.auth.models import AnonymousUser |
|
||||
from django.contrib.contenttypes.models import ContentType |
|
||||
from django.core.exceptions import ObjectDoesNotExist |
|
||||
|
|
||||
import logging |
|
||||
|
|
||||
import seminar.models as m |
|
||||
import treenode.treelib as t |
|
||||
|
|
||||
logger = logging.getLogger(__name__) |
|
||||
|
|
||||
org_required = permission_required('auth.org') |
|
||||
resitel_required = permission_required('auth.resitel') |
|
||||
|
|
||||
|
|
||||
# inspirováno django.contrib.auth.decorators permission_required |
|
||||
def check_perms(user): |
|
||||
if user.has_perms(('auth.resitel',)): |
|
||||
return True |
|
||||
if user.has_perms(('auth.org',)): |
|
||||
return True |
|
||||
return False |
|
||||
|
|
||||
|
|
||||
resitel_or_org_required = user_passes_test(check_perms) |
|
||||
|
|
||||
User = get_user_model() |
|
||||
# Není to úplně hezké, ale budeme doufat, že to je funkční... |
|
||||
User.je_org = property(lambda self: self.has_perm('auth.org')) |
|
||||
User.je_resitel = property(lambda self: self.has_perm('auth.resitel')) |
|
||||
AnonymousUser.je_org = False |
|
||||
AnonymousUser.je_resitel = False |
|
||||
|
|
||||
|
|
||||
def vzorecek_na_prepocet(body, resitelu): |
|
||||
""" Vzoreček na přepočet plných bodů na parciálni, když má řešení více řešitelů. """ |
|
||||
return body * 3 / (resitelu + 2) |
|
||||
|
|
||||
|
|
||||
def inverze_vzorecku_na_prepocet(body: decimal.Decimal, resitelu) -> decimal.Decimal: |
|
||||
""" Vzoreček na přepočet parciálních bodů na plné, když má řešení více řešitelů. """ |
|
||||
return round(body * (resitelu + 2) / 3, 1) |
|
||||
|
|
||||
|
|
||||
def histogram(seznam): |
|
||||
d = {} |
|
||||
for i in seznam: |
|
||||
if i not in d: |
|
||||
d[i] = 0 |
|
||||
d[i] += 1 |
|
||||
return d |
|
||||
|
|
||||
# Pozor: zarovnáno velmi netradičně pro přehlednost |
|
||||
roman_numerals = zip((1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1), |
|
||||
('M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I')) |
|
||||
|
|
||||
|
|
||||
def roman(num): |
|
||||
res = "" |
|
||||
for i, n in roman_numerals: |
|
||||
res += n * (num // i) |
|
||||
num %= i |
|
||||
return res |
|
||||
|
|
||||
|
|
||||
def from_roman(rom): |
|
||||
if not rom: |
|
||||
return 0 |
|
||||
for i, n in roman_numerals: |
|
||||
if rom.upper().startswith(n): |
|
||||
return i + from_roman(rom[len(n):]) |
|
||||
raise Exception('Invalid roman numeral: "%s"', rom) |
|
||||
|
|
||||
|
|
||||
def seznam_problemu(): |
|
||||
"""Funkce pro hledání nekonzistencí v databázi a dalších nežádoucích stavů webu/databáze. |
|
||||
|
|
||||
Nijak nesouvisí s Problémy zadanými řešitelům.""" |
|
||||
# FIXME: přejmenovat funkci? |
|
||||
# FIXME: Tak, jak je napsaná, asi spíš patří někam k views a ne do utils (?) |
|
||||
problemy = [] |
|
||||
|
|
||||
# Pomocna fce k formatovani problemovych hlasek |
|
||||
def prb(cls, msg, objs=None): |
|
||||
s = '<b>%s:</b> %s' % (cls.__name__, msg) |
|
||||
if objs: |
|
||||
s += ' [' |
|
||||
for o in objs: |
|
||||
try: |
|
||||
url = o.admin_url() |
|
||||
except: |
|
||||
url = None |
|
||||
if url: |
|
||||
s += '<a href="%s">%s</a>, ' % (url, o.pk,) |
|
||||
else: |
|
||||
s += '%s, ' % (o.pk,) |
|
||||
s = s[:-2] + ']' |
|
||||
problemy.append(s) |
|
||||
|
|
||||
# Duplicita jmen |
|
||||
jmena = {} |
|
||||
for r in m.Resitel.objects.all(): |
|
||||
j = r.osoba.plne_jmeno() |
|
||||
if j not in jmena: |
|
||||
jmena[j] = [] |
|
||||
jmena[j].append(r) |
|
||||
for j in jmena: |
|
||||
if len(jmena[j]) > 1: |
|
||||
prb(m.Resitel, 'Duplicitní jméno "%s"' % (j,), jmena[j]) |
|
||||
|
|
||||
# Data maturity a narození |
|
||||
for r in m.Resitel.objects.all(): |
|
||||
if not r.rok_maturity: |
|
||||
prb(m.Resitel, 'Neznámý rok maturity', [r]) |
|
||||
if r.rok_maturity and (r.rok_maturity < 1990 or r.rok_maturity > datetime.date.today().year + 10): |
|
||||
prb(m.Resitel, 'Podezřelé datum maturity', [r]) |
|
||||
if r.osoba.datum_narozeni and ( |
|
||||
r.osoba.datum_narozeni.year < 1970 or r.osoba.datum_narozeni.year > datetime.date.today().year - 12): |
|
||||
prb(m.Resitel, 'Podezřelé datum narození', [r]) |
|
||||
# if not r.email: |
|
||||
# prb(Resitel, u'Neznámý email', [r]) |
|
||||
|
|
||||
## Kontroly konzistence databáze a TreeNodů |
|
||||
|
|
||||
# Články |
|
||||
for clanek in m.Clanek.objects.all(): |
|
||||
# získáme řešení svázané se článkem a z něj node ve stromě |
|
||||
reseni = clanek.reseni_set |
|
||||
if (reseni.count() != 1): |
|
||||
raise ValueError("Článek k sobě má nejedno řešení!") |
|
||||
r = reseni.first() |
|
||||
clanek_node = r.text_cely # vazba na ReseniNode z Reseni |
|
||||
# content type je věc pomáhající rozeznávat různé typy objektů v django-polymorphic |
|
||||
# protože isinstance vrátí vždy jen TreeNode |
|
||||
# https://django-polymorphic.readthedocs.io/en/stable/migrating.html |
|
||||
cislonode_ct = ContentType.objects.get_for_model(m.CisloNode) |
|
||||
node = clanek_node |
|
||||
while node is not None: |
|
||||
node_ct = node.polymorphic_ctype |
|
||||
if node_ct == cislonode_ct: # dostali jsme se k CisloNode |
|
||||
# zkontrolujeme, že stromové číslo odpovídá atributu |
|
||||
# .cislonode je opačná vazba k treenode_ptr, abychom z TreeNode dostali |
|
||||
# CisloNode |
|
||||
if clanek.cislo != node.cislonode.cislo: |
|
||||
prb(m.Clanek, "Číslo otištění uložené u článku nesedí s " |
|
||||
"číslem otištění podle struktury treenodů.", [clanek]) |
|
||||
break |
|
||||
node = t.get_parent(node) |
|
||||
|
|
||||
return problemy |
|
||||
|
|
||||
|
|
||||
### Generovani obalek |
|
||||
def resi_v_rocniku(rocnik, cislo=None): |
|
||||
""" Vrátí seznam řešitelů, co vyřešili nějaký problém v daném ročníku, do daného čísla. |
|
||||
Parametry: |
|
||||
rocnik (typu Rocnik) ročník, ze kterého chci řešitele, co něco odevzdali |
|
||||
cislo (typu Cislo) číslo, do kterého včetně se počítá, že v daném |
|
||||
ročníku řešitel něco poslal. |
|
||||
Pokud není zadané, počítají se všechna řešení z daného ročníku. |
|
||||
Výstup: |
|
||||
QuerySet objektů typu Resitel """ |
|
||||
|
|
||||
if cislo is None: |
|
||||
# filtrujeme pouze podle ročníku |
|
||||
return m.Resitel.objects.filter(rok_maturity__gte=rocnik.druhy_rok(), |
|
||||
reseni__hodnoceni__deadline_body__cislo__rocnik=rocnik).distinct() |
|
||||
else: # filtrujeme podle ročníku i čísla |
|
||||
return m.Resitel.objects.filter(rok_maturity__gte=rocnik.druhy_rok(), |
|
||||
reseni__hodnoceni__deadline_body__cislo__rocnik=rocnik, |
|
||||
reseni__hodnoceni__deadline_body__cislo__poradi__lte=cislo.poradi).distinct() |
|
||||
|
|
||||
|
|
||||
def aktivniResitele(cislo, pouze_letosni=False): |
|
||||
""" Vrací QuerySet aktivních řešitelů, což jsou ti, co ještě neodmaturovali |
|
||||
a letos něco poslali (anebo loni něco poslali, pokud jde o první tři čísla). |
|
||||
Parametry: |
|
||||
cislo (typu Cislo) číslo, o které se jedná |
|
||||
pouze_letosni jen řešitelé, kteří tento rok něco poslali |
|
||||
|
|
||||
""" |
|
||||
letos = cislo.rocnik |
|
||||
|
|
||||
# detekujeme, zda jde o první tři čísla či nikoli (tj. zda spamovat řešitele z minulého roku) |
|
||||
zacatek_rocniku = True |
|
||||
try: |
|
||||
if int(cislo.poradi) > 3: |
|
||||
zacatek_rocniku = False |
|
||||
except ValueError: |
|
||||
# if cislo.poradi != '7-8': |
|
||||
# raise ValueError(f'{cislo} je neplatné číslo čísla (není int a není 7-8)') |
|
||||
zacatek_rocniku = False |
|
||||
|
|
||||
# nehledě na číslo chceme jen řešitele, kteří letos něco odevzdali |
|
||||
if pouze_letosni: |
|
||||
zacatek_rocniku = False |
|
||||
|
|
||||
try: |
|
||||
loni = m.Rocnik.objects.get(rocnik=letos.rocnik - 1) |
|
||||
except ObjectDoesNotExist: |
|
||||
# Pro první ročník neexistuje ročník předchozí |
|
||||
zacatek_rocniku = False |
|
||||
|
|
||||
if not zacatek_rocniku: |
|
||||
return resi_v_rocniku(letos, cislo).filter(rok_maturity__gte=letos.druhy_rok()) |
|
||||
else: |
|
||||
# spojíme querysety s řešiteli loni a letos do daného čísla |
|
||||
return (resi_v_rocniku(loni) | resi_v_rocniku(letos, cislo)).distinct().filter(rok_maturity__gte=letos.druhy_rok()) |
|
||||
|
|
||||
def viewMethodSwitch(get, post): |
|
||||
""" |
|
||||
Vrátí view, který zavolá různé jiné views podle toho, kterou metodou je zavolán. |
|
||||
|
|
||||
Inspirováno https://docs.djangoproject.com/en/3.1/topics/class-based-views/mixins/#an-alternative-better-solution, jen jsem to udělal genericky. |
|
||||
|
|
||||
Parametry: |
|
||||
post view pro metodu POST |
|
||||
get view pro metodu GET |
|
||||
|
|
||||
V obou případech se míní už view jakožto funkce, takže u class-based views se už má použít .as_view() |
|
||||
|
|
||||
TODO: Podpora i pro metodu HEAD? A možná i pro FILES? |
|
||||
""" |
|
||||
|
|
||||
theGetView = get |
|
||||
thePostView = post |
|
||||
|
|
||||
class NewView(DjangoViews.View): |
|
||||
def get(self, request, *args, **kwargs): |
|
||||
return theGetView(request, *args, **kwargs) |
|
||||
def post(self, request, *args, **kwargs): |
|
||||
return thePostView(request, *args, **kwargs) |
|
||||
|
|
||||
return NewView.as_view() |
|
||||
|
|
||||
|
|
||||
def sync_skoly(base_url): |
|
||||
"""Stáhne všechny školy z mamwebu na adrese <base_url> a uloží je do databáze""" |
|
||||
from django.urls import reverse |
|
||||
full_url = base_url.rstrip('/') + reverse('export_skoly') |
|
||||
import requests |
|
||||
from django.core import serializers |
|
||||
json = requests.get(full_url, stream=True).content |
|
||||
for skola in serializers.deserialize('json', json): |
|
||||
skola.save() |
|
||||
|
|
||||
@transaction.atomic |
|
||||
def merge_resitele(cilovy, zdrojovy): |
|
||||
"""Spojí dva řešitelské objekty do cílového. |
|
||||
|
|
||||
Pojmenování "zdrojový" je silně nepřiléhající, ale co už…""" |
|
||||
|
|
||||
# Postup: |
|
||||
# Sjednotit / upravit informace cílového řešitele |
|
||||
print('Upravuji data modelu') |
|
||||
fieldy_shoda = ['skola', 'rok_maturity', 'zasilat', 'zasilat_cislo_emailem', 'zasilat_cislo_papirove'] |
|
||||
|
|
||||
for f in fieldy_shoda: |
|
||||
zf = getattr(zdrojovy, f) |
|
||||
cf = getattr(cilovy, f) |
|
||||
if cf == zf: |
|
||||
print(f' Údaj {f} je shodný ({zf})') |
|
||||
else: |
|
||||
if zf is None: |
|
||||
print(f' Údaj {f} je pouze v cílovém, používám') |
|
||||
continue |
|
||||
if cf is None: |
|
||||
setattr(cilovy, f, zf) |
|
||||
cilovy.poznamka += f'\nDEBUG: Merge: doplnéný údaj {f} ze zdrojového: {zf}' |
|
||||
print(f" Přiřazuji {f} ze zdrojového: {zf}") |
|
||||
continue |
|
||||
# Jsou fakt různé… |
|
||||
# FIXME: chybí možnost na vlastní úpravu… |
|
||||
verdikt = input(f"\n\n Údaj {f} se u řešitele {cilovy} ({cilovy.id}) liší:\n Zdrojový: {zf}\n Cílový: {cf}\n Který použít, [z]drojový, [c]ílový? ") |
|
||||
verdikt = verdikt[0].casefold() |
|
||||
if verdikt == 'z': |
|
||||
setattr(cilovy, f, zf) |
|
||||
cilovy.poznamka += f'\nDEBUG: Merge: pro {f} použit údaj {zf} (zdrojový), nepoužit {cf} (cílový)' |
|
||||
elif verdikt == 'c': |
|
||||
cilovy.poznamka += f'\nDEBUG: Merge: pro {f} použit údaj {cf} (cílový), nepoužit {zf} (zdrojový)' |
|
||||
else: raise ValueError('Špatná odpověď, řešitel pravděpodobně neuložen') |
|
||||
# poznámku chceme nezahodit… |
|
||||
cilovy.poznamka += f'\nDEBUG: Merge: Původní poznámka: {zdrojovy.poznamka}' |
|
||||
print(f' Výsledný řešitel: {cilovy.__dict__}, ukládám') |
|
||||
cilovy.save() |
|
||||
|
|
||||
|
|
||||
# Přepojit všechny vazby ze zdrojového na cílového |
|
||||
print('Přepojuji vazby') |
|
||||
# Vazby: Škola (hotovo), Řešení_Řešitelé, Konfery_Účastníci, Soustředění_Účastníci, Osoba (vyřeší se později, nejde přepojit) |
|
||||
ct = m.Reseni_Resitele.objects.filter(resitele=zdrojovy).update(resitele=cilovy) |
|
||||
print(f' Přepojeno {ct} řešení') |
|
||||
ct = m.Konfery_Ucastnici.objects.filter(resitel=zdrojovy).update(resitel=cilovy) |
|
||||
print(f' Přepojeno {ct} konfer') |
|
||||
ct = m.Soustredeni_Ucastnici.objects.filter(resitel=zdrojovy).update(resitel=cilovy) |
|
||||
print(f' Přepojeno {ct} sousů') |
|
||||
|
|
||||
# Teď by na zdrojovém řešiteli nemělo nic viset, smazat ho, pamatujíce si jeho Osobu |
|
||||
zdrosoba = zdrojovy.osoba |
|
||||
print(f'Mažu zdrojového řešitele {zdrojovy.__dict__}') |
|
||||
zdrojovy.delete() |
|
||||
# Spojit osoby (separátní funkce). |
|
||||
merge_osoby(cilovy.osoba, zdrosoba) |
|
||||
|
|
||||
input("Potvrdit transakci řešitelů (^C pro zrušení) ") |
|
||||
|
|
||||
@transaction.atomic |
|
||||
def merge_osoby(cilova, zdrojova): |
|
||||
""" Spojí dvě osoby do cílové |
|
||||
|
|
||||
Nehlídá omezení typu "max 1 řešitel na osobu", to by měla hlídat databáze (OneToOneField).""" |
|
||||
# Sjednocení dat |
|
||||
print('Sjednocuji data osob') |
|
||||
# ID, User neřešíme, poznámku vyřešíme separátně. |
|
||||
fieldy = ['datum_narozeni', 'datum_registrace', 'datum_souhlasu_udaje', |
|
||||
'datum_souhlasu_zasilani', 'email', 'foto', 'jmeno', 'mesto', |
|
||||
'osloveni', 'prezdivka', 'prijmeni', 'psc', 'stat', 'telefon', 'ulice'] |
|
||||
for f in fieldy: |
|
||||
zf = getattr(zdrojova, f) |
|
||||
cf = getattr(cilova, f) |
|
||||
if cf == zf: |
|
||||
print(f' Údaj {f} je shodný ({zf})') |
|
||||
else: |
|
||||
if zf is None: |
|
||||
print(f' Údaj {f} je pouze v cílové, používám') |
|
||||
continue |
|
||||
if cf is None: |
|
||||
setattr(cilova, f, zf) |
|
||||
cilova.poznamka += f'\nDEBUG: Merge: doplnéný údaj {f} ze zdrojové: {zf}' |
|
||||
print(f" Přiřazuji {f} ze zdrojové: {zf}") |
|
||||
continue |
|
||||
# Jsou fakt různé… |
|
||||
# FIXME: chybí možnost na vlastní úpravu… |
|
||||
verdikt = input(f"\n\n Údaj {f} se u osoby {cilova} ({cilova.id}) liší:\n Zdrojový: {zf}\n Cílový: {cf}\n Který použít, [z]drojový, [c]ílový? ") |
|
||||
verdikt = verdikt[0].casefold() |
|
||||
if verdikt == 'z': |
|
||||
setattr(cilova, f, zf) |
|
||||
cilova.poznamka += f'\nDEBUG: Merge: pro {f} použit údaj {zf} (zdrojová), nepoužit {cf} (cílová)' |
|
||||
elif verdikt == 'c': |
|
||||
cilova.poznamka += f'\nDEBUG: Merge: pro {f} použit údaj {cf} (cílová), nepoužit {zf} (zdrojová)' |
|
||||
else: raise ValueError('Špatná odpověď, řešitel pravděpodobně neuložen') |
|
||||
# poznámku chceme nezahodit… |
|
||||
cilova.poznamka += f'\nDEBUG: Merge: Původní poznámka: {zdrojova.poznamka}' |
|
||||
print(f' Výsledná osoba: {cilova.__dict__}, ukládám') |
|
||||
cilova.save() |
|
||||
|
|
||||
# Vazby: Řešitel, User, Příjemce, Organizátor, Škola.kontaktní_osoba |
|
||||
print('Přepojuji vazby') |
|
||||
ct = m.Skola.objects.filter(kontaktni_osoba=zdrojova).update(kontaktni_osoba=cilova) |
|
||||
print(f' Přepojeno {ct} kontaktních osob') |
|
||||
# Ostatní vazby vyřeší OneToOneFieldy, ale někdy nemusí existovat… |
|
||||
ct = m.Resitel.objects.filter(osoba=zdrojova).update(osoba=cilova) |
|
||||
print(f' Přepojeno {ct} řešitelů') |
|
||||
ct = m.Prijemce.objects.filter(osoba=zdrojova).update(osoba=cilova) |
|
||||
print(f' Přepojeno {ct} příjemců') |
|
||||
ct = m.Organizator.objects.filter(osoba=zdrojova).update(osoba=cilova) |
|
||||
print(f' Přepojeno {ct} organizátorů') |
|
||||
# Uživatelé vedou opačným směrem, radši chceme zkontrolovat, že jsou různí ručně: |
|
||||
if zdrojova.user != cilova.user: |
|
||||
# Jeden z nich může být nenastavený… |
|
||||
if zdrojova.user is None: |
|
||||
print('Uživatel je již v cílové osobě') |
|
||||
elif cilova.user is None: |
|
||||
print('Používám uživatele zdrojové osoby') |
|
||||
cilova.user = zdrojova.user |
|
||||
# Teď nemůžeme uložit, protože kolize uživatelů. Ukládat cílovou budeme až po smazání zdrojové. |
|
||||
else: raise ValueError('Osoby mají obě uživatele, radši padám') |
|
||||
|
|
||||
# Uložení a mazání |
|
||||
print(f'Mažu zdrojovou osobu {zdrojova.__dict__}') |
|
||||
zdrojova.delete() |
|
||||
print(f'Ukládám cílovou osobu {cilova.__dict__}') |
|
||||
cilova.save() |
|
||||
|
|
||||
input("Potvrdit transakci osob (^C pro zrušení) ") |
|
||||
|
|
||||
|
|
@ -1,4 +0,0 @@ |
|||||
from .views_all import * |
|
||||
|
|
||||
# Dočsasné views |
|
||||
from .docasne import * |
|
@ -0,0 +1,69 @@ |
|||||
|
import logging |
||||
|
import datetime |
||||
|
import random |
||||
|
from typing import Sequence |
||||
|
|
||||
|
import lorem |
||||
|
|
||||
|
from .models import Soustredeni, Konfera |
||||
|
import seminar.models.tvorba as am |
||||
|
import personalni.models as pm |
||||
|
|
||||
|
logger = logging.getLogger(__name__) |
||||
|
|
||||
|
|
||||
|
def gen_soustredeni( |
||||
|
size: int, |
||||
|
resitele: Sequence[pm.Resitel], |
||||
|
organizatori: Sequence[pm.Organizator], |
||||
|
rnd: random.Random = None, |
||||
|
) -> Sequence[Soustredeni]: |
||||
|
logger.info('Generuji soustředění (size={})...') |
||||
|
rnd = rnd or random.Random(x=42) |
||||
|
|
||||
|
soustredeni = [] |
||||
|
for _ in range(1, 10): # FIXME Tu range si změňte jak chcete, nevím, co přesně znamená size (asi Anet?) |
||||
|
datum_zacatku = datetime.date(rnd.randint(2000, 2020), rnd.randint(1, 12), rnd.randint(1, 28)) |
||||
|
working_sous = Soustredeni.objects.create( |
||||
|
rocnik=am.Rocnik.objects.order_by('?').first(), |
||||
|
verejne_db=rnd.choice([True, False]), |
||||
|
misto=rnd.choice(['Kremrolovice', 'Indiánov', 'U zmzliny', 'Vafláreň', 'Větrník', 'Horní Rakvička', 'Dolní cheesecake']), |
||||
|
typ=rnd.choice(['jarni', 'podzimni', 'vikend']), |
||||
|
datum_zacatku=datum_zacatku, |
||||
|
datum_konce=datum_zacatku + datetime.timedelta(days=7)) |
||||
|
ucastnici = rnd.sample(resitele, min(len(resitele), 20)) |
||||
|
working_sous.ucastnici.set(ucastnici) |
||||
|
orgove_vyber = rnd.sample(organizatori, min(len(organizatori), 20)) |
||||
|
working_sous.organizatori.set(orgove_vyber) |
||||
|
working_sous.save() |
||||
|
soustredeni.append(working_sous) |
||||
|
return soustredeni |
||||
|
|
||||
|
|
||||
|
def gen_konfery( |
||||
|
size: int, |
||||
|
organizatori: Sequence[pm.Organizator], |
||||
|
soustredeni: Sequence[Soustredeni], |
||||
|
resitele: Sequence[pm.Resitel] = None, |
||||
|
rnd: random.Random = None, |
||||
|
) -> Sequence[Konfera]: |
||||
|
logger.info('Generuji konfery (size={})...'.format(size)) |
||||
|
rnd = rnd or random.Random(x=42) |
||||
|
|
||||
|
konfery = [] |
||||
|
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(), |
||||
|
abstrakt=lorem.paragraph(), |
||||
|
garant=rnd.choice(organizatori), |
||||
|
soustredeni=rnd.choice(soustredeni), |
||||
|
typ_prezentace=rnd.choice(['veletrh', 'prezentace'])) |
||||
|
ucastnici_sous = resitele if resitele else list(konfera.soustredeni.ucastnici.all()) |
||||
|
ucastnici = rnd.sample(ucastnici_sous, min(len(ucastnici_sous), rnd.randint(3, 6))) |
||||
|
konfera.ucastnici.set(ucastnici) |
||||
|
konfera.save() |
||||
|
konfery.append(konfera) |
||||
|
return konfery |
@ -0,0 +1,6 @@ |
|||||
|
from django.apps import AppConfig |
||||
|
|
||||
|
|
||||
|
class TvorbaConfig(AppConfig): |
||||
|
name = 'tvorba' |
||||
|
verbose_name = 'Tvorba' |
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 300 KiB After Width: | Height: | Size: 300 KiB |
@ -0,0 +1,506 @@ |
|||||
|
# FIXME vypreparovat treenode |
||||
|
|
||||
|
import datetime |
||||
|
|
||||
|
import lorem |
||||
|
import django.contrib.auth |
||||
|
import logging |
||||
|
|
||||
|
from seminar.models import Rocnik, Cislo, Deadline, Problem, Tema, Uloha, TextNode, UlohaVzorakNode, RocnikNode, CisloNode, TemaVCisleNode, Text, UlohaZadaniNode |
||||
|
import seminar.models as m |
||||
|
|
||||
|
from treenode.treelib import all_children, insert_last_child, all_children_of_type, create_node_after |
||||
|
|
||||
|
from odevzdavatko.testutils import gen_reseni_ulohy |
||||
|
|
||||
|
logger = logging.getLogger(__name__) |
||||
|
|
||||
|
User = django.contrib.auth.get_user_model() |
||||
|
|
||||
|
|
||||
|
def gen_zadani_ulohy(rnd, cisla, organizatori, pocet_oboru, poradi_cisla, poradi_problemu): |
||||
|
|
||||
|
# Proměnné pro náhodné generování názvů a zadání. |
||||
|
jaka = ["Šachová", "Černá", "Větrná", "Dlouhá", "Křehká", "Rychlá", |
||||
|
"Zákeřná", "Fyzikální"] |
||||
|
co = ["kostka", "smršť", "díra", "zrada", "toulka", "tyč", |
||||
|
"úloha", "blecha"] |
||||
|
sloveso = ["Najděte", "Spočítejte", "Zapište", "Změřte", "Odhadněte"] |
||||
|
koho = ["délku", "počet", "množství", "dílky"] |
||||
|
ceho = ["všech", "správných", "konstatních", "zelených"] |
||||
|
jmeno = ["řešení", "tahů", "čísel", "kalhot", "koulí", "hadů"] |
||||
|
kde = ["na zemi", "ve vesmíru", "ve vzduchu", "na šňůře", "v letadle"] |
||||
|
obory = ["M", "F", "I", "O", "B"] |
||||
|
|
||||
|
p = Uloha.objects.create( |
||||
|
# atributy třídy Problem |
||||
|
nazev=" ".join([rnd.choice(jaka), rnd.choice(co)]), |
||||
|
stav=Problem.STAV_ZADANY, |
||||
|
zamereni=rnd.sample(obory, pocet_oboru), |
||||
|
autor=rnd.choice(organizatori), |
||||
|
garant=rnd.choice(organizatori), |
||||
|
kod=str(poradi_problemu), |
||||
|
# atributy třídy Uloha |
||||
|
cislo_zadani=cisla[poradi_cisla-2-1], |
||||
|
cislo_reseni=cisla[poradi_cisla-1], |
||||
|
cislo_deadline=cisla[poradi_cisla-1], |
||||
|
max_body = rnd.randint(1, 8) |
||||
|
) |
||||
|
|
||||
|
text = " ".join( |
||||
|
[rnd.choice(sloveso), |
||||
|
rnd.choice(koho), |
||||
|
rnd.choice(ceho), |
||||
|
rnd.choice(jmeno), |
||||
|
rnd.choice(kde)] |
||||
|
) |
||||
|
text_zadani = Text.objects.create( |
||||
|
na_web = text, |
||||
|
do_cisla = text, |
||||
|
) |
||||
|
zad = TextNode.objects.create(text = text_zadani, root = p.cislo_zadani.rocnik.rocniknode) |
||||
|
uloha_zadani = UlohaZadaniNode.objects.create(uloha = p, first_child = zad, root = p.cislo_zadani.rocnik.rocniknode) |
||||
|
p.ulohazadaninode = uloha_zadani |
||||
|
otec_syn(cisla[poradi_cisla-2-1].cislonode, uloha_zadani) |
||||
|
|
||||
|
return p |
||||
|
|
||||
|
def gen_vzoroveho_reseni_ulohy(rnd, organizatori, uloha, pocet_opravovatelu): |
||||
|
reseni = ["to je přece jasné", "triviální", "omlouváme se," |
||||
|
"otevřený problém", "neřešitelné", "triviálně triviální", |
||||
|
"použitím věty z prvního semestru na matfyzu", |
||||
|
"jednoduše pomocí látky z druhého semestru na matfyzu", |
||||
|
"netriviální aplikace diferenciálních rovnic", "zadání je vnitřně" |
||||
|
"sporné", "nepopsatelně jednoduché", "pokud jste na to nepřišli," |
||||
|
"tak jste fakt hloupí"] |
||||
|
|
||||
|
# Generování vzorového řešení. |
||||
|
obsah = rnd.choice(reseni) |
||||
|
text_vzoraku = Text.objects.create( |
||||
|
na_web = obsah, |
||||
|
do_cisla = obsah |
||||
|
) |
||||
|
vzorak = TextNode.objects.create(text = text_vzoraku, root = uloha.cislo_zadani.rocnik.rocniknode) |
||||
|
uloha_vzorak = UlohaVzorakNode.objects.create(uloha = uloha, first_child = vzorak, root = uloha.cislo_zadani.rocnik.rocniknode) |
||||
|
uloha.ulohavzoraknode = uloha_vzorak |
||||
|
|
||||
|
uloha.opravovatele.set(rnd.sample(organizatori, pocet_opravovatelu)) |
||||
|
uloha.save() |
||||
|
return uloha_vzorak |
||||
|
|
||||
|
|
||||
|
def gen_ulohy_do_cisla(rnd, organizatori, resitele, rocnik_cisla, rocniky, size): |
||||
|
logger.info('Generuji úlohy do čísla (size={})...'.format(size)) |
||||
|
|
||||
|
k = 0 |
||||
|
for rocnik in rocniky: |
||||
|
k += 1 |
||||
|
print("Generuji {}. číslo.".format(k)) |
||||
|
cisla = rocnik_cisla[k - 1] |
||||
|
for ci in range(3, len(cisla) + 1): # pro všechna čísla |
||||
|
resitele_size = round(7/8 * 30 * size) # očekáváný celkový počet řešitelů |
||||
|
poc_res = rnd.randint(resitele_size//8, resitele_size//4) |
||||
|
# dané číslo řeší něco mezi osminou a čtvrtinou všech řešitelů |
||||
|
# (náhodná hausnumera, možno změnit) |
||||
|
# účelem je, aby se řešení generovala z menší množiny řešitelů a tedy |
||||
|
# bylo více řešení od jednoho řešitele daného čísla |
||||
|
resitele_cisla = rnd.sample(resitele, poc_res) |
||||
|
for pi in range(1, ((size + 1) // 2) + 1): # počet problémů |
||||
|
|
||||
|
poc_op = rnd.randint(1, 4) # počet opravovatelů |
||||
|
poc_oboru = rnd.randint(1, 2) |
||||
|
|
||||
|
# Generování zadání úlohy a UlohaZadaniNode, |
||||
|
# přivěšení pod dané číslo |
||||
|
p = gen_zadani_ulohy(rnd, cisla, organizatori, poc_oboru, ci, pi) |
||||
|
# Generování vzorového řešení |
||||
|
uloha_vzorak = gen_vzoroveho_reseni_ulohy(rnd, organizatori, |
||||
|
p, poc_op) |
||||
|
insert_last_child(cisla[ci-1].cislonode, uloha_vzorak) |
||||
|
|
||||
|
# Generování řešení a hodnocení k úloze |
||||
|
gen_reseni_ulohy(rnd, cisla, p, poc_res, ci, |
||||
|
resitele_cisla, resitele) |
||||
|
|
||||
|
return |
||||
|
|
||||
|
|
||||
|
def gen_rocniky(last_rocnik, size): |
||||
|
logger.info('Generuji ročníky (size={})...'.format(size)) |
||||
|
|
||||
|
rocniky = [] |
||||
|
node = None |
||||
|
for ri in range(min(last_rocnik - size, 1), last_rocnik + 1): |
||||
|
rocnik = Rocnik.objects.create(prvni_rok = 1993 + ri, rocnik = ri) |
||||
|
node2 = RocnikNode.objects.create(rocnik = rocnik, succ = node) |
||||
|
rocnik.save() |
||||
|
node = node2 |
||||
|
rocniky.append(rocnik) |
||||
|
return rocniky |
||||
|
|
||||
|
|
||||
|
def gen_cisla(rnd, rocniky): |
||||
|
logger.info('Generuji čísla...') |
||||
|
|
||||
|
rocnik_cisla = [] |
||||
|
for rocnik in rocniky: |
||||
|
otec = True |
||||
|
cisla = [] |
||||
|
cisel = rnd.randint(4, 8) |
||||
|
node = None |
||||
|
for ci in range(1, cisel + 1): |
||||
|
# první číslo vydáváme typicky okolo prázdnin |
||||
|
# (ci - 1)*2 zaručuje první číslo v červnu a všechna |
||||
|
# další po dvou měsících (což je rozumná aproximace) |
||||
|
mesic_vydani = (ci - 1)*2 + 6 |
||||
|
# celociselné dělení mi řekne, jestli to je první nebo druhý rok ročníku |
||||
|
vydano = datetime.date(rocnik.prvni_rok + mesic_vydani // 12, |
||||
|
(mesic_vydani - 1) % 12 + 1, |
||||
|
rnd.randint(1, 28)) |
||||
|
deadline = datetime.date(rocnik.prvni_rok + (mesic_vydani + 2) // 12, |
||||
|
(mesic_vydani + 1) % 12 + 1, |
||||
|
rnd.randint(1, 28)) |
||||
|
|
||||
|
cislo = Cislo.objects.create( |
||||
|
rocnik = rocnik, |
||||
|
poradi = str(ci), |
||||
|
datum_vydani=vydano, |
||||
|
verejne_db=True, |
||||
|
) |
||||
|
node2 = CisloNode.objects.get(cislo = cislo) |
||||
|
node2.succ = node |
||||
|
node2.root = rocnik.rocniknode |
||||
|
cislo.save() |
||||
|
deadline = Deadline.objects.create( |
||||
|
cislo=cislo, |
||||
|
deadline=deadline, |
||||
|
typ=Deadline.TYP_CISLA, |
||||
|
verejna_vysledkovka=True, |
||||
|
) |
||||
|
deadline.save() |
||||
|
node = node2 |
||||
|
if otec: |
||||
|
otec = False |
||||
|
rocnik.rocniknode.first_child = node |
||||
|
rocnik.save() |
||||
|
|
||||
|
cisla.append(cislo) |
||||
|
rocnik_cisla.append(cisla) |
||||
|
return rocnik_cisla |
||||
|
|
||||
|
def add_first_child(node, child): |
||||
|
node.first_child = child |
||||
|
node.save() |
||||
|
return |
||||
|
|
||||
|
def get_text(): |
||||
|
odstavec = lorem.paragraph() |
||||
|
return Text.objects.create(na_web = odstavec, do_cisla = odstavec) |
||||
|
|
||||
|
def gen_dlouhe_tema(rnd, organizatori, rocnik, nazev, obor, kod): |
||||
|
tema = Tema.objects.create( |
||||
|
nazev=nazev, |
||||
|
stav=Problem.STAV_ZADANY, |
||||
|
zamereni="M", |
||||
|
autor=rnd.choice(organizatori), |
||||
|
garant=rnd.choice(organizatori), |
||||
|
kod=str(kod), |
||||
|
tema_typ=rnd.choice(Tema.TEMA_CHOICES)[0], |
||||
|
rocnik=rocnik, |
||||
|
abstrakt = lorem.paragraph() |
||||
|
) |
||||
|
|
||||
|
# Generování struktury k tématu |
||||
|
cisla = sorted(rocnik.cisla.all(), key=lambda cislo: cislo.poradi) |
||||
|
for cislo in cisla: |
||||
|
# Přidáme TemaVCisleNode do daného čísla |
||||
|
cislo_node = cislo.cislonode |
||||
|
tema_cislo_node = TemaVCisleNode.objects.create(tema = tema, root = cislo_node.root) |
||||
|
insert_last_child(cislo_node, tema_cislo_node) |
||||
|
|
||||
|
# Přidávání obsahu do čísla |
||||
|
cast_node = m.CastNode.objects.create(nadpis = "Příspěvek k číslu {}".format(cislo.kod), root=cislo_node.root) |
||||
|
add_first_child(tema_cislo_node, cast_node) |
||||
|
|
||||
|
text_node = TextNode.objects.create(text = get_text(), root=cislo_node.root) |
||||
|
add_first_child(cast_node, text_node) |
||||
|
|
||||
|
cast_node2 = m.CastNode.objects.create(nadpis = "První podproblém", root=cislo_node.root) |
||||
|
add_first_child(text_node, cast_node2) |
||||
|
|
||||
|
text_node2 = TextNode.objects.create(text = get_text(), root=cislo_node.root) |
||||
|
add_first_child(cast_node2, text_node2) |
||||
|
|
||||
|
cast_node3 = m.CastNode.objects.create(nadpis = "Druhý podproblém", root=cislo_node.root) |
||||
|
add_first_child(text_node2, cast_node3) |
||||
|
|
||||
|
text_node3 = TextNode.objects.create(text = get_text(), root=cislo_node.root) |
||||
|
add_first_child(cast_node3, text_node3) |
||||
|
|
||||
|
cast_node4 = m.CastNode.objects.create(nadpis = "Třetí podproblém", root=cislo_node.root) |
||||
|
add_first_child(text_node3, cast_node4) |
||||
|
|
||||
|
text_node4 = TextNode.objects.create(text = get_text(), root=cislo_node.root) |
||||
|
add_first_child(cast_node3, text_node4) |
||||
|
|
||||
|
cast_node3a = m.CastNode.objects.create(nadpis = "Podproblém paralelní s " |
||||
|
"druhým podproblémem", root=cislo_node.root) |
||||
|
cast_node3.succ = cast_node3a |
||||
|
cast_node3.save() |
||||
|
|
||||
|
text_node3a = TextNode.objects.create(text = get_text(), root=cislo_node.root) |
||||
|
add_first_child(cast_node3a, text_node3a) |
||||
|
|
||||
|
# Občas přidáme mezičíslo |
||||
|
if rnd.randint(1, 3) == 1: |
||||
|
create_node_after(cislo_node, m.MezicisloNode, root=cislo_node.root) |
||||
|
mezicislo_node = cislo_node.succ |
||||
|
|
||||
|
cast_node_mezicislo = m.CastNode.objects.create( |
||||
|
nadpis = "Příspěvek k mezičíslu".format(cislo.kod), root=cislo_node.root) |
||||
|
add_first_child(mezicislo_node, cast_node_mezicislo) |
||||
|
|
||||
|
odstavec = lorem.paragraph() |
||||
|
text_mezicislo = Text.objects.create(na_web = odstavec, do_cisla = odstavec) |
||||
|
text_node_mezicislo = TextNode.objects.create(text = text_mezicislo, root=cislo_node.root) |
||||
|
add_first_child(cast_node_mezicislo, text_node_mezicislo) |
||||
|
|
||||
|
return tema |
||||
|
|
||||
|
def gen_temata(rnd, rocniky, rocnik_cisla, organizatori): |
||||
|
logger.info('Generuji témata...') |
||||
|
|
||||
|
jake = ["Hravé", "Fyzikální", "Nejlepší", "Totálně masakrální", |
||||
|
"Šokující", "Magnetické", "Modré", "Překvapivé", |
||||
|
"Plasmatické", "Novoroční"] |
||||
|
co = ["téma", "záření", "stavení", "jiskření", "jelito", |
||||
|
"drama", "kuře", "moře", "klání", "proudění", "čekání"] |
||||
|
poc_oboru = rnd.randint(1, 2) |
||||
|
|
||||
|
rocnik_temata = [] |
||||
|
# Věříme, že rocnik_cisla je pole polí čísel podle ročníků, tak si necháme dát |
||||
|
# vždycky jeden ročník a k němu příslušná čísla. |
||||
|
for rocnik, cisla in zip(rocniky, rocnik_cisla): |
||||
|
kod = 1 |
||||
|
letosni_temata = [] |
||||
|
# Do každého ročníku vymyslíme tři (zatím) témata, v každém z prvních čísel jedno |
||||
|
for zacatek_tematu in range(1, 3): |
||||
|
# Vygenerujeme téma |
||||
|
t = Tema.objects.create( |
||||
|
# atributy třídy Problem |
||||
|
nazev=" ".join([rnd.choice(jake), rnd.choice(co)]), |
||||
|
stav=Problem.STAV_ZADANY, |
||||
|
zamereni=rnd.sample(["M", "F", "I", "O", "B"], poc_oboru), |
||||
|
autor=rnd.choice(organizatori), |
||||
|
garant=rnd.choice(organizatori), |
||||
|
kod=str(kod), |
||||
|
# atributy třídy Téma |
||||
|
tema_typ=rnd.choice(Tema.TEMA_CHOICES)[0], |
||||
|
rocnik=rocnik, |
||||
|
abstrakt = "Abstrakt tematka {}".format(kod) |
||||
|
) |
||||
|
kod += 1 |
||||
|
|
||||
|
# Vymyslíme, kdy skončí |
||||
|
konec_tematu = min(rnd.randint(zacatek_tematu, 7), len(cisla)) |
||||
|
|
||||
|
# Vyrobíme TemaVCisleNody pro obsah |
||||
|
for i in range(zacatek_tematu, konec_tematu+1): |
||||
|
node = TemaVCisleNode.objects.create(tema = t,root=rocnik.rocniknode) |
||||
|
# FIXME: Není to off-by-one? |
||||
|
otec = cisla[i-1].cislonode |
||||
|
otec_syn(otec, node) |
||||
|
|
||||
|
# Vymyslíme, kdo to bude opravovat |
||||
|
poc_opravovatelu = rnd.randint(1, 3) |
||||
|
t.opravovatele.set(rnd.sample(organizatori, poc_opravovatelu)) |
||||
|
|
||||
|
# Uložíme všechno |
||||
|
t.save() |
||||
|
letosni_temata.append((zacatek_tematu, konec_tematu, t)) |
||||
|
rocnik_temata.append(letosni_temata) |
||||
|
return rocnik_temata |
||||
|
|
||||
|
def gen_ulohy_tematu(rnd, organizatori, resitele, tema, kod, cislo, cislo_se_vzorakem): |
||||
|
""" Generování úlohy k danému tématu. """ |
||||
|
|
||||
|
# Proměnné pro náhodné generování názvů a zadání. |
||||
|
jaka = ["Šachová", "Černá", "Větrná", "Dlouhá", "Křehká", "Rychlá", |
||||
|
"Zákeřná", "Fyzikální"] |
||||
|
co = ["kostka", "smršť", "díra", "zrada", "toulka", "tyč", |
||||
|
"úloha", "blecha"] |
||||
|
sloveso = ["Najděte", "Spočítejte", "Zapište", "Změřte", "Odhadněte"] |
||||
|
koho = ["délku", "počet", "množství", "dílky"] |
||||
|
ceho = ["všech", "správných", "konstatních", "zelených"] |
||||
|
jmeno = ["řešení", "tahů", "čísel", "kalhot", "koulí", "hadů"] |
||||
|
kde = ["na zemi", "ve vesmíru", "ve vzduchu", "na šňůře", "v letadle"] |
||||
|
obory = ["M", "F", "I", "O", "B"] |
||||
|
|
||||
|
uloha = Uloha.objects.create( |
||||
|
nazev=": ".join([tema.nazev, |
||||
|
"úloha {}.".format(kod)]), |
||||
|
nadproblem=tema, |
||||
|
stav=Problem.STAV_ZADANY, |
||||
|
zamereni=tema.zamereni, |
||||
|
autor=tema.autor, |
||||
|
garant=tema.garant, |
||||
|
kod=str(kod), |
||||
|
cislo_zadani=cislo, |
||||
|
cislo_reseni=cislo_se_vzorakem, |
||||
|
cislo_deadline=cislo_se_vzorakem, |
||||
|
max_body = rnd.randint(1, 8) |
||||
|
) |
||||
|
|
||||
|
# Samotný obsah následně vzniklého Textu zadání |
||||
|
obsah = " ".join( |
||||
|
[rnd.choice(sloveso), |
||||
|
rnd.choice(koho), |
||||
|
rnd.choice(ceho), |
||||
|
rnd.choice(jmeno), |
||||
|
rnd.choice(kde)] |
||||
|
) |
||||
|
text_zadani = Text.objects.create( |
||||
|
na_web = obsah, |
||||
|
do_cisla = obsah, |
||||
|
) |
||||
|
zad = TextNode.objects.create(text = text_zadani, root=tema.temavcislenode_set.first().root) |
||||
|
uloha_zadani = UlohaZadaniNode.objects.create(uloha=uloha, first_child = zad, root=tema.temavcislenode_set.first().root) |
||||
|
uloha.ulohazadaninode = uloha_zadani |
||||
|
|
||||
|
# Generování řešení a hodnocení k úloze |
||||
|
gen_reseni_ulohy(rnd, [cislo], uloha, len(resitele)//4, 1, |
||||
|
resitele, resitele) |
||||
|
|
||||
|
return uloha, uloha_zadani |
||||
|
|
||||
|
|
||||
|
def gen_ulohy_k_tematum(rnd, rocniky, rocnik_cisla, rocnik_temata, organizatori, resitele): |
||||
|
logger.info('Generuji úlohy k tématům...') |
||||
|
|
||||
|
# Ke každému ročníku si vezmeme příslušná čísla a témata |
||||
|
for rocnik, cisla, temata in zip(rocniky, rocnik_cisla, rocnik_temata): |
||||
|
# Do každého čísla nagenerujeme ke každému témátku pár úložek |
||||
|
for cislo in cisla: |
||||
|
print("Generuji úložky do {}-tého čísla".format(cislo.poradi)) |
||||
|
# Vzorák bude o dvě čísla dál |
||||
|
cislo_se_vzorakem = Cislo.objects.filter( |
||||
|
rocnik=rocnik, |
||||
|
poradi=str(int(cislo.poradi) + 2), |
||||
|
) |
||||
|
# Pokud není číslo pro vzorák, tak se dá do posledního čísla |
||||
|
# (i kdyby tam mělo být zadání i řešení...) |
||||
|
# Tohle sice umožňuje vygenerovat vzorák do čísla dávno po konci témátka, |
||||
|
# ale to nám pro jednoduchost nevadí. |
||||
|
if len(cislo_se_vzorakem) == 0: |
||||
|
cislo_se_vzorakem = cisla[-1] |
||||
|
else: |
||||
|
cislo_se_vzorakem = cislo_se_vzorakem.first() |
||||
|
|
||||
|
for tema_node in all_children_of_type(cislo.cislonode, TemaVCisleNode): |
||||
|
tema = tema_node.tema |
||||
|
|
||||
|
# Pokud už témátko skončilo, žádné úložky negenerujeme |
||||
|
# FIXME: Bylo by hezčí, kdyby se čísla předávala jako Cislo a ne |
||||
|
# jako int v té trojici (start, konec, tema) |
||||
|
if not temata[int(tema.kod)-1][1] >= int(cislo_se_vzorakem.poradi): |
||||
|
continue |
||||
|
|
||||
|
# Generujeme 1 až 4 úložky k tomuto témátku do tohoto čísla. |
||||
|
for kod in range(1, rnd.randint(1, 4)): |
||||
|
u, uz = gen_ulohy_tematu(rnd, organizatori, resitele, tema, kod, |
||||
|
cislo, cislo_se_vzorakem) |
||||
|
|
||||
|
insert_last_child(tema_node, uz) |
||||
|
|
||||
|
poc_op = rnd.randint(1, 4) |
||||
|
uvz = gen_vzoroveho_reseni_ulohy(rnd, organizatori, |
||||
|
u, poc_op) |
||||
|
|
||||
|
# Najdeme správný TemaVCisleNode pro vložení vzoráku |
||||
|
res_tema_node = None; |
||||
|
for node in all_children(cislo_se_vzorakem.cislonode): |
||||
|
if isinstance(node, TemaVCisleNode): |
||||
|
if node.tema == tema: |
||||
|
res_tema_node = node |
||||
|
if res_tema_node is None: |
||||
|
raise LookupError("Nenalezen Node pro vložení vzoráku") |
||||
|
insert_last_child(res_tema_node, uvz) |
||||
|
u.save() |
||||
|
return |
||||
|
|
||||
|
|
||||
|
def otec_syn(otec, syn): |
||||
|
bratr = otec.first_child |
||||
|
syn.succ = bratr |
||||
|
otec.first_child = syn |
||||
|
syn.save() |
||||
|
otec.save() |
||||
|
|
||||
|
def gen_clanek(rnd, organizatori, resitele): |
||||
|
logger.info("Generuji článek do čísla 22.2") |
||||
|
clanek = m.Clanek.objects.create( |
||||
|
nazev="Článek o Lorem ipsum", |
||||
|
nadproblem=None, |
||||
|
stav='vyreseny', |
||||
|
zamereni=['I'], |
||||
|
garant=rnd.choice(organizatori), |
||||
|
kod='cl', |
||||
|
) |
||||
|
clanek.save() |
||||
|
|
||||
|
reseni = m.Reseni.objects.create( |
||||
|
zverejneno=True, |
||||
|
) |
||||
|
reseni.resitele.add(rnd.choice(resitele)) |
||||
|
reseni.save() |
||||
|
|
||||
|
cislo = m.Cislo.objects.get(rocnik__rocnik=22, poradi=2) |
||||
|
cislonode = cislo.cislonode |
||||
|
|
||||
|
hodnoceni = m.Hodnoceni.objects.create( |
||||
|
body=15.0, |
||||
|
cislo_body=cislo, |
||||
|
reseni=reseni, |
||||
|
problem=clanek, |
||||
|
) |
||||
|
hodnoceni.save() |
||||
|
|
||||
|
reseninode = m.ReseniNode.objects.create( |
||||
|
reseni=reseni |
||||
|
) |
||||
|
reseninode.save() |
||||
|
|
||||
|
# Bude to celý text |
||||
|
reseni.text_cely = reseninode |
||||
|
reseni.save() |
||||
|
|
||||
|
from treenode.treelib import insert_last_child, create_child |
||||
|
insert_last_child(cislonode, reseninode) |
||||
|
|
||||
|
# Vyrobíme nějaký obsah |
||||
|
# FIXME: Ten, kdo vymyslel TreeLib (mj. týž, kdo psal tenhle kód), |
||||
|
# nevyrobil vhodnou funkci, takže to postavíme pozpátku pomocí create_child |
||||
|
# (které vyrábí _prvního_ syna) |
||||
|
create_child(reseninode, m.CastNode, nadpis="Lorem ipsum") |
||||
|
# Taky ten člověk nevyrobil vracení nových věcí... |
||||
|
castnode = reseninode.first_child |
||||
|
|
||||
|
# Úvodní odstaveček |
||||
|
obsah = "Tohle je zamyšlení o textu lorem ipsum. Začneme a skončíme ukázkou." |
||||
|
text = m.Text.objects.create( |
||||
|
na_web=obsah, |
||||
|
do_cisla=obsah, |
||||
|
) |
||||
|
text.save() |
||||
|
create_child(reseninode, m.TextNode, text=text) |
||||
|
|
||||
|
# Několik odstavců lorem ipsum |
||||
|
for _ in range(rnd.randint(3, 7)): |
||||
|
lipsum = lorem.paragraph() |
||||
|
text = m.Text.objects.create( |
||||
|
na_web=lipsum, |
||||
|
do_cisla=lipsum, |
||||
|
) |
||||
|
text.save() |
||||
|
create_child(castnode, m.TextNode, text=text) |
||||
|
logger.info(f"Článek vygenerován (reseni={reseni.id}, treenode={reseninode.id})") |
@ -0,0 +1,89 @@ |
|||||
|
from django.core.exceptions import ObjectDoesNotExist |
||||
|
|
||||
|
import personalni.models |
||||
|
|
||||
|
import seminar.models as m |
||||
|
|
||||
|
|
||||
|
def resi_v_rocniku(rocnik, cislo=None): |
||||
|
""" Vrátí seznam řešitelů, co vyřešili nějaký problém v daném ročníku, do daného čísla. |
||||
|
Parametry: |
||||
|
rocnik (typu Rocnik) ročník, ze kterého chci řešitele, co něco odevzdali |
||||
|
cislo (typu Cislo) číslo, do kterého včetně se počítá, že v daném |
||||
|
ročníku řešitel něco poslal. |
||||
|
Pokud není zadané, počítají se všechna řešení z daného ročníku. |
||||
|
Výstup: |
||||
|
QuerySet objektů typu Resitel """ |
||||
|
|
||||
|
if cislo is None: |
||||
|
# filtrujeme pouze podle ročníku |
||||
|
return personalni.models.Resitel.objects.filter( |
||||
|
rok_maturity__gte=rocnik.druhy_rok(), |
||||
|
reseni__hodnoceni__deadline_body__cislo__rocnik=rocnik |
||||
|
).distinct() |
||||
|
else: # filtrujeme podle ročníku i čísla |
||||
|
return personalni.models.Resitel.objects.filter( |
||||
|
rok_maturity__gte=rocnik.druhy_rok(), |
||||
|
reseni__hodnoceni__deadline_body__cislo__rocnik=rocnik, |
||||
|
reseni__hodnoceni__deadline_body__cislo__poradi__lte=cislo.poradi |
||||
|
).distinct() |
||||
|
|
||||
|
|
||||
|
def aktivniResitele(cislo, pouze_letosni=False): |
||||
|
""" Vrací QuerySet aktivních řešitelů, což jsou ti, co ještě neodmaturovali |
||||
|
a letos něco poslali (anebo loni něco poslali, pokud jde o první tři čísla). |
||||
|
Parametry: |
||||
|
cislo (typu Cislo) číslo, o které se jedná |
||||
|
pouze_letosni jen řešitelé, kteří tento rok něco poslali |
||||
|
|
||||
|
""" |
||||
|
letos = cislo.rocnik |
||||
|
|
||||
|
# detekujeme, zda jde o první tři čísla či nikoli (tj. zda spamovat řešitele z minulého roku) |
||||
|
zacatek_rocniku = True |
||||
|
try: |
||||
|
if int(cislo.poradi) > 3: |
||||
|
zacatek_rocniku = False |
||||
|
except ValueError: |
||||
|
# if cislo.poradi != '7-8': |
||||
|
# raise ValueError(f'{cislo} je neplatné číslo čísla (není int a není 7-8)') |
||||
|
zacatek_rocniku = False |
||||
|
|
||||
|
# nehledě na číslo chceme jen řešitele, kteří letos něco odevzdali |
||||
|
if pouze_letosni: |
||||
|
zacatek_rocniku = False |
||||
|
|
||||
|
try: |
||||
|
loni = m.Rocnik.objects.get(rocnik=letos.rocnik - 1) |
||||
|
except ObjectDoesNotExist: |
||||
|
# Pro první ročník neexistuje ročník předchozí |
||||
|
zacatek_rocniku = False |
||||
|
|
||||
|
if not zacatek_rocniku: |
||||
|
return resi_v_rocniku(letos, cislo).filter(rok_maturity__gte=letos.druhy_rok()) |
||||
|
else: |
||||
|
# spojíme querysety s řešiteli loni a letos do daného čísla |
||||
|
return (resi_v_rocniku(loni) | resi_v_rocniku(letos, cislo))\ |
||||
|
.distinct().filter(rok_maturity__gte=letos.druhy_rok()) |
||||
|
|
||||
|
|
||||
|
# Pozor: zarovnáno velmi netradičně pro přehlednost |
||||
|
roman_numerals = zip((1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1), # noqa |
||||
|
('M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I')) # noqa |
||||
|
|
||||
|
|
||||
|
def roman(num): |
||||
|
res = "" |
||||
|
for i, n in roman_numerals: |
||||
|
res += n * (num // i) |
||||
|
num %= i |
||||
|
return res |
||||
|
|
||||
|
|
||||
|
def from_roman(rom): |
||||
|
if not rom: |
||||
|
return 0 |
||||
|
for i, n in roman_numerals: |
||||
|
if rom.upper().startswith(n): |
||||
|
return i + from_roman(rom[len(n):]) |
||||
|
raise Exception('Invalid roman numeral: "%s"', rom) |
@ -0,0 +1,584 @@ |
|||||
|
# Dočsasné views |
||||
|
from .docasne import * |
||||
|
|
||||
|
# Zbytek |
||||
|
|
||||
|
from django.shortcuts import get_object_or_404, render |
||||
|
from django.http import HttpResponse |
||||
|
from django.urls import reverse |
||||
|
from django.core.exceptions import ObjectDoesNotExist |
||||
|
from django.views import generic |
||||
|
from django.utils.translation import gettext as _ |
||||
|
from django.http import Http404 |
||||
|
from django.db.models import Q, Sum, Count |
||||
|
from django.views.generic.base import RedirectView |
||||
|
from django.core.exceptions import PermissionDenied |
||||
|
|
||||
|
import seminar.models as s |
||||
|
import seminar.models as m |
||||
|
from seminar.models import Problem, Cislo, Reseni, Nastaveni, Rocnik, \ |
||||
|
Resitel, Novinky, Tema, Clanek, \ |
||||
|
Deadline # Tohle je stare a chceme se toho zbavit. Pouzivejte s.ToCoChci |
||||
|
#from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva |
||||
|
from treenode import treelib |
||||
|
import treenode.templatetags as tnltt |
||||
|
import treenode.serializers as vr |
||||
|
from vysledkovky.utils import body_resitelu, VysledkovkaCisla, \ |
||||
|
VysledkovkaRocniku, VysledkovkaDoTeXu |
||||
|
|
||||
|
from datetime import date, datetime |
||||
|
from itertools import groupby |
||||
|
from collections import OrderedDict |
||||
|
import os |
||||
|
import os.path as op |
||||
|
from django.conf import settings |
||||
|
import unicodedata |
||||
|
import logging |
||||
|
import time |
||||
|
|
||||
|
import personalni.views |
||||
|
|
||||
|
from .. import utils |
||||
|
|
||||
|
# ze starého modelu |
||||
|
#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 temata_v_rocniku(rocnik): |
||||
|
# return Problem.objects.filter(typ=Problem.TYP_TEMA, rocnik=rocnik) |
||||
|
|
||||
|
logger = logging.getLogger(__name__) |
||||
|
|
||||
|
def get_problemy_k_tematu(tema): |
||||
|
return Problem.objects.filter(nadproblem = tema) |
||||
|
|
||||
|
|
||||
|
# FIXME: Pozor, níž je ještě jeden ProblemView! |
||||
|
#class ProblemView(generic.DetailView): |
||||
|
# model = s.Problem |
||||
|
# # Zkopírujeme template_name od TreeNodeView, protože jsme prakticky jen trošku upravený TreeNodeView |
||||
|
# template_name = TreeNodeView.template_name |
||||
|
# |
||||
|
# def get_context_data(self, **kwargs): |
||||
|
# context = super().get_context_data(**kwargs) |
||||
|
# user = self.request.user |
||||
|
# # Teď potřebujeme doplnit tnldata do kontextu. |
||||
|
# # Ošklivý type switch, hezčí by bylo udělat to polymorfni. FIXME. |
||||
|
# if False: |
||||
|
# # Hezčí formátování zbytku :-P |
||||
|
# pass |
||||
|
# elif isinstance(self.object, s.Clanek) or isinstance(self.object, s.Konfera): |
||||
|
# # Tyhle Problémy mají ŘešeníNode |
||||
|
# context['tnldata'] = TNLData.from_treenode(self.object.reseninode,user) |
||||
|
# elif isinstance(self.object, s.Uloha): |
||||
|
# # FIXME: Teď vždycky zobrazujeme i vzorák! Možná by bylo hezčí/lepší mít to stejně jako pro Téma: procházet jen dosažitelné z Ročníku / čísla / whatever |
||||
|
# tnl_zadani = TNLData.from_treenode(self.object.ulohazadaninode,user) |
||||
|
# tnl_vzorak = TNLData.from_treenode(self.object.ulohavzoraknode,user) |
||||
|
# context['tnldata'] = TNLData.from_tnldata_list([tnl_zadani, tnl_vzorak]) |
||||
|
# elif isinstance(self.object, s.Tema): |
||||
|
# rocniknode = self.object.rocnik.rocniknode |
||||
|
# context['tnldata'] = TNLData.filter_treenode(rocniknode, lambda x: isinstance(x, s.TemaVCisleNode)) |
||||
|
# else: |
||||
|
# raise ValueError("Obecný problém nejde zobrazit.") |
||||
|
# return context |
||||
|
|
||||
|
|
||||
|
#class AktualniZadaniView(generic.TemplateView): |
||||
|
# template_name = 'treenode/treenode.html' |
||||
|
|
||||
|
# TODO Co chceme vlastně zobrazovat na této stránce? Zatím je zde aktuální číslo, ale může tu být cokoli jiného... |
||||
|
#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 AktualniZadaniView(request): |
||||
|
nastaveni = get_object_or_404(Nastaveni) |
||||
|
verejne = nastaveni.aktualni_cislo.verejne() |
||||
|
return render(request, 'tvorba/zadani/AktualniZadani.html', |
||||
|
{'nastaveni': nastaveni, |
||||
|
'verejne': verejne, |
||||
|
}, |
||||
|
) |
||||
|
|
||||
|
def ZadaniTemataView(request): |
||||
|
nastaveni = get_object_or_404(Nastaveni) |
||||
|
verejne = nastaveni.aktualni_cislo.verejne() |
||||
|
akt_rocnik = nastaveni.aktualni_cislo.rocnik |
||||
|
temata = s.Tema.objects.filter(rocnik=akt_rocnik, stav='zadany') |
||||
|
return render(request, 'tvorba/tematka/rozcestnik.html', |
||||
|
{ |
||||
|
'tematka': temata, |
||||
|
'verejne': verejne, |
||||
|
}, |
||||
|
) |
||||
|
|
||||
|
|
||||
|
# 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, 'tvorba/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, 'tvorba/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, 'tvorba/tematka/rozcestnik.html', {"tematka": tematka, "rocnik" : nastaveni.aktualni_rocnik().rocnik}) |
||||
|
# |
||||
|
|
||||
|
def ZadaniAktualniVysledkovkaView(request): |
||||
|
nastaveni = get_object_or_404(Nastaveni) |
||||
|
# Aktualni verejna vysledkovka |
||||
|
rocnik = nastaveni.aktualni_rocnik |
||||
|
context = {'vysledkovka': VysledkovkaRocniku(rocnik, True)} |
||||
|
|
||||
|
# kdyz neni verejna vysledkovka, tak zobraz starou |
||||
|
if len(context['vysledkovka'].cisla_rocniku) == 0: |
||||
|
try: |
||||
|
minuly_rocnik = Rocnik.objects.get( |
||||
|
rocnik=(rocnik.rocnik-1)) |
||||
|
rocnik = minuly_rocnik |
||||
|
|
||||
|
# Přepíšeme prázdnou výsledkovku výsledkovkou z minulého ročníku |
||||
|
context['vysledkovka'] = VysledkovkaRocniku(rocnik, True) |
||||
|
except ObjectDoesNotExist: |
||||
|
pass |
||||
|
|
||||
|
context['rocnik'] = rocnik |
||||
|
return render( |
||||
|
request, |
||||
|
'tvorba/zadani/AktualniVysledkovka.html', |
||||
|
context |
||||
|
) |
||||
|
|
||||
|
|
||||
|
### Titulni strana |
||||
|
|
||||
|
def aktualni_temata(rocnik): |
||||
|
""" |
||||
|
Vrací PolymorphicQuerySet témat v daném ročníku, ke kterým se aktuálně dá něco odevzdat. |
||||
|
""" |
||||
|
return Tema.objects.filter(rocnik=rocnik, stav='zadany').order_by('kod') |
||||
|
|
||||
|
|
||||
|
### Archiv |
||||
|
|
||||
|
|
||||
|
class ArchivView(generic.ListView): |
||||
|
model = Rocnik |
||||
|
template_name = 'tvorba/archiv/cisla.html' |
||||
|
|
||||
|
def get_context_data(self, **kwargs): |
||||
|
context = super(ArchivView, self).get_context_data(**kwargs) |
||||
|
|
||||
|
cisla = Cislo.objects.filter(poradi=1) |
||||
|
if not self.request.user.je_org: |
||||
|
cisla = cisla.filter(verejne_db=True) |
||||
|
urls ={} |
||||
|
|
||||
|
for i, c in enumerate(cisla): |
||||
|
# Výchozí nastavení |
||||
|
if c.rocnik not in urls: |
||||
|
urls[c.rocnik] = op.join(settings.STATIC_URL, "tvorba", "no-picture.png") |
||||
|
# NOTE: tohle možná nastavuje poslední titulku |
||||
|
if c.titulka_nahled: |
||||
|
urls[c.rocnik] = c.titulka_nahled.url |
||||
|
|
||||
|
context["object_list"] = urls |
||||
|
|
||||
|
return context |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
class RocnikView(generic.DetailView): |
||||
|
model = Rocnik |
||||
|
template_name = 'tvorba/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() |
||||
|
|
||||
|
return get_object_or_404(queryset,rocnik=self.kwargs.get('rocnik')) |
||||
|
|
||||
|
def get_context_data(self, **kwargs): |
||||
|
context = super(RocnikView, self).get_context_data(**kwargs) |
||||
|
context["vysledkovka"] = VysledkovkaRocniku(context["rocnik"], True) |
||||
|
context["neprazdna_vysledkovka"] = len(context['vysledkovka'].cisla_rocniku) != 0 |
||||
|
context["vysledkovka_neverejna"] = VysledkovkaRocniku(context["rocnik"], False) |
||||
|
return context |
||||
|
|
||||
|
def resiteleRocnikuCsvExportView(request, rocnik): |
||||
|
from personalni.views import dataResiteluCsvResponse |
||||
|
assert request.method in ('GET', 'HEAD') |
||||
|
return dataResiteluCsvResponse( |
||||
|
utils.resi_v_rocniku( |
||||
|
get_object_or_404(m.Rocnik, rocnik=rocnik) |
||||
|
) |
||||
|
) |
||||
|
|
||||
|
|
||||
|
# FIXME: Pozor, výš je ještě jeden ProblemView! |
||||
|
#class ProblemView(generic.DetailView): |
||||
|
# model = Problem |
||||
|
# |
||||
|
# # Používáme funkci, protože přímo template_name neumí mít v přiřazení dost logiky. Ledaže by se to udělalo polymorfně... |
||||
|
# def get_template_names(self, **kwargs): |
||||
|
# # FIXME: Switch podle typu není hezký, ale nechtělo se mi to přepisovat celé. Správně by se tohle mělo řešit polymorfismem. |
||||
|
# spravne_templaty = { |
||||
|
# s.Uloha: "uloha", |
||||
|
# s.Tema: "tema", |
||||
|
# s.Konfera: "konfera", |
||||
|
# s.Clanek: "clanek", |
||||
|
# } |
||||
|
# context = super().get_context_data(**kwargs) |
||||
|
# return ['tvorba/archiv/problem_' + spravne_templaty[context['object'].__class__] + '.html'] |
||||
|
# |
||||
|
# def get_context_data(self, **kwargs): |
||||
|
# context = super().get_context_data(**kwargs) |
||||
|
# # Musí se používat context['object'], protože nevíme, jestli dostaneme úložku, téma, článek, .... a tyhle věci vyrábějí různé klíče. |
||||
|
# if not context['object'].verejne() and not self.request.user.je_org: |
||||
|
# raise PermissionDenied() |
||||
|
# if isinstance(context['object'], Clanek): |
||||
|
# context['reseni'] = Reseni.objects.filter(problem=context['object']).select_related('resitel').order_by('resitel__prijmeni') |
||||
|
# return context |
||||
|
|
||||
|
|
||||
|
|
||||
|
class CisloView(generic.DetailView): |
||||
|
# FIXME zobrazování témátek a vůbec, teď je tam jen odkaz na číslo v pdf |
||||
|
model = Cislo |
||||
|
template_name = 'tvorba/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') |
||||
|
poradi_arg = self.kwargs.get('cislo') |
||||
|
queryset = queryset.filter(rocnik__rocnik=rocnik_arg, poradi=poradi_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) |
||||
|
|
||||
|
cislo = context['cislo'] |
||||
|
context['prevcislo'] = Cislo.objects.filter((Q(rocnik__lt=self.object.rocnik) | Q(poradi__lt=self.object.poradi))&Q(rocnik__lte=self.object.rocnik)).first() |
||||
|
|
||||
|
deadliny = Deadline.objects.filter(cislo=cislo).reverse() |
||||
|
deadliny_s_vysledkovkami = [] |
||||
|
|
||||
|
nadpisy = { |
||||
|
m.Deadline.TYP_CISLA: "Výsledkovka", |
||||
|
m.Deadline.TYP_PRVNI: "Výsledkovka do prvního deadlinu", |
||||
|
m.Deadline.TYP_PRVNI_A_SOUS: "Výsledkovka do prvního deadlinu a deadlinu pro účast na soustředění", |
||||
|
m.Deadline.TYP_SOUS: "Výsledkovka do deadlinu pro účast na soustředění", |
||||
|
} |
||||
|
|
||||
|
for deadline in deadliny: |
||||
|
if self.request.user.je_org | deadline.verejna_vysledkovka: |
||||
|
deadliny_s_vysledkovkami.append((deadline, nadpisy[deadline.typ], VysledkovkaCisla(cislo, not self.request.user.je_org, deadline))) |
||||
|
|
||||
|
context['deadliny_s_vysledkovkami'] = deadliny_s_vysledkovkami |
||||
|
return context |
||||
|
|
||||
|
|
||||
|
class ArchivTemataView(generic.ListView): |
||||
|
model = Problem |
||||
|
template_name = 'tvorba/archiv/temata.html' |
||||
|
queryset = Tema.objects.filter(stav=Problem.STAV_ZADANY).select_related('rocnik').order_by('rocnik', 'kod') |
||||
|
|
||||
|
def get_context_data(self, *args, **kwargs): |
||||
|
ctx = super().get_context_data(*args, **kwargs) |
||||
|
ctx['rocniky'] = OrderedDict() |
||||
|
for rocnik, temata in groupby(ctx['object_list'], lambda tema: tema.rocnik): |
||||
|
ctx['rocniky'][rocnik] = list(temata) |
||||
|
return ctx |
||||
|
|
||||
|
class OdmenyView(generic.TemplateView): |
||||
|
template_name = 'tvorba/archiv/odmeny.html' |
||||
|
|
||||
|
def get_context_data(self, **kwargs): |
||||
|
context = super().get_context_data(**kwargs) |
||||
|
fromcislo = get_object_or_404(Cislo, rocnik=self.kwargs.get('frocnik'), poradi=self.kwargs.get('fcislo')) |
||||
|
tocislo = get_object_or_404(Cislo, rocnik=self.kwargs.get('trocnik'), poradi=self.kwargs.get('tcislo')) |
||||
|
resitele = utils.aktivniResitele(tocislo) |
||||
|
|
||||
|
def get_diff(from_deadline: Deadline, to_deadline: Deadline): |
||||
|
frombody = body_resitelu(resitele=resitele, jen_verejne=False, do=from_deadline) |
||||
|
tobody = body_resitelu(resitele=resitele, jen_verejne=False, do=to_deadline) |
||||
|
outlist = [] |
||||
|
for resitel in resitele: |
||||
|
fbody = frombody.get(resitel.id, 0) |
||||
|
tbody = tobody.get(resitel.id, 0) |
||||
|
ftitul = resitel.get_titul(fbody) |
||||
|
ttitul = resitel.get_titul(tbody) |
||||
|
if ftitul != ttitul: |
||||
|
outlist.append({'jmeno': resitel.osoba.plne_jmeno(), 'ftitul': ftitul, 'ttitul': ttitul}) |
||||
|
return outlist |
||||
|
|
||||
|
def posledni_deadline_oprava(cislo: Cislo) -> Deadline: |
||||
|
posledni_deadline = cislo.posledni_deadline |
||||
|
if posledni_deadline is None: |
||||
|
return Deadline.objects.filter(Q(cislo__poradi__lt=cislo.poradi, cislo__rocnik=cislo.rocnik) | Q(cislo__rocnik__rocnik__lt=cislo.rocnik.rocnik)).order_by("deadline").last() |
||||
|
return posledni_deadline |
||||
|
|
||||
|
context["from_cislo"] = fromcislo |
||||
|
context["to_cislo"] = tocislo |
||||
|
from_deadline = posledni_deadline_oprava(fromcislo) |
||||
|
to_deadline = posledni_deadline_oprava(tocislo) |
||||
|
context["from_deadline"] = from_deadline |
||||
|
context["to_deadline"] = to_deadline |
||||
|
context["zmeny"] = get_diff(from_deadline, to_deadline) |
||||
|
|
||||
|
return context |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
### Generovani vysledkovky |
||||
|
|
||||
|
class CisloVysledkovkaView(CisloView): |
||||
|
"""View vytvořené pro stránku zobrazující výsledkovku čísla v TeXu.""" |
||||
|
|
||||
|
model = Cislo |
||||
|
template_name = 'tvorba/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 |
||||
|
|
||||
|
def get_context_data(self, **kwargs): |
||||
|
context = super(CisloVysledkovkaView, self).get_context_data() |
||||
|
cislo = context['cislo'] |
||||
|
|
||||
|
cislopred = cislo.predchozi() |
||||
|
if cislopred is not None: |
||||
|
context['vysledkovka'] = VysledkovkaDoTeXu( |
||||
|
cislo, |
||||
|
od_vyjma=cislopred.zlomovy_deadline_pro_papirove_cislo(), |
||||
|
do_vcetne=cislo.zlomovy_deadline_pro_papirove_cislo(), |
||||
|
) |
||||
|
else: |
||||
|
context['vysledkovka'] = VysledkovkaCisla( |
||||
|
cislo, |
||||
|
jen_verejne=False, |
||||
|
do_deadlinu=cislo.zlomovy_deadline_pro_papirove_cislo(), |
||||
|
) |
||||
|
return context |
||||
|
|
||||
|
|
||||
|
# Podle předchozího |
||||
|
class PosledniCisloVysledkovkaView(generic.DetailView): |
||||
|
"""View vytvořené pro zobrazení výsledkovky posledního čísla v TeXu.""" |
||||
|
|
||||
|
model = Rocnik |
||||
|
template_name = 'tvorba/archiv/cislo_vysledkovka.tex' |
||||
|
content_type = 'text/plain; charset=UTF8' |
||||
|
|
||||
|
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(PosledniCisloVysledkovkaView, self).get_context_data() |
||||
|
rocnik = context['rocnik'] |
||||
|
cislo = rocnik.cisla.order_by("poradi").filter(deadline_v_cisle__isnull=False).last() |
||||
|
if cislo is None: |
||||
|
raise Http404(f"Ročník {rocnik.rocnik} nemá číslo s deadlinem.") |
||||
|
cislopred = cislo.predchozi() |
||||
|
context['vysledkovka'] = VysledkovkaDoTeXu( |
||||
|
cislo, |
||||
|
od_vyjma=cislopred.zlomovy_deadline_pro_papirove_cislo(), |
||||
|
do_vcetne=cislo.deadline_v_cisle.order_by("deadline").last(), |
||||
|
) |
||||
|
return context |
||||
|
|
||||
|
|
||||
|
class RocnikVysledkovkaView(RocnikView): |
||||
|
""" View vytvořené pro stránku zobrazující výsledkovku ročníku v TeXu.""" |
||||
|
model = Rocnik |
||||
|
template_name = 'tvorba/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 |
||||
|
|
||||
|
def cisloObalkyView(request, rocnik, cislo): |
||||
|
realne_cislo = get_object_or_404(Cislo, poradi=cislo, rocnik__rocnik=rocnik) |
||||
|
return personalni.views.obalkyView(request, utils.aktivniResitele(realne_cislo)) |
||||
|
|
||||
|
|
||||
|
|
||||
|
### Tituly |
||||
|
def TitulyViewRocnik(request, rocnik): |
||||
|
return TitulyView(request, rocnik, None) |
||||
|
|
||||
|
|
||||
|
def TitulyView(request, rocnik, cislo): |
||||
|
""" View pro stažení makra titulů v TeXu.""" |
||||
|
rocnik_obj = get_object_or_404(Rocnik, rocnik = rocnik) |
||||
|
resitele = Resitel.objects.filter(rok_maturity__gte = rocnik_obj.prvni_rok) |
||||
|
|
||||
|
asciijmena = [] |
||||
|
jmenovci = False # detekuje, zda jsou dva řešitelé jmenovci (modulo nabodeníčka), |
||||
|
# pokud ano, vrátí se jako true |
||||
|
if cislo is not None: |
||||
|
cislo_obj = get_object_or_404(Cislo, rocnik=rocnik_obj, poradi=cislo) |
||||
|
slovnik_s_body = body_resitelu(do=cislo_obj.zlomovy_deadline_pro_papirove_cislo(), jen_verejne=False) |
||||
|
else: |
||||
|
slovnik_s_body = body_resitelu(do=Deadline.objects.filter(cislo__rocnik=rocnik_obj).last(), jen_verejne=False) |
||||
|
|
||||
|
for resitel in resitele: |
||||
|
resitel.titul = resitel.get_titul(slovnik_s_body[resitel.id]) |
||||
|
jmeno = resitel.osoba.jmeno+resitel.osoba.prijmeni |
||||
|
# převedeme jména a příjmení řešitelů do ASCII |
||||
|
ascii_jmeno_bytes = unicodedata.normalize('NFKD', jmeno).encode("ascii","ignore") |
||||
|
# vrátí se byte string, převedeme na standardní string |
||||
|
ascii_jmeno_divnoznaky = str(ascii_jmeno_bytes, "utf-8", "ignore").replace(" ","") |
||||
|
resitel.ascii = ''.join(a for a in ascii_jmeno_divnoznaky if a.isalnum()) |
||||
|
if resitel.ascii not in asciijmena: |
||||
|
asciijmena.append(resitel.ascii) |
||||
|
else: |
||||
|
jmenovci = True |
||||
|
|
||||
|
return render(request, 'tvorba/archiv/tituly.tex', |
||||
|
{'resitele': resitele,'jmenovci':jmenovci},content_type="text/plain") |
||||
|
|
||||
|
|
||||
|
### Články |
||||
|
def group_by_rocnik(clanky): |
||||
|
''' Vezme zadaný seznam článků a seskupí je podle ročníku. |
||||
|
Vrátí seznam seznamů článků ze stejného ročníku.''' |
||||
|
if len(clanky) == 0: |
||||
|
return clanky |
||||
|
clanky.order_by('cislo__rocnik__rocnik') |
||||
|
skupiny_clanku = [] |
||||
|
skupina = [] |
||||
|
|
||||
|
rocnik = clanky.first().cislo.rocnik.rocnik # první ročník |
||||
|
for clanek in clanky: |
||||
|
if clanek.cislo.rocnik.rocnik == rocnik: |
||||
|
skupina.append(clanek) |
||||
|
else: |
||||
|
skupiny_clanku.append(skupina) |
||||
|
skupina = [] |
||||
|
skupina.append(clanek) |
||||
|
rocnik = clanek.cislo.rocnik.rocnik |
||||
|
skupiny_clanku.append(skupina) |
||||
|
return skupiny_clanku |
||||
|
|
||||
|
|
||||
|
# FIXME: clanky jsou vsechny, pokud budou i neresitelske, tak se take zobrazi |
||||
|
# FIXME: Původně tu byl kód přímo v těle třídy, což rozbíjelo migrace. Opravil jsem, ale vůbec nevím, jestli to funguje. |
||||
|
class ClankyResitelView(generic.ListView): |
||||
|
model = Problem |
||||
|
template_name = 'tvorba/clanky/resitelske_clanky.html' |
||||
|
|
||||
|
# FIXME: QuerySet není pole! |
||||
|
def get_queryset(self): |
||||
|
clanky = Clanek.objects.filter(stav=Problem.STAV_VYRESENY).select_related('cislo__rocnik').order_by('-cislo__rocnik__rocnik') |
||||
|
queryset = [] |
||||
|
skupiny_clanku = group_by_rocnik(clanky) |
||||
|
for skupina in skupiny_clanku: |
||||
|
skupina.sort(key=lambda clanek: clanek.kod_v_rocniku) |
||||
|
for clanek in skupina: |
||||
|
queryset.append(clanek) |
||||
|
return queryset |
||||
|
|
||||
|
# FIXME: pokud chceme orgoclanky, tak nejak zavest do modelu a podle toho odkomentovat a upravit |
||||
|
#class ClankyOrganizatorView(generic.ListView)<F12>: |
||||
|
# model = Problem |
||||
|
# template_name = 'tvorba/clanky/organizatorske_clanky.html' |
||||
|
# queryset = Problem.objects.filter(stav=Problem.STAV_ZADANY).select_related('cislo_zadani__rocnik').order_by('-cislo_zadani__rocnik__rocnik', 'kod') |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
class AktualniRocnikRedirectView(RedirectView): |
||||
|
permanent=False |
||||
|
pattern_name = 'seminar_rocnik' |
||||
|
|
||||
|
def get_redirect_url(self, *args, **kwargs): |
||||
|
aktualni_rocnik = m.Nastaveni.get_solo().aktualni_rocnik.rocnik |
||||
|
return super().get_redirect_url(rocnik=aktualni_rocnik, *args, **kwargs) |
@ -1 +1,6 @@ |
|||||
|
from solo.admin import SingletonModelAdmin |
||||
from django.contrib import admin |
from django.contrib import admin |
||||
|
|
||||
|
from .models import Nastaveni |
||||
|
|
||||
|
admin.site.register(Nastaveni, SingletonModelAdmin) |
||||
|
@ -1,13 +1,11 @@ |
|||||
import datetime |
|
||||
import os |
import os |
||||
import random |
|
||||
|
|
||||
from django.core.management.base import BaseCommand |
from django.core.management.base import BaseCommand |
||||
from django.core.management import call_command |
from django.core.management import call_command |
||||
from django.conf import settings |
from django.conf import settings |
||||
|
|
||||
from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni |
from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni |
||||
from seminar.testutils import create_test_data |
from various.testutils import create_test_data |
||||
import django.contrib.auth |
import django.contrib.auth |
||||
User = django.contrib.auth.get_user_model() |
User = django.contrib.auth.get_user_model() |
||||
|
|
@ -0,0 +1,16 @@ |
|||||
|
{% extends 'base.html' %} |
||||
|
|
||||
|
{% load humanize %} |
||||
|
{% load static %} |
||||
|
|
||||
|
|
||||
|
{% block content %} |
||||
|
|
||||
|
<div class=jakresit> |
||||
|
|
||||
|
{% include 'various/jakresit/jakresit_1.svg' %} |
||||
|
{% include 'various/jakresit/jakresit_2.svg' %} |
||||
|
{% include 'various/jakresit/jakresit_3.svg' %} |
||||
|
|
||||
|
</div> |
||||
|
{% endblock %} |
Before Width: | Height: | Size: 664 KiB After Width: | Height: | Size: 664 KiB |
Before Width: | Height: | Size: 689 KiB After Width: | Height: | Size: 689 KiB |
Before Width: | Height: | Size: 767 KiB After Width: | Height: | Size: 767 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
@ -0,0 +1,135 @@ |
|||||
|
import datetime |
||||
|
import random |
||||
|
import logging |
||||
|
|
||||
|
import django.contrib.auth |
||||
|
from django.contrib.flatpages.models import FlatPage |
||||
|
from django.contrib.sites.models import Site |
||||
|
from django.db import transaction |
||||
|
|
||||
|
from seminar.models import Rocnik, Cislo, Nastaveni, Osoba, Organizator |
||||
|
|
||||
|
from korektury.testutils import create_test_pdf |
||||
|
from novinky.testutils import gen_novinky |
||||
|
from personalni.testutils import gen_organizatori, gen_osoby, gen_prijemci, gen_resitele, gen_skoly |
||||
|
from soustredeni.testutils import gen_soustredeni, gen_konfery |
||||
|
from tvorba.testutils import gen_cisla, gen_clanek, gen_dlouhe_tema, gen_rocniky, gen_temata, gen_ulohy_do_cisla, gen_ulohy_k_tematum |
||||
|
|
||||
|
logger = logging.getLogger(__name__) |
||||
|
|
||||
|
User = django.contrib.auth.get_user_model() |
||||
|
|
||||
|
|
||||
|
@transaction.atomic |
||||
|
def create_test_data(size=6, rnd=None): |
||||
|
logger.info('Vyrábím testovací data (size={})...'.format(size)) |
||||
|
|
||||
|
assert size >= 1 |
||||
|
# pevna pseudo-nahodnost |
||||
|
rnd = rnd or random.Random(x=42) |
||||
|
|
||||
|
# static URL stranky |
||||
|
# FIXME: nakopirovat sem vsechny z produkcni databaze |
||||
|
s = Site.objects.filter(name="example.com") |
||||
|
f = FlatPage.objects.create( |
||||
|
url="/", title="Seminář M&M", |
||||
|
content="<p>Vítejte na stránce semináře MaM!</p>", |
||||
|
) |
||||
|
print(s) |
||||
|
f.sites.add(s[0]) |
||||
|
f.save() |
||||
|
|
||||
|
# users |
||||
|
admin = User.objects.create_superuser( |
||||
|
username='admin', email='', password='admin', |
||||
|
) |
||||
|
os_admin = Osoba.objects.create( |
||||
|
user=admin, jmeno='admin', prijmeni='admin', |
||||
|
prezdivka='admin', osloveni='', email='admin@admin.admin', |
||||
|
telefon='123 456 789', datum_narozeni=datetime.date(2000, 1, 1), |
||||
|
ulice='admin', mesto='admin', psc='100 00', |
||||
|
datum_registrace=datetime.date(2020, 9, 6), |
||||
|
) |
||||
|
or_admin = Organizator.objects.create( |
||||
|
osoba=os_admin, organizuje_od=None, organizuje_do=None, |
||||
|
strucny_popis_organizatora="Organizátor k uživateli Admin", |
||||
|
) |
||||
|
|
||||
|
usernames = ['anet', 'bara', 'cyril', 'david', 'eva', 'filip'] |
||||
|
users = [] |
||||
|
for usr in usernames[:size]: |
||||
|
u = User.objects.create_user(username=usr, password=usr) |
||||
|
u.first_name = usr.capitalize() |
||||
|
u.save() |
||||
|
users.append(u) |
||||
|
print(users) |
||||
|
|
||||
|
# skoly |
||||
|
skoly = gen_skoly() |
||||
|
|
||||
|
# osoby |
||||
|
osoby = gen_osoby(rnd, size) |
||||
|
|
||||
|
# resitele a organizatori |
||||
|
last_rocnik = 25 |
||||
|
organizatori = gen_organizatori(rnd, osoby, last_rocnik) |
||||
|
resitele = gen_resitele(rnd, osoby, skoly) |
||||
|
|
||||
|
# generování novinek |
||||
|
novinky = gen_novinky(rnd, organizatori) |
||||
|
|
||||
|
# prijemci |
||||
|
prijemci = gen_prijemci(rnd, osoby) |
||||
|
|
||||
|
# rocniky |
||||
|
rocniky = gen_rocniky(last_rocnik, size) |
||||
|
|
||||
|
# cisla |
||||
|
# rocnik_cisla je pole polí čísel (typ Cislo), vnitřní pole odpovídají jednotlivým ročníkům. |
||||
|
rocnik_cisla = gen_cisla(rnd, rocniky) |
||||
|
|
||||
|
# generování obyčejných úloh do čísel |
||||
|
gen_ulohy_do_cisla(rnd, organizatori, resitele, rocnik_cisla, rocniky, size) |
||||
|
|
||||
|
# generování témat, zatím v prvních třech číslech po jednom |
||||
|
# FIXME: více témat |
||||
|
# rocnik_temata je pole polí trojic (první číslo :int, poslední číslo :int, téma:Tema), přičemž každé vnitřní pole odpovídá ročníku a FIXME: je to takhle fuj a když to někdo vidí poprvé, tak je z toho smutný, protože vůbec neví, co se děje a co má čekat. |
||||
|
rocnik_temata = gen_temata(rnd, rocniky, rocnik_cisla, organizatori) |
||||
|
|
||||
|
rocnik = Rocnik.objects.filter(rocnik=23).first() |
||||
|
dlouhe_tema = gen_dlouhe_tema( |
||||
|
rnd, organizatori, rocnik, "Strašně dlouhé téma", |
||||
|
"MFI", 8, |
||||
|
) |
||||
|
|
||||
|
# generování úloh k tématům ve všech číslech |
||||
|
gen_ulohy_k_tematum(rnd, rocniky, rocnik_cisla, rocnik_temata, organizatori, resitele) |
||||
|
|
||||
|
# generování soustředění |
||||
|
soustredeni = gen_soustredeni(size, resitele, organizatori, rnd=rnd) |
||||
|
|
||||
|
# generování konfer |
||||
|
konfery = gen_konfery(size, organizatori, soustredeni, rnd=rnd) |
||||
|
|
||||
|
# vytvoreni pdf ke korekturam |
||||
|
create_test_pdf(rnd, organizatori) |
||||
|
|
||||
|
# TODO: nastavi správně, kolik se čeho generuje, aby rozsahy přibližně odpovídaly |
||||
|
# FIXME: misto typu ruzne typy objektu a vnoreni do sebe (Tom nechápe, co je tímto fixme míněno) |
||||
|
# TODO: vytvorit temata s ruznymi vlakny |
||||
|
# TODO: nagenerovat starsim rocnikum pohadku |
||||
|
# TODO: nagenerovat články |
||||
|
# TODO: vecpat obrázky všude, kde to jde |
||||
|
# TODO: mezičíslo node |
||||
|
# TODO: přidat ke konferám řešení a dát je do čísel |
||||
|
|
||||
|
# Dohackované vytvoření jednoho článku |
||||
|
gen_clanek(rnd, organizatori, resitele) |
||||
|
|
||||
|
# TODO: přidat články včetně zařazení do struktury treenodů, |
||||
|
# a následně otestovat konsistency check databáze z utils.py |
||||
|
# pomocí stránky /stav |
||||
|
|
||||
|
# obecné nastavení semináře, musí být už přidané ročníky a čísla, jinak se nastaví divně |
||||
|
nastaveni = Nastaveni.objects.create( |
||||
|
aktualni_cislo=Cislo.objects.all()[1]) |
@ -0,0 +1,9 @@ |
|||||
|
from django.urls import path |
||||
|
from .views.final import TitulniStranaView, JakResitView, StavDatabazeView |
||||
|
from personalni.utils import org_required |
||||
|
|
||||
|
urlpatterns = [ |
||||
|
path('', TitulniStranaView.as_view(), name='titulni_strana'), |
||||
|
path('jak-resit/', JakResitView.as_view(), name='jak_resit'), |
||||
|
path('stav', org_required(StavDatabazeView), name='stav_databaze'), |
||||
|
] |