Browse Source

Merge branch 'data_migrations' into treelib_tests

middleware_test
Pavel 'LEdoian' Turinsky 4 years ago
parent
commit
e345ab8e1f
  1. 36
      galerie/static/galerie/prvky/dalsi.svg
  2. 38
      galerie/static/galerie/prvky/predchozi.svg
  3. 8
      seminar/models.py
  4. 10
      seminar/static/seminar/prihlaska.js
  5. 14
      seminar/templates/seminar/archiv/temata.html
  6. 85
      seminar/templates/seminar/edit.html
  7. 7
      seminar/templates/seminar/login.html
  8. 118
      seminar/templates/seminar/prihlaska.html
  9. 25
      seminar/templates/seminar/prihlaska_field.html
  10. 241
      seminar/testutils.py
  11. 41
      seminar/treelib.py
  12. 5
      seminar/urls.py
  13. 62
      seminar/views/unicodecsv.py
  14. 20
      seminar/views/views_all.py

36
galerie/static/galerie/prvky/dalsi.svg

@ -5,11 +5,39 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25.135418mm"
height="42.333332mm"
viewBox="0 0 25.135418 42.333331"
version="1.1"
id="svg851">
id="svg851"
sodipodi:docname="dalsi.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1850"
inkscape:window-height="1136"
id="namedview7"
showgrid="true"
inkscape:zoom="23.600001"
inkscape:cx="18.587131"
inkscape:cy="74.924864"
inkscape:window-x="70"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg851">
<inkscape:grid
type="xygrid"
id="grid833" />
</sodipodi:namedview>
<defs
id="defs845" />
<metadata
@ -28,8 +56,10 @@
id="layer1"
transform="matrix(-1.0282842,0,0,1,111.4545,-88.415317)">
<path
d="m 108.38881,88.415317 -6.43264,21.166663 6.43264,21.16667 -18.011397,-21.16667 z"
d="m 98.096584,101.64448 1.286528,1.32292 -5.660724,5.82083 h 13.379892 v 1.5875 H 93.722388 l 5.660724,5.82083 -1.286528,1.32292 -7.719171,-7.9375 z"
style="fill:#e84e10;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.23177969"
id="path44-3" />
id="path44-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccc" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

38
galerie/static/galerie/prvky/predchozi.svg

@ -5,11 +5,39 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25.135418mm"
height="42.333332mm"
viewBox="0 0 25.135418 42.333331"
version="1.1"
id="svg851">
id="svg851"
sodipodi:docname="predchozi.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1850"
inkscape:window-height="1136"
id="namedview7"
showgrid="true"
inkscape:zoom="4.1719301"
inkscape:cx="124.03002"
inkscape:cy="97.874031"
inkscape:window-x="70"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg851">
<inkscape:grid
type="xygrid"
id="grid833" />
</sodipodi:namedview>
<defs
id="defs845" />
<metadata
@ -26,10 +54,12 @@
</metadata>
<g
id="layer1"
transform="matrix(-1.0282842,0,0,1,111.4545,-88.415317)">
transform="matrix(1.0282842,0,0,1,-86.319083,-88.415315)">
<path
d="m 83.944774,88.415319 6.43264,21.166661 -6.43264,21.16667 18.011396,-21.16667 z"
d="m 98.096584,101.64448 1.286528,1.32292 -5.660724,5.82083 h 13.379892 v 1.5875 H 93.722388 l 5.660724,5.82083 -1.286528,1.32292 -7.719171,-7.9375 z"
style="fill:#e84e10;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.23177969"
id="path44-3" />
id="path44-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccc" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

8
seminar/models.py

