diff --git a/seminar/treelib.py b/seminar/treelib.py index bf696545..cfb49d86 100644 --- a/seminar/treelib.py +++ b/seminar/treelib.py @@ -1,4 +1,6 @@ +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) # Slouží k debugování pro rychlé získání představy o podobě podstromu pod tímto TreeNode. def print_tree(node,indent=0): @@ -9,23 +11,69 @@ def print_tree(node,indent=0): if node.succ: print_tree(node.succ, indent=indent) +# Django je trošku hloupé, takže node.prev nevrací None, ale hází django.core.exceptions.ObjectDoesNotExist +def safe_pred(node): + try: + return node.prev + except ObjectDoesNotExist: + return None + +# A to samé pro .father_of_first +def safe_father_of_first(node): + return node.prev + except ObjectDoesNotExist: + return None + ## Rodinné vztahy def get_parent(node): - pass # Nejdřív získáme prvního potomka... - + while safe_pred(node) is not None: + node = safe_pred(node) # ... a z prvního potomka umíme najít rodiče + return safe_father_of_first(node) # Obecný next: další Node v "the-right-order" pořadí (já, pak potomci, pak sousedé) def general_next(node): - pass -def general_prev(node): - pass + # Máme potomka? + if node.first_child is not None: + return node.first_child + # Nemáme potomka. + # Chceme najít následníka sebe, nebo některého (toho nejblíž příbuzného) z našich předků (tatínka, dědečka, ...) + while node.succ is None: + node = get_parent(node) + if node is None: + return None # žádný z předků nemá následníka, takže žádny vrchol nenásleduje. + return node.succ + +def last_brother(node): + while node.succ is not None: + node = node.succ + return node -# Generátor potomků -# TODO: copy-pasta +def general_prev(node): + # Předchůdce je buď rekurzivně poslední potomek předchůdce, nebo náš otec. + # Otce vyřešíme nejdřív: + if safe_pred(node) is None: + return safe_father_of_first(node) + pred = safe_pred(node) + while pred.first_child is not None: + pred = last_brother(pred.first_child) + # 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 potomků níže spoléhá na to, že se tohle dá volat i s parametrem None. +def all_brothers(node): + current = node + while current is not None: + yield current + current = current.succ + +# Generátor potomků +def all_children(node): + brothers = all_brothers(node.first_child) + for br in brothers: + yield br # Generátor následníků v "the-right-order"