fix(import): Eltern-Alter-Sanity-Check + plausiblere Eltern-Auswahl aus Chart-Refs
Eine Rennmaus lebt max ~6 Jahre, kann also nicht Elternteil eines Tiers sein, das nach ihrem Tod (oder vor ihrer Geburt) geboren wurde. Bisher fehlte diese Prüfung: z. B. war Jayjay (*2013) als Vater von Solice (*2022) eingetragen, und Solice/Silvain (Vollgeschwister, beide *27.03.2022) landeten in getrennten Würfen mit verschiedenen Eltern. - parent_age_plausible(): Elternteil muss vor dem Kind UND innerhalb der Lebensspanne (≤6 J.) geboren sein. Genutzt im Namens-Resolver (Kandidaten- filter) und als finaler Sanity-Pass, der unmögliche FatherId/MotherId verwirft und im Log auflistet. - pick_parent_ref(): bei mehreren widersprüchlichen Chart-parentRefs wird nicht mehr blind der erste genommen, sondern ein alters-plausibler bevorzugt und das Tier der jeweils anderen Elternrolle gemieden (Vollgeschwister-Charts nennen denselben Namen in beiden Slots). Ergebnis: Solice = Lui × Molly = Geschwister von Silvain (gemeinsamer Wurf); 0 Selbst-Verpaarungen, 0 Gender-Rollen-Fehler, 0 Eltern-Alter-Verletzungen über alle 977 Würfe. Tests in test_merge_resolve.py ergänzt. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -154,6 +154,44 @@ check("names_overlap: matching father name", m.names_overlap(litter(None, fname=
|
||||
check("names_overlap: nothing in common", not m.names_overlap(litter(None, fname="A"), litter(None, mname="B")))
|
||||
|
||||
|
||||
# ── parent_age_plausible: born before child, within ~6y lifespan ──
|
||||
check("age: parent 1y before child → plausible", m.parent_age_plausible("16.04.2021", "27.03.2022"))
|
||||
check("age: parent born AFTER child → implausible", not m.parent_age_plausible("2023-01-01", "2022-03-27"))
|
||||
check("age: parent born SAME day → implausible", not m.parent_age_plausible("2022-03-27", "2022-03-27"))
|
||||
check("age: 9 years older (Jayjay→Solice) → implausible", not m.parent_age_plausible("19.06.2013", "27.03.2022"))
|
||||
check("age: exactly ~5y older → plausible", m.parent_age_plausible("01.06.2017", "01.05.2022"))
|
||||
check("age: 7 years older → implausible", not m.parent_age_plausible("25.10.2018", "13.08.2025"))
|
||||
check("age: unknown parent dob → plausible (can't disprove)", m.parent_age_plausible(None, "2022-03-27"))
|
||||
check("age: unknown litter date → plausible", m.parent_age_plausible("2021-04-16", None))
|
||||
|
||||
|
||||
# ── pick_parent_ref: prefer age-plausible ref, avoid duplicating the other role ──
|
||||
def pref(name, role, dob=None):
|
||||
return {"name": name, "roleGuess": role, "dob": dob}
|
||||
|
||||
# Solice case: first father ref (Jayjay, no DOB) loses to the dated, plausible Lui.
|
||||
solice_refs = [
|
||||
pref("Jayjay", "father"),
|
||||
pref("Lui von den Kleinen Chaoten", "mother", "16.04.2021"),
|
||||
pref("Lui von den Kleinen Chaoten", "father", "16.04.2021"),
|
||||
pref("Molly of Black Forest", "mother", "13.09.2021"),
|
||||
]
|
||||
f = m.pick_parent_ref(solice_refs, "father", "27.03.2022")
|
||||
check("pick: father = plausible-dated Lui, not first-listed Jayjay",
|
||||
f and f["name"] == "Lui von den Kleinen Chaoten")
|
||||
mo = m.pick_parent_ref(solice_refs, "mother", "27.03.2022", avoid_name=f["name"])
|
||||
check("pick: mother = Molly (Lui avoided as it is the father)",
|
||||
mo and mo["name"] == "Molly of Black Forest")
|
||||
|
||||
check("pick: a dated-but-impossible ref loses to a plausible one",
|
||||
m.pick_parent_ref([pref("Old", "father", "2010-01-01"), pref("Dad", "father", "2021-01-01")],
|
||||
"father", "2022-03-27")["name"] == "Dad")
|
||||
check("pick: no ref for role → None",
|
||||
m.pick_parent_ref([pref("X", "mother", "2021-01-01")], "father", "2022-03-27") is None)
|
||||
check("pick: single ref is returned",
|
||||
m.pick_parent_ref([pref("Solo", "father")], "father", "2022-03-27")["name"] == "Solo")
|
||||
|
||||
|
||||
if check.failed:
|
||||
print(f"\n{check.failed} test(s) FAILED")
|
||||
sys.exit(1)
|
||||
|
||||
Reference in New Issue
Block a user