From a0ea0199b480f78e2e7a2e317149a152097557ce Mon Sep 17 00:00:00 2001 From: Blaise Thompson Date: Sat, 30 May 2020 06:54:02 -0500 Subject: tree --- make_tree.py | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 make_tree.py (limited to 'make_tree.py') diff --git a/make_tree.py b/make_tree.py new file mode 100644 index 0000000..39a520d --- /dev/null +++ b/make_tree.py @@ -0,0 +1,156 @@ +import os +import jinja2 +import pathlib +from datetime import datetime +import toml +from dataclasses import dataclass +import subprocess + + +__here__ = pathlib.Path(__file__).resolve().parent + +date = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + +env = jinja2.Environment( + loader=jinja2.FileSystemLoader(str(__here__ / "tree-source" / "templates")) +) + + +# get people -------------------------------------------------------------------------------------- + + +@dataclass +class Person: + index: int + name: str + nee: [str] = None + birthday: str = None + birthplace: str = None + deathday: str = None + parents: [int] = None + children: [int] = None + partners: [int] = None + + +people = {} +for path in os.listdir(__here__ / "tree-source"): + if not path.endswith("toml"): + continue + if "#" in path: + continue + with open(__here__ / "tree-source" / path, "r") as f: + d = toml.loads(f.read()) + d["index"] = int(path.split(".")[0]) + people[d["index"]] = Person(**d) + + +# sort +people = {k: v for k, v in sorted(people.items())} + + +# generate graphs --------------------------------------------------------------------------------- + + +@dataclass +class Node: + person: object + distance: int + level: int + + +@dataclass +class Edge: + a: int + b: int + relationship: str + + +for index, person in people.items(): + directory = __here__ / "tree-source" / "graphs" + if not os.path.isdir(directory): + os.mkdir(directory) + nodes = {} + edges = [] + todo = [Node(person=person, distance=0, level=0)] + + def add_edge(edge): + for old in edges: + if old.a == edge.a and old.b == edge.b: + return + if old.b == edge.a and old.a == edge.b: + return + edges.append(edge) + + while todo: + current = todo.pop(0) + if abs(current.distance) < 3: + if current.person.children: + for child in current.person.children: + todo.append( + Node(people[child], current.distance + 1, current.level - 1) + ) + add_edge(Edge(current.person.index, child, "#de935f")) + if current.person.parents: + for parent in current.person.parents: + todo.append( + Node(people[parent], current.distance + 1, current.level + 1) + ) + add_edge(Edge(current.person.index, parent, "#de935f")) + if current.person.partners: + for partner in current.person.partners: + nodes[partner] = Node( + people[partner], current.distance + 1, current.level + ) + add_edge(Edge(current.person.index, partner, "#b5db68")) + nodes[current.person.index] = current + min_level = 0 + max_level = 0 + for node in nodes.values(): + node.person.name = node.person.name.replace(" ", "\n") + if node.level < min_level: + min_level = node.level + if node.level > max_level: + max_level = node.level + print(person.name, min_level, max_level) + template = env.get_template("graph.dot") + name = str(person.index).zfill(3) + with open(directory / (name + ".dot"), "w") as f: + f.write( + template.render( + nodes=nodes.values(), + edges=edges, + person=person, + min_level=min_level, + max_level=max_level, + ) + ) + os.chdir(directory) + subprocess.call(["dot", "-Tsvg", name + ".dot", "-o", name + ".svg"]) + + +# index html -------------------------------------------------------------------------------------- + + +template = env.get_template("index.html") +with open(__here__ / "public" / "tree" / "index.html", "w") as f: + f.write(template.render(date=date, people=people)) + + +# people ------------------------------------------------------------------------------------------ + + +for index, person in people.items(): + directory = __here__ / "public" / "tree" / str(person.index).zfill(3) + if not os.path.isdir(directory): + os.mkdir(directory) + template = env.get_template("person.html") + svg = __here__ / "tree-source" / "graphs" / (str(person.index).zfill(3) + ".svg") + svg_out = "" + with open(svg, "r") as f: + for line in f: + if line.startswith("