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))
|