You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

867 lines
31 KiB

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, Osoba, Organizator, Prijemce, Tema, Uloha, 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
from soustredeni.testutils import gen_soustredeni, gen_konfery
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_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 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&iacute;tejte na str&aacute;nce semin&aacute;ř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(size, 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])