# -*- coding: utf-8 -*- import datetime from django.contrib.auth.models import Permission from django.contrib.auth.models import Group from pytz import timezone 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 = rnd.randint(0,1) jmeno = rnd.choice([jmena_m, jmena_f][pohlavi]) prijmeni = rnd.choice([prijmeni_m, prijmeni_f][pohlavi]) 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][pohlavi]) prijmeni = rnd.choice([prijmeni_m, prijmeni_f][pohlavi]) 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, pohlavi_muz = pohlavi, 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=timezone('CET'), ) do = datetime.datetime( year=od.year + rnd.randint(1, 6), month=rnd.randint(1, 12), day=rnd.randint(1, 28), tzinfo=timezone('CET'), ) #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', pohlavi_muz=1, 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])