summaryrefslogtreecommitdiff
path: root/make_tree.py
blob: 39a520d81530c13c86e3cf8dc87946b60cfe8aee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
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))