summaryrefslogtreecommitdiff
path: root/make_tree.py
diff options
context:
space:
mode:
authorBlaise Thompson <blaise@untzag.com>2020-05-30 06:54:02 -0500
committerBlaise Thompson <blaise@untzag.com>2020-05-30 06:54:02 -0500
commita0ea0199b480f78e2e7a2e317149a152097557ce (patch)
tree2559102c2bb4c5da26999a9d983bbf7603f54b11 /make_tree.py
parent2cfcec1a2ff0fb7b57786f11d99586f66bb98ba9 (diff)
tree
Diffstat (limited to 'make_tree.py')
-rw-r--r--make_tree.py156
1 files changed, 156 insertions, 0 deletions
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("<svg width="):
+ svg_out += '<svg width="100%" height="auto"\n'
+ else:
+ svg_out += line
+ with open(directory / "index.html", "w") as f:
+ f.write(template.render(date=date, person=person, svg=svg_out))