feat(stammbaum): gleiches Geburtsdatum der Eltern als Geschwister-Indiz werten
Ein identisches Geburtsdatum bei Vater und Mutter ist ein starkes Indiz für eine Vollgeschwister-Verpaarung — ein gemeinsamer Wurf ist praktisch der einzige Grund dafür, und die Eltern-Würfe sind in den importierten Daten nicht immer verknüpft (gleiche litterId fehlt dann). Die Geschwister-Erkennung (Diagramm-Zusammenführung in build.ts + Akte-Chip in GerbilDetailPage) greift jetzt bei gleicher litterId ODER gleichem, gesetztem Geburtsdatum beider Eltern (distinkte Tiere vorausgesetzt). Tests: gleiches DOB bei fehlender/verschiedener litterId → erkannt; unterschied- liches DOB → nicht erkannt. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -137,14 +137,16 @@ export default function GerbilDetailPage() {
|
|||||||
const lookup = (map: Map<string, string>, key: string | null) => (key ? (map.get(key) ?? '—') : '—')
|
const lookup = (map: Map<string, string>, key: string | null) => (key ? (map.get(key) ?? '—') : '—')
|
||||||
const storedColorName = g.colorVarietyId ? (colorName.get(g.colorVarietyId) ?? null) : null
|
const storedColorName = g.colorVarietyId ? (colorName.get(g.colorVarietyId) ?? null) : null
|
||||||
|
|
||||||
// Geschwisterverpaarung: Vater und Mutter dieses Tiers stammen aus demselben
|
// Geschwisterverpaarung: Vater und Mutter dieses Tiers sind Vollgeschwister —
|
||||||
// Wurf (Vollgeschwister) — erkennbar an gemeinsamer litterId der Eltern.
|
// erkennbar an gemeinsamer litterId ODER gleichem Geburtsdatum (starkes Indiz:
|
||||||
|
// ein identisches Datum entsteht praktisch nur durch einen gemeinsamen Wurf,
|
||||||
|
// und die Eltern-Würfe sind in den Daten nicht immer verknüpft).
|
||||||
const isSiblingPairing =
|
const isSiblingPairing =
|
||||||
!!father.data &&
|
!!father.data &&
|
||||||
!!mother.data &&
|
!!mother.data &&
|
||||||
father.data.id !== mother.data.id &&
|
father.data.id !== mother.data.id &&
|
||||||
!!father.data.litterId &&
|
((!!father.data.litterId && father.data.litterId === mother.data.litterId) ||
|
||||||
father.data.litterId === mother.data.litterId
|
(!!father.data.dateOfBirth && father.data.dateOfBirth === mother.data.dateOfBirth))
|
||||||
|
|
||||||
const parentLink = (
|
const parentLink = (
|
||||||
pid: string | null,
|
pid: string | null,
|
||||||
|
|||||||
@@ -208,6 +208,34 @@ describe('buildPedigree', () => {
|
|||||||
expect(animal(mutter.mother).gerbil.name).toBe('Oma')
|
expect(animal(mutter.mother).gerbil.name).toBe('Oma')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('erkennt Geschwister-Verpaarung am gleichen Geburtsdatum (litterId fehlt/verschieden)', async () => {
|
||||||
|
// Vater und Mutter haben verschiedene litterId, aber dasselbe Geburtsdatum
|
||||||
|
// (starkes Indiz: gemeinsamer Wurf, der in den Daten nicht verknüpft ist).
|
||||||
|
const source = makeSource(
|
||||||
|
[
|
||||||
|
makeGerbil('kind', 'Kind', 'w-kind'),
|
||||||
|
{ ...makeGerbil('vater', 'Vater', 'w-v'), dateOfBirth: '2018-09-22' },
|
||||||
|
{ ...makeGerbil('mutter', 'Mutter', 'w-m'), dateOfBirth: '2018-09-22' },
|
||||||
|
],
|
||||||
|
[makeLitter('w-kind', 'vater', 'mutter')],
|
||||||
|
)
|
||||||
|
const root = await buildPedigree(source, 'kind')
|
||||||
|
expect(animal(root!.mother).siblingPairing).toEqual({ siblingName: 'Vater', siblingPath: 'v' })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('gleiches Geburtsdatum nur bei BEIDEN Eltern (unterschiedliches DOB → keine Verpaarung)', async () => {
|
||||||
|
const source = makeSource(
|
||||||
|
[
|
||||||
|
makeGerbil('kind', 'Kind', 'w-kind'),
|
||||||
|
{ ...makeGerbil('vater', 'Vater', 'w-v'), dateOfBirth: '2018-09-22' },
|
||||||
|
{ ...makeGerbil('mutter', 'Mutter', 'w-m'), dateOfBirth: '2019-05-15' },
|
||||||
|
],
|
||||||
|
[makeLitter('w-kind', 'vater', 'mutter')],
|
||||||
|
)
|
||||||
|
const root = await buildPedigree(source, 'kind')
|
||||||
|
expect(animal(root!.mother).siblingPairing).toBeUndefined()
|
||||||
|
})
|
||||||
|
|
||||||
it('verlangt für Geschwister-Verpaarung dieselbe litterId (Halbgeschwister zählen nicht)', async () => {
|
it('verlangt für Geschwister-Verpaarung dieselbe litterId (Halbgeschwister zählen nicht)', async () => {
|
||||||
// Gemeinsamer Vater (Opa), aber verschiedene Würfe → keine Verpaarung-Marke.
|
// Gemeinsamer Vater (Opa), aber verschiedene Würfe → keine Verpaarung-Marke.
|
||||||
const source = makeSource(
|
const source = makeSource(
|
||||||
|
|||||||
@@ -71,16 +71,20 @@ async function buildAnimal(
|
|||||||
parentNode(source, litter?.motherId, path + 'm', generationsLeft - 1, nextAncestors),
|
parentNode(source, litter?.motherId, path + 'm', generationsLeft - 1, nextAncestors),
|
||||||
])
|
])
|
||||||
|
|
||||||
// Geschwister-Verpaarung: Stammen Vater und Mutter aus DEMSELBEN Wurf
|
// Geschwister-Verpaarung: Vater und Mutter sind Vollgeschwister, wenn sie aus
|
||||||
// (gleiche litterId), sind sie Vollgeschwister. Die Vorfahren-Linie ist dann
|
// DEMSELBEN Wurf stammen (gleiche litterId) ODER am selben Tag geboren sind
|
||||||
// auf beiden Seiten identisch — wir markieren die Mutter, damit das Diagramm
|
// (gleiches Geburtsdatum ist ein starkes Indiz — Würfe sind praktisch der
|
||||||
|
// einzige Grund für ein identisches Datum, und die Daten verknüpfen die
|
||||||
|
// Eltern-Würfe nicht immer). Wir markieren dann die Mutter, damit das Diagramm
|
||||||
// ihren Ast zu einem Verweis auf die Vaterlinie zusammenführt. Die echten
|
// ihren Ast zu einem Verweis auf die Vaterlinie zusammenführt. Die echten
|
||||||
// Vorfahren bleiben im Modell erhalten (Druck-Ahnentafel nutzt sie weiter).
|
// Vorfahren bleiben im Modell erhalten (Druck-Ahnentafel nutzt sie weiter).
|
||||||
if (
|
if (
|
||||||
father.kind === 'animal' &&
|
father.kind === 'animal' &&
|
||||||
mother.kind === 'animal' &&
|
mother.kind === 'animal' &&
|
||||||
father.gerbil.litterId &&
|
father.gerbil.id !== mother.gerbil.id &&
|
||||||
father.gerbil.litterId === mother.gerbil.litterId
|
((father.gerbil.litterId && father.gerbil.litterId === mother.gerbil.litterId) ||
|
||||||
|
(father.gerbil.dateOfBirth != null &&
|
||||||
|
father.gerbil.dateOfBirth === mother.gerbil.dateOfBirth))
|
||||||
) {
|
) {
|
||||||
const markedMother: AnimalNode = {
|
const markedMother: AnimalNode = {
|
||||||
...mother,
|
...mother,
|
||||||
|
|||||||
Reference in New Issue
Block a user