Merge branch 'data_migrations' of gimli.ms.mff.cuni.cz:/akce/mam/git/mamweb into data_migrations
This commit is contained in:
		
						commit
						6e882f75f7
					
				
					 8 changed files with 376 additions and 145 deletions
				
			
		
							
								
								
									
										27
									
								
								seminar/migrations/0078_otistenereseninode.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								seminar/migrations/0078_otistenereseninode.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| # Generated by Django 2.2.9 on 2020-03-18 23:59 | ||||
| 
 | ||||
| from django.db import migrations, models | ||||
| import django.db.models.deletion | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
| 
 | ||||
|     dependencies = [ | ||||
|         ('seminar', '0077_auto_20200318_2146'), | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.CreateModel( | ||||
|             name='OtisteneReseniNode', | ||||
|             fields=[ | ||||
|                 ('treenode_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='seminar.TreeNode')), | ||||
|                 ('reseni', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='seminar.Reseni', verbose_name='reseni')), | ||||
|             ], | ||||
|             options={ | ||||
|                 'verbose_name': 'Otištěné řešení (Node)', | ||||
|                 'verbose_name_plural': 'Otištěná řešení (Node)', | ||||
|                 'db_table': 'seminar_nodes_otistene_reseni', | ||||
|             }, | ||||
|             bases=('seminar.treenode',), | ||||
|         ), | ||||
|     ] | ||||
|  | @ -1474,6 +1474,26 @@ class CastNode(TreeNode): | |||
| 	 | ||||
| 	nadpis = models.CharField('Nadpis', max_length=100, help_text = 'Nadpis podvěšené části obsahu') | ||||
| 
 | ||||
| 	def aktualizuj_nazev(self): | ||||
| 		self.nazev = "CastNode: "+str(self.nadpis) | ||||
| 
 | ||||
| 	def getOdkazStr(self): | ||||
| 		return str(self.nadpis) | ||||
| 
 | ||||
| class OtisteneReseniNode(TreeNode): | ||||
| 	class Meta: | ||||
| 		db_table = 'seminar_nodes_otistene_reseni' | ||||
| 		verbose_name = 'Otištěné řešení (Node)' | ||||
| 		verbose_name_plural = 'Otištěná řešení (Node)' | ||||
| 	reseni = models.ForeignKey(Reseni, | ||||
| 		on_delete=models.PROTECT, | ||||
| 		verbose_name = 'reseni') | ||||
| 	 | ||||
| 	def aktualizuj_nazev(self): | ||||
| 		self.nazev = "OtisteneReseniNode: "+str(self.reseni) | ||||
| 
 | ||||
| 	def getOdkazStr(self): | ||||
| 		return str(self.reseni) | ||||
| 
 | ||||
| ## FIXME: Logiku přesunout do views. | ||||
| #class VysledkyBase(SeminarModelBase): | ||||
|  |  | |||
							
								
								
									
										10
									
								
								seminar/templates/seminar/treenode.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								seminar/templates/seminar/treenode.html
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | |||
| {% extends "seminar/archiv/base_ulohy.html" %} | ||||
| 
 | ||||
| {% load comments %} | ||||
| 
 | ||||
| {% block content %} | ||||
| 
 | ||||
