# -*- coding: utf-8 -*-
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í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 ( 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 ] )