@ -14,6 +14,7 @@ from django.utils.text import slugify
from django.urls import reverse
from django.core.cache import cache
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.contenttypes.models import ContentType
from django.utils.text import get_valid_filename
from imagekit.models import ImageSpecField, ProcessedImageField
from imagekit.processors import ResizeToFit, Transpose
@ -27,6 +28,7 @@ from reversion import revisions as reversion
from seminar.utils import roman, FirstTagParser # Pro získání úryvku z TextNode
from unidecode import unidecode # Používám pro získání ID odkazu (ještě je to někde po někom zakomentované)
from seminar.treelib import safe_pred
from polymorphic.models import PolymorphicModel
@ -1303,6 +1305,10 @@ class TreeNode(PolymorphicModel):
def aktualizuj_nazev(self):
raise NotImplementedError("Pokus o aktualizaci názvu obecného TreeNode místo konkrétní instance")
def get_admin_url(self):
content_type = ContentType.objects.get_for_model(self.__class__)
return reverse("admin:%s_%s_change" % (content_type.app_label, content_type.model), args=(self.id,))
class RocnikNode(TreeNode):
class Meta:
db_table = 'seminar_nodes_rocnik'
@ -1338,7 +1344,7 @@ class MezicisloNode(TreeNode):
# TODO: Využít TreeLib
def aktualizuj_nazev(self):
if self.prev:
if safe_pred(self) is not None:
if (self.prev.get_real_instance_class() != CisloNode and
self.prev.get_real_instance_class() != MezicisloNode):
raise ValueError("Předchůdce není číslo!")

10
seminar/static/seminar/prihlaska.js

