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("