# -*- coding: utf-8 -*- """Rekursive Ahnentafel aus _rpro3.db: verfolgt Eltern-Zeiger (pid_raw/mid_raw) ueber ALLE Generationen zurueck. Gibt Vorfahren + Eltern-Kind-Links aus. python -X utf8 rpro3_pedigree.py "" [dob] """ import sys import compare_rpro3 as C DB = "_rpro3.db" def build(): R = C.load_rpro3(DB) A = R["animals"] by_rid = {a["rid"]: a for a in A} return A, by_rid def norm(s): import re s = (s or "").lower() s = re.split(r"\bvon\b|\bof\b|\bv\.d\.\b|\bgen\.?\b", s)[0] return re.sub(r"[\s._-]", "", s) def find(A, name, dob=None): cs = [a for a in A if norm(a["name"]) == norm(name)] if dob: m = next((a for a in cs if a["dob"] == dob), None) if m: return m return cs[0] if len(cs) == 1 else None def walk(root, by_rid): """Return (nodes {rid:animal}, links [(child_rid, father_rid, mother_rid)]) via ancestors.""" nodes, links, seen = {}, [], set() stack = [root] while stack: a = stack.pop() if not a or a["rid"] in seen: continue seen.add(a["rid"]) nodes[a["rid"]] = a f = by_rid.get(a.get("pid_raw")) m = by_rid.get(a.get("mid_raw")) if f or m: links.append((a["rid"], f["rid"] if f else None, m["rid"] if m else None)) for p in (f, m): if p and p["rid"] not in seen: stack.append(p) return nodes, links if __name__ == "__main__": name = sys.argv[1] dob = sys.argv[2] if len(sys.argv) > 2 else None A, by_rid = build() root = find(A, name, dob) if not root: print("nicht gefunden"); sys.exit(1) nodes, links = walk(root, by_rid) print(f"Wurzel: {root['name']} (*{root['dob']}) | Vorfahren gesamt: {len(nodes)-1} | Links: {len(links)}") # depth per node depth = {root["rid"]: 0} changed = True while changed: changed = False for c, f, m in links: for p in (f, m): if p and c in depth and depth.get(p, -1) < depth[c] + 1: depth[p] = depth[c] + 1 changed = True for rid in sorted(nodes, key=lambda r: depth.get(r, 0)): a = nodes[rid] d = depth.get(rid, 0) print(f" gen{d}: {a['name']} (*{a['dob']}, {a['farbe']} [{a['fcode']}], Herkunft {a['origin']})") print("\nLinks (Kind <- Vater x Mutter):") for c, f, m in links: print(f" {nodes[c]['name']} (*{nodes[c]['dob']}) <- " f"{nodes[f]['name'] if f else '?'} x {nodes[m]['name'] if m else '?'}")