List a child of several families of a parent once (#1502)

A child in two families of the same parent, such as a child whose
mother remarried, appeared twice in the descendant and hourglass charts,
with everything below them doubled. The child is now listed once, from
their primary parent family if it is one of the parent's families.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
David Straub
2026-10-07 21:21:10 +02:00
committed by GitHub
parent 6514158f57
commit cd0b4dbfa4
2 changed files with 49 additions and 2 deletions
+17 -2
View File
@@ -94,18 +94,33 @@ export class FamilyGraph {
}
// Returns the person's children in all families where they are a parent,
// each with its `handle` and its `relation` to this parent
// each with its `handle` and its `relation` to this parent. A child in
// several of these families, such as a child of a parent who remarried, is
// listed once, from their primary parent family if it is one of them and
// otherwise from the first.
childRelations(handle) {
return this.partnerFamilies(handle).flatMap(family => {
const entries = this.partnerFamilies(handle).flatMap(family => {
const isFather = family.father_handle === handle
if (!isFather && family.mother_handle !== handle) {
return []
}
return (family.child_ref_list || []).map(childRef => ({
family,
handle: childRef.ref,
relation: (isFather ? childRef.frel : childRef.mrel) || 'Birth',
}))
})
const chosen = new Map()
for (const entry of entries) {
const primary = this.person(entry.handle)?.extended?.primary_parent_family
?.handle
if (!chosen.has(entry.handle) || entry.family.handle === primary) {
chosen.set(entry.handle, entry)
}
}
return entries
.filter(entry => chosen.get(entry.handle) === entry)
.map(({handle: child, relation}) => ({handle: child, relation}))
}
// Returns the handles of the person's children in all families where they
+32
View File
@@ -82,6 +82,38 @@ describe('FamilyGraph', () => {
})
})
it('lists a child in several families of the parent once', () => {
// M had G with an unknown father, then married S, who took G in
const fFirst = family('fFirst', '', 'M', [childRef('G')])
const fSecond = family('fSecond', 'S', 'M', [
childRef('H'),
childRef('G', 'Stepchild', 'Birth'),
])
const people = (...families) => [
{handle: 'M', extended: {families}},
{handle: 'S', extended: {families: [fSecond]}},
{handle: 'G', extended: {primary_parent_family: fFirst}},
]
// From the primary parent family, wherever it is in the family list
expect(
new FamilyGraph(people(fSecond, fFirst)).childRelations('M')
).toEqual([
{handle: 'H', relation: 'Birth'},
{handle: 'G', relation: 'Birth'},
])
expect(
new FamilyGraph(people(fFirst, fSecond)).childRelations('S')
).toEqual([
{handle: 'H', relation: 'Birth'},
{handle: 'G', relation: 'Stepchild'},
])
// From the first family for a child who was not fetched
const unfetched = new FamilyGraph([
{handle: 'M', extended: {families: [fSecond, fFirst]}},
])
expect(unfetched.children('M')).toEqual(['H', 'G'])
})
it('returns no children for a person without families', () => {
expect(graph.children('S')).toEqual([])
expect(graph.children('X')).toEqual([])