| {%with obj=tnldata depth=1 template_name="seminar/treenode_recursive.html" %} | ||||
|    {%include template_name%} | ||||
| {%endwith%} | ||||
| {% endblock content %} | ||||
							
								
								
									
										28
									
								
								seminar/templates/seminar/treenode_recursive.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								seminar/templates/seminar/treenode_recursive.html
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | |||
| {% load treenodes %} | ||||
| {# <b>{{depth}}</b> #} | ||||
| <div> | ||||
| {%   if obj.node|isRocnik %} | ||||
| <h{{depth}}> Ročník {{obj.node.rocnik}} </h{{depth}}> | ||||
| {% elif obj.node|isCislo %} | ||||
| <h{{depth}}> Číslo {{obj.node.cislo}} </h{{depth}}> | ||||
| {% elif obj.node|isTemaVCisle %} | ||||
| <h{{depth}}> Téma {{obj.node.tema.nazev}} </h{{depth}}> | ||||
| {% elif obj.node|isUlohaZadani %} | ||||
| <h{{depth}}>Úloha {{obj.node.uloha.kod_v_rocniku}} ({{obj.node.uloha.max_body}} b)</h{{depth}}> | ||||
| {% elif obj.node|isUlohaVzorak %} | ||||
| <h{{depth}}>Řešení: {{obj.node.uloha.kod_v_rocniku}}</h{{depth}}> | ||||
| {% elif obj.node|isText %} | ||||
| {{obj.node.text.na_web}} | ||||
| {% else %} | ||||
| Objekt jiného typu {{obj.node}} | ||||
| {% endif %} | ||||
|     {%if obj.children %} | ||||
| 	<div> | ||||
|          {%for ch in obj.children %} | ||||
|               {%with obj=ch depth=depth|add:"1" template_name="seminar/treenode_recursive.html" %} | ||||
|                    {%include template_name%} | ||||
|               {%endwith%} | ||||
|          {%endfor%} | ||||
| 	</div> | ||||
|     {%endif%} | ||||
| </div> | ||||
							
								
								
									
										49
									
								
								seminar/templatetags/treenodes.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								seminar/templatetags/treenodes.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,49 @@ | |||
| from django import template | ||||
| import seminar.models as m | ||||
| 
 | ||||
| register = template.Library() | ||||
| 
 | ||||
| @register.filter | ||||
| def isRocnik(value): | ||||
|     return isinstance(value, m.RocnikNode) | ||||
| 
 | ||||
| @register.filter | ||||
| def isCislo(value): | ||||
|     return isinstance(value, m.CisloNode) | ||||
| 
 | ||||
| @register.filter | ||||
| def isCast(value): | ||||
|     return isinstance(value, m.CastNode) | ||||
| 
 | ||||
| @register.filter | ||||
| def isText(value): | ||||
|     return isinstance(value, m.TextNode) | ||||
| 
 | ||||
| @register.filter | ||||
| def isTemaVCisle(value): | ||||
|     return isinstance(value, m.TemaVCisleNode) | ||||
| 
 | ||||
| @register.filter | ||||
| def isKonfera(value): | ||||
|     return isinstance(value, m.KonferaNode) | ||||
| 
 | ||||
| @register.filter | ||||
| def isClanek(value): | ||||
|     return isinstance(value, m.ClanekNode) | ||||
| 
 | ||||
| @register.filter | ||||
| def isUlohaVzorak(value): | ||||
|     return isinstance(value, m.UlohaVzorakNode) | ||||
| 
 | ||||
| @register.filter | ||||
| def isUlohaZadani(value): | ||||
|     return isinstance(value, m.UlohaZadaniNode) | ||||
| 
 | ||||
| @register.filter | ||||
| def isPohadka(value): | ||||
|     return isinstance(value, m.PohadkaNode) | ||||
| 
 | ||||
| #@register.filter | ||||
| #def isOtisteneReseniNode(value): | ||||
| #    return isinstance(value, m.OtisteneReseniNode) | ||||
| 
 | ||||
|  | @ -1,6 +1,7 @@ | |||
| from django.core.exceptions import ObjectDoesNotExist | ||||
| # NOTE: node.prev a node.succ jsou implementovány přímo v models.TreeNode | ||||
| # TODO: Všechny tyto funkce se naivně spoléhají na to, že jako parametr dostanou nějaký TreeNode (některé možná zvládnou i None) | ||||
| # TODO: Chceme, aby všechno nějak zvládlo None jako parametr. | ||||
| 
 | ||||
| # Slouží k debugování pro rychlé získání představy o podobě podstromu pod tímto TreeNode. | ||||
| def print_tree(node,indent=0): | ||||
|  | @ -18,9 +19,19 @@ def safe_pred(node): | |||
| 	except ObjectDoesNotExist: | ||||
| 		return None | ||||
| 
 | ||||
| def first_brother(node): | ||||
| 	if node is None: | ||||
| 		return None | ||||
| 	brother = node | ||||
| 	while safe_pred(brother) is not None: | ||||
| 		brother = safe_pred(brother) | ||||
| 	return brother | ||||
| 
 | ||||
| # A to samé pro .father_of_first | ||||
| def safe_father_of_first(node): | ||||
| 		return node.prev | ||||
| 	first = first_brother(node) | ||||
| 	try: | ||||
| 		return first.father_of_first | ||||
| 	except ObjectDoesNotExist: | ||||
| 		return None | ||||
| 
 | ||||
|  | @ -61,14 +72,34 @@ def general_prev(node): | |||
| 	# pred nyní nemá žádné potomky, takže je to poslední rekurzivní potomek původního předchůdce | ||||
| 	return pred | ||||
| 
 | ||||
| # Generátor bratrů | ||||
| # Generátor pravých bratrů (konkrétně sebe a následujících potomků) | ||||
| # Generátor potomků níže spoléhá na to, že se tohle dá volat i s parametrem None. | ||||
| def all_brothers(node): | ||||
| def me_and_right_brothers(node): | ||||
| 	current = node | ||||
| 	while current is not None: | ||||
| 		yield current | ||||
| 		current = current.succ | ||||
| 
 | ||||
| def right_brothers(node): | ||||
| 	generator = me_and_right_brothers(node.succ) | ||||
| 	for item in generator: | ||||
| 		yield item | ||||
| 
 | ||||
| # Generátor všech sourozenců (vč. sám sebe) | ||||
| def all_brothers(node): | ||||
| 	# Najdeme prvního bratra | ||||
| 	fb = first_brother(node) | ||||
| 	marb = me_and_right_brothers(fb) | ||||
| 	for cur in marb: | ||||
| 		yield cur | ||||
| 	 | ||||
| def all_proper_brothers(node): | ||||
| 	all = all_brothers(node) | ||||
| 	for br in all: | ||||
| 		if br is node: | ||||
| 			continue | ||||
| 		yield br | ||||
| 
 | ||||
| # Generátor potomků | ||||
| def all_children(node): | ||||
| 	brothers = all_brothers(node.first_child) | ||||
|  | @ -76,44 +107,129 @@ def all_children(node): | |||
| 		yield br | ||||
| 
 | ||||
| # Generátor následníků v "the-right-order" | ||||
| # Bez tohoto vrcholu | ||||
| def all_following(node): | ||||
| 	current = general_next(node) | ||||
| 	while current is not None: | ||||
| 		yield current | ||||
| 		current = general_next(current) | ||||
| 
 | ||||
| ## Filtrační hledání | ||||
| # Najdi dalšího bratra nějakého typu, nebo None. | ||||
| # hledá i podtřídy, i.e. get_next_brother_of_type(neco, TreeNode) je prostě succ. | ||||
| def get_next_brother_of_type(current, type): | ||||
| 	pass | ||||
| def get_prev_brother_of_type(current, type): | ||||
| 	pass | ||||
| def get_next_brother_of_type(node, type): | ||||
| 	for current in right_brothers(node): | ||||
| 		if isinstance(current, type): | ||||
| 			return current | ||||
| 	return None | ||||
| 	 | ||||
| def get_prev_brother_of_type(node, type): | ||||
| 	# Na tohle není rozumný generátor, ani ho asi nechceme, prostě to implementujeme cyklem. | ||||
| 	current = node | ||||
| 	while safe_pred(current) is not None: | ||||
| 		current = safe_pred(current) | ||||
| 		if isinstance(current, type): | ||||
| 			return current | ||||
| 	return None | ||||
| 
 | ||||
| # Totéž pro "the-right-order" pořadí | ||||
| def get_next_node_of_type(current, type): | ||||
| 	pass | ||||
| def get_next_node_of_type(current, type): | ||||
| 	pass | ||||
| def get_next_node_of_type(node, type): | ||||
| 	for cur in all_folowing(node): | ||||
| 		if isinstance(cur, type): | ||||
| 			return cur | ||||
| 	return None | ||||
| 
 | ||||
| def get_prev_node_of_type(node, type): | ||||
| 	# Na tohle není rozumný generátor, ani ho asi nechceme, prostě to implementujeme cyklem. | ||||
| 	current = node | ||||
| 	while general_prev(current) is not None: | ||||
| 		current = general_prev(current) | ||||
| 		if isinstance(current, type): | ||||
| 			return current | ||||
| 	return None | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| # Editace stromu: | ||||
| def create_node_after(predecessor, type, **kwargs): | ||||
| 	pass | ||||
| 	new_node = type.objects.create(**kwargs) | ||||
| 	new_node.save() | ||||
| 	succ = predecessor.succ | ||||
| 	predecessor.succ = new_node | ||||
| 	predecessor.save() | ||||
| 	new_node.succ = succ | ||||
| 	new_node.save() | ||||
| 
 | ||||
| # Vyrábí prvního syna, ostatní nalepí za (existují-li) | ||||
| def create_child(parent, type, **kwargs): | ||||
| 	pass | ||||
| 	new_node = type.objects.create(**kwargs) | ||||
| 	new_node.save() | ||||
| 	orig_child = parent.first_child | ||||
| 	parent.first_child = new_node | ||||
| 	parent.save() | ||||
| 	if orig_child is not None: | ||||
| 		# Přidáme původního prvního syna jako potomka nového vrcholu | ||||
| 		new_node.succ = orig_child | ||||
| 		new_node.save() | ||||
| 
 | ||||
| def create_node_before(successor, type, **kwargs): | ||||
| 	if safe_pred(successor) is not None: | ||||
| 		# Easy: přidáme za předchůdce | ||||
| 		create_node_after(successor.prev, type, **kwargs) | ||||
| 	# Nemáme předchůdce, jsme tedy první z bratrů. Máme otce? | ||||
| 	if safe_father_of_first(successor) is not None: | ||||
| 		# Ano -> Easy: vyrobíme nového potomka | ||||
| 		# NOTE: Tohle je možná trošku abuse implementace výše, ale to nevadí moc... | ||||
| 		create_child(successor.father_of_first, type, **kwargs) | ||||
| 	# Teď už easy: Jsme sirotci, takže se vyrobíme a našeho následníka si přidáme jako succ | ||||
| 	new = type.objects.create(**kwargs) | ||||
| 	new.succ = successor | ||||
| 	new.save() | ||||
| 
 | ||||
| def create_node_before(some, arguments, but, i, dont, know, which, yet): | ||||
| 	pass | ||||
| 	# Tohle bude hell. | ||||
| 
 | ||||
| # ValueError, pokud je (aspoň) jeden parametr None | ||||
| def swap(node, other): | ||||
| 	raise NotImplementedError("YAGNI (You aren't gonna need it).") | ||||
| 
 | ||||
| # Exception, kterou některé metody při špatném použití mohou házet | ||||
| # Hlavní důvod je možnost informovat o selhání, aby se příslušný problém dal zobrazit na frontendu, | ||||
| class TreeLibError(RuntimeError): | ||||
| 	pass | ||||
| 
 | ||||
| def swap_pred(node): | ||||
| 	pass | ||||
| 	if node is None: | ||||
| 		raise TreeLibError("Nelze přesunout None. Tohle by se nemělo stát.") | ||||
| 	pred = safe_pred(node) | ||||
| 	if pred is None: | ||||
| 		raise TreeLibError("Nelze posunout vlevo, není tam žádný další uzel.") | ||||
| 	pre_pred = safe_pred(pred) | ||||
| 	succ = node.succ | ||||
| 
 | ||||
| 	if pre_pred is not None: | ||||
| 		pre_pred.succ = node | ||||
| 		pre_pred.save() | ||||
| 	node.succ = pred | ||||
| 	node.save() | ||||
| 	pred.succ = succ | ||||
| 	pred.save() | ||||
| 
 | ||||
| def swap_succ(node): | ||||
| 	pass | ||||
| 	if node is None: | ||||
| 		raise TreeLibError("Nelze přesunout None. Tohle by se nemělo stát.") | ||||
| 	succ = node.succ | ||||
| 	if succ is None: | ||||
| 		raise TreeLibError("Nelze posunout vpravo, není tam žádný další uzel") | ||||
| 	pred = safe_pred(node) | ||||
| 	post_succ = succ.succ | ||||
| 
 | ||||
| 	if pred is not None: | ||||
| 		pred.succ = succ | ||||
| 		pred.save() | ||||
| 	succ.succ = node | ||||
| 	succ.save() | ||||
| 	node.succ = post_succ | ||||
| 	node.save() | ||||
| 
 | ||||
| # Rotace stromu | ||||
| # Dokumentace viz wiki: | ||||
|  |  | |||
|  | @ -8,8 +8,8 @@ from django.contrib.auth import views as auth_views | |||
| staff_member_required = user_passes_test(lambda u: u.is_staff) | ||||
| 
 | ||||
| urlpatterns = [ | ||||
|   path('aktualni/temata/', views.TemataRozcestnikView), | ||||
| 	path('<int:rocnik>/t<int:tematko>/', views.TematkoView), | ||||
| #	path('aktualni/temata/', views.TemataRozcestnikView), | ||||
| #	path('<int:rocnik>/t<int:tematko>/', views.TematkoView), | ||||
| 
 | ||||
| 	# REDIRECTy | ||||
| 	path('jak-resit/', RedirectView.as_view(url='/co-je-MaM/jak-resit/')), | ||||
|  | @ -25,6 +25,7 @@ urlpatterns = [ | |||
| 	path('rocnik/<int:rocnik>/', views.RocnikView.as_view(), name='seminar_rocnik'), | ||||
| 	path('cislo/<int:rocnik>.<int:cislo>/', views.CisloView.as_view(), name='seminar_cislo'), | ||||
| 	path('problem/<int:pk>/', views.ProblemView.as_view(), name='seminar_problem'), | ||||
| 	path('treenode/<int:pk>/', views.TreeNodeView.as_view(), name='seminar_treenode'), | ||||
| 	#path('problem/(?P<pk>\d+)/(?P<prispevek>\d+)/', views.PrispevekView.as_view(), name='seminar_problem_prispevek'), | ||||
| 
 | ||||
| 	# Soustredeni | ||||
|  | @ -59,8 +60,8 @@ urlpatterns = [ | |||
| 	), | ||||
| 
 | ||||
| 	# Zadani | ||||
| 	path('zadani/aktualni/', views.AktualniZadaniView, name='seminar_aktualni_zadani'), | ||||
| 	path('zadani/temata/', views.ZadaniTemataView, name='seminar_temata'), | ||||
| #	path('zadani/aktualni/', views.AktualniZadaniView, name='seminar_aktualni_zadani'), | ||||
| #	path('zadani/temata/', views.ZadaniTemataView, name='seminar_temata'), | ||||
| 	#path('zadani/vysledkova-listina/', views.ZadaniAktualniVysledkovkaView, name='seminar_vysledky'), | ||||
| 	path('stare-novinky/', views.StareNovinkyView.as_view(), name='stare_novinky'), | ||||
| 
 | ||||
|  | @ -107,9 +108,6 @@ urlpatterns = [ | |||
| 	path('auth/login/', views.LoginView.as_view(), name='login'), | ||||
| 	path('auth/logout/', views.LogoutView.as_view(), name='logout'), | ||||
| 	path('auth/resitel/', views.ResitelView.as_view(), name='seminar_resitel'), | ||||
| 	path('autocomplete/skola/',views.SkolaAutocomplete.as_view(), name='autocomplete_skola'), | ||||
| 	path('autocomplete/resitel/',views.ResitelAutocomplete.as_view(), name='autocomplete_resitel'), | ||||
| 	path('autocomplete/problem/odevzdatelny',views.OdevzdatelnyProblemAutocomplete.as_view(), name='autocomplete_problem_odevzdatelny'), | ||||
| 	path('auth/reset_password/', views.PasswordResetView.as_view(), name='reset_password'), | ||||
| 	path('auth/change_password/', views.PasswordChangeView.as_view(), name='change_password'), | ||||
| 	path('auth/reset_password_done/', views.PasswordResetDoneView.as_view(), name='reset_password_done'), | ||||
|  | @ -117,6 +115,10 @@ urlpatterns = [ | |||
| 	path('auth/reset_password_complete/', views.PasswordResetCompleteView.as_view(), name='reset_password_complete'), | ||||
| 	path('auth/resitel_edit', views.resitelEditView, name='seminar_resitel_edit'), | ||||
| 
 | ||||
| 	# Autocomplete | ||||
| 	path('autocomplete/skola/',views.SkolaAutocomplete.as_view(), name='autocomplete_skola'), | ||||
| 	path('autocomplete/resitel/',views.ResitelAutocomplete.as_view(), name='autocomplete_resitel'), | ||||
| 	path('autocomplete/problem/odevzdatelny',views.OdevzdatelnyProblemAutocomplete.as_view(), name='autocomplete_problem_odevzdatelny'), | ||||
| 
 | ||||
| 	path('temp/add_solution', views.AddSolutionView.as_view(),name='seminar_vloz_reseni'), | ||||
| 	path('temp/submit_solution', views.SubmitSolutionView.as_view(),name='seminar_nahraj_reseni'), | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ from django.db import transaction | |||
| 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 | ||||
| from seminar import utils,treelib | ||||
| from .unicodecsv import UnicodeWriter | ||||
| from seminar.forms import PrihlaskaForm, LoginForm, ProfileEditForm | ||||
| import seminar.forms as f | ||||
|  | @ -83,131 +83,110 @@ class ObalkovaniView(generic.ListView): | |||
| 		context['cislo'] = self.cislo  | ||||
| 		return context | ||||
| 
 | ||||
| class TNLData(object): | ||||
| 	def __init__(self,anode): | ||||
| 		self.node = anode | ||||
| 		self.children = [] | ||||
| 
 | ||||
| 
 | ||||
| def treenode_strom_na_seznamy(node): | ||||
| 	out = TNLData(node) | ||||
| 	for ch in treelib.all_children(node): | ||||
| 		outitem = treenode_strom_na_seznamy(ch) | ||||
| 		out.children.append(outitem) | ||||
| 	return out | ||||
| 
 | ||||
| def AktualniZadaniView(request): | ||||
| 	nastaveni = get_object_or_404(Nastaveni) | ||||
| 	verejne = nastaveni.aktualni_cislo.verejne() | ||||
| 	problemy = Problem.objects.filter(cislo_zadani=nastaveni.aktualni_cislo).filter(stav = 'zadany') | ||||
| 	ulohy = problemy.filter(typ = 'uloha').order_by('kod') | ||||
| 	serialy = problemy.filter(typ = 'serial').order_by('kod') | ||||
| 	jednorazove_problemy = [ulohy, serialy] | ||||
| 	return render(request, 'seminar/zadani/AktualniZadani.html', | ||||
| 			{'nastaveni': nastaveni, | ||||
| 			 'jednorazove_problemy': jednorazove_problemy, | ||||
| 			 'temata': verejna_temata(nastaveni.aktualni_rocnik), | ||||
| 			 'verejne': verejne, | ||||
| 				}, | ||||
| 			) | ||||
| class TreeNodeView(generic.DetailView): | ||||
| 	model = s.TreeNode | ||||
| 	template_name = 'seminar/treenode.html' | ||||
| 
 | ||||
| def ZadaniTemataView(request): | ||||
| 	nastaveni = get_object_or_404(Nastaveni) | ||||
| 	temata = verejna_temata(nastaveni.aktualni_rocnik) | ||||
| 	for t in temata: | ||||
| 		if request.user.is_staff: | ||||
| 			t.prispevky = t.prispevek_set.filter(problem=t) | ||||
| 		else: | ||||
| 			t.prispevky = t.prispevek_set.filter(problem=t, zverejnit=True) | ||||
| 	return render(request, 'seminar/zadani/Temata.html', | ||||
| 		{ | ||||
| 			'temata': temata, | ||||
| 		} | ||||
| 	) | ||||
| 
 | ||||
| # TODO Napsat tuto funkci znovu rekurzivně podle Jethrorad. Potom se podívat, jak lehce se dá modifikovat pro Rozcestník. Pokud lehce, rozšířit ji. Pokud složitě - použít tuhle | ||||
| def vytahniZLesaSeznam(tematko, koren, pouze_zajimave=False): | ||||
| 	returnVal = [] | ||||
| 
 | ||||
| 	stack = [] | ||||
| 	stack.append((koren.first_child, 0, False)) #Tuple of node, depth and relevance | ||||
| 
 | ||||
| 	while len(stack) > 0: | ||||
| 		wn, wd, wr = stack.pop() | ||||
| 
 | ||||
| 		if wn.succ != None: | ||||
| 			stack.append((wn.succ, wd, wr)) | ||||
| 		if isinstance(wn, s.TemaVCisleNode): | ||||
| 			print("TEMA") | ||||
| 			print(wn.tema.id)	 | ||||
| 			print(tematko.id)	 | ||||
| 			if wn.tema.id == tematko.id: | ||||
| 				returnVal.append((posledni_cislo, 0)) | ||||
| 				print("PRIDANO") | ||||
| 				wr = True | ||||
| 				wd = 1 | ||||
| 
 | ||||
| 		if wn.srolovatelne: | ||||
| 			tagOpen = s.Text(na_web = "Otevírací srolovací tag") | ||||
| 			tagOpenNode = s.TextNode(text = tagOpen) | ||||
| 			tagClose = s.Text(na_web = "Zavírací srolovací tag") | ||||
| 			tagCloseNode = s.TextNode(text = tagClose) | ||||
| 			stack.append((tagCloseNode, wd, True)) | ||||
| 			 | ||||
| 		if wn.first_child != None: | ||||
| 			stack.append((wn.first_child, wd + 1, wr)) | ||||
| 
 | ||||
| 		if isinstance(wn, s.CisloNode): | ||||
| 			posledni_cislo = wn | ||||
| 		print(wn) | ||||
| 
 | ||||
| 		if wr:						 | ||||
| 			print("ZAJIMAVE") | ||||
| 			if pouze_zajimave: | ||||
| 				if not wn.zajimave: | ||||
| 					continue | ||||
| 			returnVal.append((wn, wd)) | ||||
| 	return returnVal | ||||
|    | ||||
| def TematkoView(request, rocnik, tematko): | ||||
| 	nastaveni = s.Nastaveni.objects.first() | ||||
| 	rocnik_object = s.Rocnik.objects.filter(rocnik=rocnik) | ||||
| 	tematko_object = s.Tema.objects.filter(rocnik=rocnik_object[0], kod=tematko) | ||||
| 	seznam = vytahniZLesaSeznam(tematko_object[0], nastaveni.aktualni_rocnik().rocniknode) | ||||
| 	for node, depth in seznam: | ||||
| 		if node.isinstance(node, s.KonferaNode): | ||||
| 			raise Exception("Not implemented yet") | ||||
| 		if node.isinstance(node, s.PohadkaNode): # Mohu ignorovat, má pod sebou | ||||
| 			pass | ||||
| 
 | ||||
| 	return render(request, 'seminar/tematka/toaletak.html', {}) | ||||
| 	def get_context_data(self,**kwargs): | ||||
| 		context = super().get_context_data(**kwargs) | ||||
| 		context['tnldata'] = treenode_strom_na_seznamy(self.object) | ||||
| 		return context | ||||
| 	 | ||||
| 
 | ||||
| def TemataRozcestnikView(request): | ||||
| 	print("=============================================") | ||||
| 	nastaveni = s.Nastaveni.objects.first() | ||||
| 	tematka_objects = s.Tema.objects.filter(rocnik=nastaveni.aktualni_rocnik()) | ||||
| 	tematka = [] #List tematka obsahuje pro kazde tematko object a list vsech TemaVCisleNodu - implementované pomocí slovníku | ||||
| 	for tematko_object in tematka_objects: | ||||
| 		print("AKTUALNI TEMATKO") | ||||
| 		print(tematko_object.id) | ||||
| 		odkazy = vytahniZLesaSeznam(tematko_object, nastaveni.aktualni_rocnik().rocniknode, pouze_zajimave = True) #Odkazy jsou tuply (node, depth) v listu | ||||
| 		print(odkazy) | ||||
| 		cisla = [] # List tuplů (nazev cisla, list odkazů) | ||||
| 		vcisle = [] | ||||
| 		cislo = None | ||||
| 		for odkaz	in odkazy: | ||||
| 			if odkaz[1] == 0: | ||||
| 				if cislo != None: | ||||
| 					cisla.append((cislo, vcisle)) | ||||
| 				cislo = (odkaz[0].getOdkazStr(), odkaz[0].getOdkaz()) | ||||
| 				vcisle = [] | ||||
| 			else: | ||||
| 				print(odkaz[0].getOdkaz()) | ||||
| 				vcisle.append((odkaz[0].getOdkazStr(), odkaz[0].getOdkaz())) | ||||
| 		if cislo != None: | ||||
| 			cisla.append((cislo, vcisle)) | ||||
| 				 | ||||
| 		print(cisla) | ||||
| 		tematka.append({ | ||||
| 			"kod" : tematko_object.kod, | ||||
| 			"nazev" : tematko_object.nazev, | ||||
| 			"abstrakt" : tematko_object.abstrakt,  | ||||
| 			"obrazek": tematko_object.obrazek, | ||||
| 			"cisla" : cisla | ||||
| 		}) | ||||
| 	return render(request, 'seminar/tematka/rozcestnik.html', {"tematka": tematka, "rocnik" : nastaveni.aktualni_rocnik().rocnik}) | ||||
|      | ||||
| 
 | ||||
| #def AktualniZadaniView(request): | ||||
| #	nastaveni = get_object_or_404(Nastaveni) | ||||
| #	verejne = nastaveni.aktualni_cislo.verejne() | ||||
| #	problemy = Problem.objects.filter(cislo_zadani=nastaveni.aktualni_cislo).filter(stav = 'zadany') | ||||
| #	ulohy = problemy.filter(typ = 'uloha').order_by('kod') | ||||
| #	serialy = problemy.filter(typ = 'serial').order_by('kod') | ||||
| #	jednorazove_problemy = [ulohy, serialy] | ||||
| #	return render(request, 'seminar/zadani/AktualniZadani.html', | ||||
| #			{'nastaveni': nastaveni, | ||||
| #			 'jednorazove_problemy': jednorazove_problemy, | ||||
| #			 'temata': verejna_temata(nastaveni.aktualni_rocnik), | ||||
| #			 'verejne': verejne, | ||||
| #				}, | ||||
| #			) | ||||
| # | ||||
| #def ZadaniTemataView(request): | ||||
| #	nastaveni = get_object_or_404(Nastaveni) | ||||
| #	temata = verejna_temata(nastaveni.aktualni_rocnik) | ||||
| #	for t in temata: | ||||
| #		if request.user.is_staff: | ||||
| #			t.prispevky = t.prispevek_set.filter(problem=t) | ||||
| #		else: | ||||
| #			t.prispevky = t.prispevek_set.filter(problem=t, zverejnit=True) | ||||
| #	return render(request, 'seminar/zadani/Temata.html', | ||||
| #		{ | ||||
| #			'temata': temata, | ||||
| #		} | ||||
| #	) | ||||
| # | ||||
| # | ||||
| #   | ||||
| #def TematkoView(request, rocnik, tematko): | ||||
| #	nastaveni = s.Nastaveni.objects.first() | ||||
| #	rocnik_object = s.Rocnik.objects.filter(rocnik=rocnik) | ||||
| #	tematko_object = s.Tema.objects.filter(rocnik=rocnik_object[0], kod=tematko) | ||||
| #	seznam = vytahniZLesaSeznam(tematko_object[0], nastaveni.aktualni_rocnik().rocniknode) | ||||
| #	for node, depth in seznam: | ||||
| #		if node.isinstance(node, s.KonferaNode): | ||||
| #			raise Exception("Not implemented yet") | ||||
| #		if node.isinstance(node, s.PohadkaNode): # Mohu ignorovat, má pod sebou | ||||
| #			pass | ||||
| # | ||||
| #	return render(request, 'seminar/tematka/toaletak.html', {}) | ||||
| #	 | ||||
| # | ||||
| #def TemataRozcestnikView(request): | ||||
| #	print("=============================================") | ||||
| #	nastaveni = s.Nastaveni.objects.first() | ||||
| #	tematka_objects = s.Tema.objects.filter(rocnik=nastaveni.aktualni_rocnik()) | ||||
| #	tematka = [] #List tematka obsahuje pro kazde tematko object a list vsech TemaVCisleNodu - implementované pomocí slovníku | ||||
| #	for tematko_object in tematka_objects: | ||||
| #		print("AKTUALNI TEMATKO") | ||||
| #		print(tematko_object.id) | ||||
| #		odkazy = vytahniZLesaSeznam(tematko_object, nastaveni.aktualni_rocnik().rocniknode, pouze_zajimave = True) #Odkazy jsou tuply (node, depth) v listu | ||||
| #		print(odkazy) | ||||
| #		cisla = [] # List tuplů (nazev cisla, list odkazů) | ||||
| #		vcisle = [] | ||||
| #		cislo = None | ||||
| #		for odkaz	in odkazy: | ||||
| #			if odkaz[1] == 0: | ||||
| #				if cislo != None: | ||||
| #					cisla.append((cislo, vcisle)) | ||||
| #				cislo = (odkaz[0].getOdkazStr(), odkaz[0].getOdkaz()) | ||||
| #				vcisle = [] | ||||
| #			else: | ||||
| #				print(odkaz[0].getOdkaz()) | ||||
| #				vcisle.append((odkaz[0].getOdkazStr(), odkaz[0].getOdkaz())) | ||||
| #		if cislo != None: | ||||
| #			cisla.append((cislo, vcisle)) | ||||
| #				 | ||||
| #		print(cisla) | ||||
| #		tematka.append({ | ||||
| #			"kod" : tematko_object.kod, | ||||
| #			"nazev" : tematko_object.nazev, | ||||
| #			"abstrakt" : tematko_object.abstrakt,  | ||||
| #			"obrazek": tematko_object.obrazek, | ||||
| #			"cisla" : cisla | ||||
| #		}) | ||||
| #	return render(request, 'seminar/tematka/rozcestnik.html', {"tematka": tematka, "rocnik" : nastaveni.aktualni_rocnik().rocnik}) | ||||
| #     | ||||
| 
 | ||||
| #def ZadaniAktualniVysledkovkaView(request): | ||||
| #	nastaveni = get_object_or_404(Nastaveni) | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Anet
						Anet