@ -3,7 +3,7 @@ function addrCountryChanged(){
var stat_text = document.getElementById('id_li_stat_text');
var stat = stat_select[stat_select.selectedIndex].value;
if (stat === "other"){
stat_text.style.display="block";
stat_text.style.display="revert";
} else {
stat_text.style.display="none";
$('#id_stat_text').val("");
@ -12,18 +12,22 @@ function addrCountryChanged(){
function hideSchoolTextfields(){
var skola_nazev = document.getElementById('id_li_skola_nazev');
var skola_adresa = document.getElementById('id_li_skola_adresa');
var skola_vypln = document.getElementById('id_li_skola_vypln');
skola_nazev.style.display="none";
skola_adresa.style.display="none";
skola_vypln.style.display="none";
}
function schoolNotInList(){
var skola_nazev = document.getElementById('id_li_skola_nazev');
var skola_adresa = document.getElementById('id_li_skola_adresa');
var skola_vypln = document.getElementById('id_li_skola_vypln');
// FIXME nefunguje a nevim proc (TypeError: $(...).select2 is not a function)
//var skola_select = $('#id_skola').select2();
//skola_select.val(null).trigger('change');
skola_nazev.style.display="block";
skola_adresa.style.display="block";
skola_vypln.style.display="revert";
skola_nazev.style.display="revert";
skola_adresa.style.display="revert";
}
document.addEventListener("DOMContentLoaded", function(){

14
seminar/templates/seminar/archiv/temata.html

@ -7,17 +7,13 @@
{% endblock %}{% endblock%}
</h1>
{% for tema in object_list %}
{% with tema.cislo_zadani.rocnik.rocnik as rocnik %}
{% ifchanged rocnik %}
{% if not forloop.first %}</ul>{% endif %}
<h2>{{ rocnik }}. ročník</h2>
{% for rocnik, temata in rocniky.items %}
<h2>Ročník {{ rocnik }}</h2>
<ul>
{% endifchanged %}
<li>
<a href="{{ tema.verejne_url }}">{{ tema.kod_v_rocniku }}: {{ tema.nazev }}</a>
{% endwith %}
{% for tema in temata %}
<li><a href="{{ tema.verejne_utl }}"> {{ tema.kod_v_rocniku }}: {{ tema.nazev }} </a></li>
{% endfor %}
</ul>
{% endfor %}
{% endblock content %}

85
seminar/templates/seminar/edit.html

@ -15,59 +15,77 @@
<form action="{% url 'seminar_resitel_edit' %}" method="post">
{% csrf_token %}
{{form.non_field_errors}}
<ul class="form">
<li>
<hr>
<h4>
Přihlašovací údaje
</li><li>
</h4>
<table class="form">
{% include "seminar/prihlaska_field.html" with field=form.username %}
</li><li>
</table>
<hr>
<h4>
Osobní údaje
</li><li>
</h4>
<table class="form">
{% include "seminar/prihlaska_field.html" with field=form.jmeno %}
</li><li>
{% include "seminar/prihlaska_field.html" with field=form.prijmeni %}
</li><li>
{% include "seminar/prihlaska_field.html" with field=form.pohlavi_muz%}
</li><li>
{% include "seminar/prihlaska_field.html" with field=form.email %}
</li><li>
{% include "seminar/prihlaska_field.html" with field=form.telefon %}
</li><li>
{% include "seminar/prihlaska_field.html" with field=form.datum_narozeni %}
</li><li>
</table>
<hr>
<h4>
Bydliště
</li><li>
</h4>
<table class="form">
{% include "seminar/prihlaska_field.html" with field=form.ulice %}
</li><li>
{% include "seminar/prihlaska_field.html" with field=form.mesto %}
</li><li>
{% include "seminar/prihlaska_field.html" with field=form.psc %}
</li><li>
{% include "seminar/prihlaska_field.html" with field=form.stat %}
</li>
<li id="id_li_stat_text">
{% include "seminar/prihlaska_field.html" with field=form.stat_text %}
</li><li>
{% include "seminar/prihlaska_field.html" with field=form.stat_text id="id_li_stat_text"%}
</table>
<hr>
<h4>
Škola
</h4>
<table class="form">
{% include "seminar/prihlaska_field.html" with field=form.skola %}
</li><li>
<button id="id_skola_text_button" type="button">Škola není v seznamu</button>
</li>
<li id="id_li_skola_nazev">
Vyplň prosím celý název a adresu školy.<br>
{% include "seminar/prihlaska_field.html" with field=form.skola_nazev %}
</li>
<li id="id_li_skola_adresa">
{% include "seminar/prihlaska_field.html" with field=form.skola_adresa %}
</li><li>
<tr><td colspan="2" ><button id="id_skola_text_button" type="button">Škola není v seznamu</button></td></tr>
<tr><td id="id_li_skola_vypln" colspan="2">Vyplň prosím celý název a adresu školy.</td></tr>
{% include "seminar/prihlaska_field.html" with field=form.skola_nazev id="id_li_skola_nazev" %}
{% include "seminar/prihlaska_field.html" with field=form.skola_adresa id="id_li_skola_adresa" %}
{% include "seminar/prihlaska_field.html" with field=form.rok_maturity %}
</li><li>
</table>
<hr>
<h4>
Pošta
</h4>
<table class="form">
{% include "seminar/prihlaska_field.html" with field=form.zasilat %}
</li><li>
</table>
<hr>
<h4>
Zasílání propagačních materiálů
</h4>
<table class="form">
{% include "seminar/prihlaska_field.html" with field=form.spam %}
</li>
</ul>
</table>
<hr>
<input type="submit" value="Změnit">
</form>
<script>
@ -75,4 +93,3 @@ $("#id_stat").on("change",addrCountryChanged);
$("#id_skola_text_button").on("click",schoolNotInList);
</script>
{% endblock %}

7
seminar/templates/seminar/login.html

@ -10,9 +10,9 @@
</h1>
<form action="{% url 'login' %}" method="post">
{% csrf_token %}
<ul class="form">
{{ form.as_ul }}
</ul>
<table class="form">
{{ form.as_table }}
</table>
{# Django si posílá jméno další stránky jako obsah formuláře a výchozí hodnota (mi přišlo, že) nejde změnit... #}
<input type="hidden" name='next' value="{{ next }}">
<input type="submit" value="Přihlásit">
@ -23,4 +23,3 @@
{% endblock %}

118
seminar/templates/seminar/prihlaska.html

@ -14,92 +14,93 @@
{% endblock %}{% endblock %}
</h1>
<form action="{% url 'seminar_prihlaska' %}" method="post">
{% csrf_token %}
{{form.non_field_errors}}
<ul class="form">
<li>
<hr>
<h4>
Přihlašovací údaje
</li>
<li>
</h4>
<table class="form">
{% include "seminar/prihlaska_field.html" with field=form.username %}
</li>
<li>
{% include "seminar/prihlaska_field.html" with field=form.password %}
</li>
<li>
{% include "seminar/prihlaska_field.html" with field=form.password_check %}
</li>
<li>
</table>
<hr>
<h4>
Osobní údaje
</li>
<li>
</h4>
<table class="form">
{% include "seminar/prihlaska_field.html" with field=form.jmeno %}
</li>
<li>
{% include "seminar/prihlaska_field.html" with field=form.prijmeni %}
</li>
<li>
{% include "seminar/prihlaska_field.html" with field=form.pohlavi_muz%}
</li>
<li>
{% include "seminar/prihlaska_field.html" with field=form.email %}
</li>
<li>
{% include "seminar/prihlaska_field.html" with field=form.telefon %}
</li>
<li>
{% include "seminar/prihlaska_field.html" with field=form.datum_narozeni %}
</li>
<li>
</table>
<hr>
<h4>
Bydliště
</li>
<li>
</h4>
<table class="form">
{% include "seminar/prihlaska_field.html" with field=form.ulice %}
</li>
<li>
{% include "seminar/prihlaska_field.html" with field=form.mesto %}
</li>
<li>
{% include "seminar/prihlaska_field.html" with field=form.psc %}
</li>
<li>
{% include "seminar/prihlaska_field.html" with field=form.stat %}
</li>
<li id="id_li_stat_text">
{% include "seminar/prihlaska_field.html" with field=form.stat_text %}
</li>
{% include "seminar/prihlaska_field.html" with field=form.stat_text id="id_li_stat_text"%}
</table>
<li>
<hr>
<h4>
Škola
</h4>
<table class="form">
{% include "seminar/prihlaska_field.html" with field=form.skola %}
</li>
<li>
<button id="id_skola_text_button" type="button">Škola není v seznamu</button>
</li>
<li id="id_li_skola_nazev">
Vyplň prosím celý název a adresu školy.<br>
{% include "seminar/prihlaska_field.html" with field=form.skola_nazev %}
</li>
<li id="id_li_skola_adresa">
{% include "seminar/prihlaska_field.html" with field=form.skola_adresa %}
</li>
<li>
<tr><td colspan="2" ><button id="id_skola_text_button" type="button">Škola není v seznamu</button></td></tr>
<tr><td id="id_li_skola_vypln" colspan="2">Vyplň prosím celý název a adresu školy.</td></tr>
{% include "seminar/prihlaska_field.html" with field=form.skola_nazev id="id_li_skola_nazev" %}
{% include "seminar/prihlaska_field.html" with field=form.skola_adresa id="id_li_skola_adresa" %}
{% include "seminar/prihlaska_field.html" with field=form.rok_maturity %}
</li>
<li>
</table>
<hr>
<h4>
Pošta
</h4>
<table class="form">
{% include "seminar/prihlaska_field.html" with field=form.zasilat %}
</li>
<li>
</table>
<hr>
<h4>
GDPR
</h4>
{% include "seminar/gdpr.html" %}
<table class="form">
{% include "seminar/prihlaska_field.html" with field=form.gdpr %}
</li>
<li>
</table>
<hr>
<h4>
Zasílání propagačních materiálů
</h4>
<table class="form">
{% include "seminar/prihlaska_field.html" with field=form.spam %}
</li>
</ul>
</table>
<hr>
<input type="submit" value="Odeslat">
</form>
<script>
@ -109,4 +110,3 @@ $("#id_skola_text_button").on("click",schoolNotInList);
{% endblock %}

25
seminar/templates/seminar/prihlaska_field.html

@ -1,4 +1,23 @@
<label class="field-label{% if field.field.required %} field-required{% endif %}" for="{{ field.id_for_label }}">{{ field.label }}:</label>
<tr id="{{ id }}" >
<td>
<label class="field-label{% if field.field.required %} field-required{% endif %}" for="{{ field.id_for_label }}">
{{ field.label }}:
</label>
</td>
<td>
{{ field }}
{% if field.help_text %}<span class="field-helptext">{{ field.help_text|safe }}</span>{% endif %}
{% if field.errors %}<span class="field-error">{{ field.errors }}</span>{% endif %}
</td>
</tr>
{% if field.help_text %}
<tr>
<td colspan="2"><span class="field-helptext">{{ field.help_text|safe }}</span></td>
</tr>
{% endif %}
{% if field.errors %}
<tr>
<td colspan="2"><span class="field-error">{{ field.errors }}</span></td>
</tr>
{% endif %}

241
seminar/testutils.py

@ -10,9 +10,12 @@ import unidecode
import logging
from seminar.models import Skola, Resitel, Rocnik, Cislo, 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 seminar.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
@ -205,21 +208,16 @@ def gen_zadani_ulohy(rnd, cisla, organizatori, pocet_oboru, poradi_cisla, poradi
max_body = rnd.randint(1, 8)
)
text_zadani = Text.objects.create(
na_web = " ".join(
[rnd.choice(sloveso),
rnd.choice(koho),
rnd.choice(ceho),
rnd.choice(jmeno),
rnd.choice(kde)]
),
do_cisla = " ".join(
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)
uloha_zadani = UlohaZadaniNode.objects.create(uloha = p, first_child = zad)
@ -228,7 +226,7 @@ def gen_zadani_ulohy(rnd, cisla, organizatori, pocet_oboru, poradi_cisla, poradi
return p
def gen_vzoroveho_reseni_ulohy(rnd, cisla, organizatori, uloha, pocet_opravovatelu, poradi_cisla):
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",
@ -238,18 +236,18 @@ def gen_vzoroveho_reseni_ulohy(rnd, cisla, organizatori, uloha, pocet_opravovate
"tak jste fakt hloupí"]
# Generování vzorového řešení.
obsah = rnd.choice(reseni)
text_vzoraku = Text.objects.create(
na_web = rnd.choice(reseni),
do_cisla = rnd.choice(reseni)
na_web = obsah,
do_cisla = obsah
)
vzorak = TextNode.objects.create(text = text_vzoraku)
uloha_vzorak = UlohaVzorakNode.objects.create(uloha = uloha, first_child = vzorak)
uloha.ulohavzoraknode = uloha_vzorak
otec_syn(cisla[poradi_cisla-1].cislonode, uloha_vzorak)
uloha.opravovatele.set(rnd.sample(organizatori, pocet_opravovatelu))
uloha.save()
return
return uloha_vzorak
def gen_reseni_ulohy(rnd, cisla, uloha, pocet_resitelu, poradi_cisla, resitele_cisla, resitele):
@ -307,7 +305,10 @@ def gen_ulohy_do_cisla(rnd, organizatori, resitele, rocnik_cisla, rocniky, size)
# přivěšení pod dané číslo
p = gen_zadani_ulohy(rnd, cisla, organizatori, poc_oboru, ci, pi)
# Generování vzorového řešení
gen_vzoroveho_reseni_ulohy(rnd, cisla, organizatori, p, poc_op, ci)
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)
@ -420,6 +421,85 @@ def gen_cisla(rnd, rocniky):
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)
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))
add_first_child(tema_cislo_node, cast_node)
text_node = TextNode.objects.create(text = get_text())
add_first_child(cast_node, text_node)
cast_node2 = m.CastNode.objects.create(nadpis = "První podproblém")
add_first_child(text_node, cast_node2)
text_node2 = TextNode.objects.create(text = get_text())
add_first_child(cast_node2, text_node2)
cast_node3 = m.CastNode.objects.create(nadpis = "Druhý podproblém")
add_first_child(text_node2, cast_node3)
text_node3 = TextNode.objects.create(text = get_text())
add_first_child(cast_node3, text_node3)
cast_node4 = m.CastNode.objects.create(nadpis = "Třetí podproblém")
add_first_child(text_node3, cast_node4)
text_node4 = TextNode.objects.create(text = get_text())
add_first_child(cast_node3, text_node4)
cast_node3a = m.CastNode.objects.create(nadpis = "Podproblém paralelní s "
"druhým podproblémem")
cast_node3.succ = cast_node3a
cast_node3.save()
text_node3a = TextNode.objects.create(text = get_text())
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)
mezicislo_node = cislo_node.succ
cast_node_mezicislo = m.CastNode.objects.create(
nadpis = "Příspěvek k mezičíslu".format(cislo.kod))
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)
add_first_child(cast_node_mezicislo, text_node_mezicislo)
return tema
def gen_temata(rnd, rocniky, rocnik_cisla, organizatori):
logger.info('Generuji témata...')
@ -474,11 +554,10 @@ def gen_temata(rnd, rocniky, rocnik_cisla, organizatori):
rocnik_temata.append(letosni_temata)
return rocnik_temata
def gen_ulohy_tematu(rnd, organizatori, tema, kod, cislo, cislo_se_vzorakem):
""" Generování úlohy k danému tématu. """
def gen_ulohy_k_tematum(rnd, rocniky, rocnik_cisla, rocnik_temata, organizatori):
logger.info('Generuji úlohy k tématům...')
# ulohy resene v cisle
# 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č",
@ -488,57 +567,9 @@ def gen_ulohy_k_tematum(rnd, rocniky, rocnik_cisla, rocnik_temata, organizatori)
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"]
obor = ["M", "F", "I", "O", "B"]
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í"]
# 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()
# FIXME: Tenhle generátor dát asi někam jinam
def potomci(node):
if not isinstance(node, TreeNode):
raise ValueError("Typ {} nemá potomky", type(node))
current_child = node.first_child
while current_child is not None:
yield current_child
current_child = current_child.succ
for mozna_tema_node in potomci(cislo.cislonode):
if not isinstance(mozna_tema_node, TemaVCisleNode):
continue
tema_node = mozna_tema_node
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
obory = ["M", "F", "I", "O", "B"]
# Generujeme 1 až 4 úložky k tomuto témátku do tohoto čísla
for kod in range(1, rnd.randint(1, 4)):
u = Uloha.objects.create(
uloha = Uloha.objects.create(
nazev=": ".join([tema.nazev,
"úloha {}.".format(kod)]),
nadproblem=tema,
@ -553,9 +584,6 @@ def gen_ulohy_k_tematum(rnd, rocniky, rocnik_cisla, rocnik_temata, organizatori)
max_body = rnd.randint(1, 8)
)
poc_opravovatelu = rnd.randint(1, 4)
u.opravovatele.set(rnd.sample(organizatori, poc_opravovatelu))
# Samotný obsah následně vzniklého Textu zadání
obsah = " ".join(
[rnd.choice(sloveso),
@ -569,32 +597,63 @@ def gen_ulohy_k_tematum(rnd, rocniky, rocnik_cisla, rocnik_temata, organizatori)
do_cisla = obsah,
)
zad = TextNode.objects.create(text = text_zadani)
uloha_zadani = UlohaZadaniNode.objects.create(uloha=u, first_child = zad)
u.ulohazadaninode = uloha_zadani
uloha_zadani = UlohaZadaniNode.objects.create(uloha=uloha, first_child = zad)
uloha.ulohazadaninode = uloha_zadani
# FIXME: Tohle dává zadání vždy jako prvního potomka témátka, spec. se naskládají v opačném pořadí a nemůže mezi nimi vzniknout žádný (orgo-)text
otec_syn(tema_node, uloha_zadani)
return uloha, uloha_zadani
# Text vzoráku stejně
obsah = rnd.choice(reseni)
text_vzoraku = Text.objects.create(
na_web = obsah,
do_cisla = obsah,
def gen_ulohy_k_tematum(rnd, rocniky, rocnik_cisla, rocnik_temata, organizatori):
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),
)
vzorak = TextNode.objects.create(text = text_vzoraku)
uloha_vzorak = UlohaVzorakNode.objects.create(uloha=u, first_child = vzorak)
u.UlohaVzorakNode = uloha_vzorak
# 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, 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 potomci(cislo_se_vzorakem.cislonode):
if isinstance(node, TemaVCisleNode) and node.tema == tema:
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")
# FIXME: Stejný problém jako výše: vzoráky se dají na začátek v opačném pořadí.
otec_syn(res_tema_node, uloha_vzorak)
insert_last_child(res_tema_node, uvz)
u.save()
return
@ -687,6 +746,10 @@ def create_test_data(size = 6, rnd = None):
# 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)

41
seminar/treelib.py

@ -12,6 +12,13 @@ def print_tree(node,indent=0):
if node.succ:
print_tree(node.succ, indent=indent)
def is_orphan(node):
""" Zjišťuje, jestli už je daný Node někde pověšený či nikoli. """
if safe_father_of_first(node) is None and safe_pred(node) is None:
return True
else:
return False
# Django je trošku hloupé, takže node.prev nevrací None, ale hází django.core.exceptions.ObjectDoesNotExist
def safe_pred(node):
try:
@ -43,6 +50,13 @@ def get_parent(node):
# ... a z prvního potomka umíme najít rodiče
return safe_father_of_first(node)
def get_last_child(node):
first = node.first_child
if first is None:
return None
else:
return last_brother(first)
# Obecný next: další Node v "the-right-order" pořadí (já, pak potomci, pak sousedé)
def general_next(node):
# Máme potomka?
@ -100,12 +114,19 @@ def all_proper_brothers(node):
continue
yield br
# Generátor potomků
def all_children(node):
""" Generátor všech potomků zadaného Node. """
brothers = all_brothers(node.first_child)
for br in brothers:
yield br
def all_children_of_type(node, type):
""" Generuje všechny potomky daného Node a daného typu. """
brothers = all_brothers(node.first_child)
for br in brothers:
if isinstance(br, type):
yield br
# Generátor následníků v "the-right-order"
# Bez tohoto vrcholu
def all_following(node):
@ -173,6 +194,24 @@ def create_child(parent, type, **kwargs):
new_node.succ = orig_child
new_node.save()
def insert_last_child(parent, node):
""" Zadaný Node přidá jako posledního potomka otce. """
last = get_last_child(parent)
if not is_orphan(node):
print(safe_pred(node))
print(safe_father_of_first(node))
if len(safe_father_of_first(node).get_real_instances()) == 0:
print("Related Manager je prázdný.")
print(type(safe_father_of_first(node).queryset_class))
raise TreeLibError("Snažíš se přidat do stromu Node, který už je zavěšený.")
if last is None:
parent.first_child = node
parent.save()
else:
last.succ = node
last.save()
def create_node_before(successor, type, **kwargs):
if safe_pred(successor) is not None:
# Easy: přidáme za předchůdce

5
seminar/urls.py

@ -34,11 +34,6 @@ urlpatterns = [
views.SoustredeniListView.as_view(),
name='seminar_seznam_soustredeni'
),
path(
'soustredeni/probehlo/<int:soustredeni>/',
views.SoustredeniView.as_view(),
name='seminar_soustredeni'
),
path(
'soustredeni/<int:soustredeni>/seznam_ucastniku',
staff_member_required(views.SoustredeniUcastniciView.as_view()),

62
seminar/views/unicodecsv.py

@ -1,62 +0,0 @@
import csv, codecs
from io import StringIO
class UTF8Recoder:
"""
Iterator that reads an encoded stream and reencodes the input to UTF-8
"""
def __init__(self, f, encoding):
self.reader = codecs.getreader(encoding)(f)
def __iter__(self):
return self
def next(self):
return self.reader.next().encode("utf-8")
class UnicodeReader:
"""
A CSV reader which will iterate over lines in the CSV file "f",
which is encoded in the given encoding.
"""
def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
f = UTF8Recoder(f, encoding)
self.reader = csv.reader(f, dialect=dialect, **kwds)
def next(self):
row = self.reader.next()
return [unicode(s, "utf-8") for s in row]
def __iter__(self):
return self
class UnicodeWriter:
"""
A CSV writer which will write rows to CSV file "f",
which is encoded in the given encoding.
"""
def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
# Redirect output to a queue
self.queue = cStringIO.StringIO()
self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
self.stream = f
self.encoder = codecs.getincrementalencoder(encoding)()
def writerow(self, row):
self.writer.writerow([s.encode("utf-8") for s in row])
# Fetch UTF-8 output from the queue ...
data = self.queue.getvalue()
data = data.decode("utf-8")
# ... and reencode it into the target encoding
data = self.encoder.encode(data)
# write to the target stream
self.stream.write(data)
# empty queue
self.queue.truncate(0)
def writerows(self, rows):
for row in rows:
self.writerow(row)

20
seminar/views/views_all.py

@ -20,13 +20,13 @@ import seminar.models as s
from seminar.models import Problem, Cislo, Reseni, Nastaveni, Rocnik, Soustredeni, Organizator, Resitel, Novinky, Soustredeni_Ucastnici, Pohadka, Tema, Clanek, Osoba, Skola # Tohle je stare a chceme se toho zbavit. Pouzivejte s.ToCoChci
#from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva
from seminar import utils, treelib
from .unicodecsv import UnicodeWriter
from seminar.forms import PrihlaskaForm, LoginForm, ProfileEditForm
import seminar.forms as f
from datetime import timedelta, date, datetime
from django.utils import timezone
from itertools import groupby
from collections import OrderedDict
import tempfile
import subprocess
import shutil
@ -777,7 +777,14 @@ class CisloView(generic.DetailView):
class ArchivTemataView(generic.ListView):
model = Problem
template_name = 'seminar/archiv/temata.html'
queryset = Tema.objects.filter(stav=Problem.STAV_ZADANY).select_related('cislo_zadani__rocnik').order_by('-cislo_zadani__rocnik__rocnik', 'kod')
queryset = Tema.objects.filter(stav=Problem.STAV_ZADANY).select_related('rocnik').order_by('rocnik', 'kod')
def get_context_data(self, *args, **kwargs):
ctx = super().get_context_data(*args, **kwargs)
ctx['rocniky'] = OrderedDict()
for rocnik, temata in groupby(ctx['object_list'], lambda tema: tema.rocnik):
ctx['rocniky'][rocnik] = list(temata)
return ctx
### Generovani vysledkovky
@ -913,10 +920,6 @@ class SoustredeniListView(generic.ListView):
model = Soustredeni
template_name = 'seminar/soustredeni/seznam_soustredeni.html'
class SoustredeniView(generic.DetailView):
model = Soustredeni
template_name = 'seminar/archiv/soustredeni.html'
def soustredeniObalkyView(request,soustredeni):
soustredeni = get_object_or_404(Soustredeni,id = soustredeni)
return obalkyView(request,soustredeni.ucastnici.all())
@ -951,10 +954,11 @@ def soustredeniUcastniciExportView(request,soustredeni):
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="ucastnici.csv"'
writer = UnicodeWriter(response)
writer = csv.writer(response)
writer.writerow(["jmeno", "prijmeni", "rok_maturity", "telefon", "email", "ulice", "mesto", "psc","stat"])
for u in ucastnici:
writer.writerow([u.jmeno, u.prijmeni, str(u.rok_maturity), u.telefon, u.email, u.ulice, u.mesto, u.psc, u.stat.name])
o = u.osoba
writer.writerow([o.jmeno, o.prijmeni, str(u.rok_maturity), o.telefon, o.email, o.ulice, o.mesto, o.psc, o.stat.name])
return response

Loading…
Cancel
Save