From 568db606da300f6820e4b3543084f19a98ff6db6 Mon Sep 17 00:00:00 2001 From: Arc676/Alessandro Vinciguerra Date: Sun, 1 Nov 2026 11:53:33 +0100 Subject: [PATCH] kinship: implement g-rule Allow arbitrary depth Signed-off-by: Arc676/Alessandro Vinciguerra --- frontend/src/utils/kinship/en.js | 61 +++++++++++++++++----- frontend/src/utils/kinship/kinship.test.js | 2 + 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/frontend/src/utils/kinship/en.js b/frontend/src/utils/kinship/en.js index 148b27f..a069651 100644 --- a/frontend/src/utils/kinship/en.js +++ b/frontend/src/utils/kinship/en.js @@ -29,6 +29,15 @@ function times(n) { } } +function grule(n) { + switch (n - 1) { + case 1: + return "Grand" + default: + return `Great-${"great-".repeat(n - 3)}grand` + } +} + export default function nameEn(path) { const { ups, downs, hasSpouse, sex } = kinshipFacts(path) @@ -45,21 +54,45 @@ export default function nameEn(path) { let label if (downs === 0 && ups > 0) { - if (ups === 1) label = g(sex, 'Father', 'Mother', 'Parent') - else if (ups === 2) label = g(sex, 'Grandfather', 'Grandmother', 'Grandparent') - else if (ups === 3) label = g(sex, 'Great-grandfather', 'Great-grandmother', 'Great-grandparent') - else label = `Ancestor, ${ups} generations up` + switch (ups) { + case 1: + label = g(sex, 'Father', 'Mother', 'Parent') + break; + default: + label = `${grule(ups)}${g(sex, 'father', 'mother', 'parent')}` + break; + } } else if (ups === 0 && downs > 0) { - if (downs === 1) label = g(sex, 'Son', 'Daughter', 'Child') - else if (downs === 2) label = g(sex, 'Grandson', 'Granddaughter', 'Grandchild') - else if (downs === 3) label = g(sex, 'Great-grandson', 'Great-granddaughter', 'Great-grandchild') - else label = `Descendant, ${downs} generations down` - } else if (ups === 1 && downs === 1) label = g(sex, 'Brother', 'Sister', 'Sibling') - else if (ups === 2 && downs === 1) label = g(sex, 'Uncle', 'Aunt', 'Uncle/Aunt') - else if (ups === 3 && downs === 1) label = g(sex, 'Great-uncle', 'Great-aunt', 'Great-uncle/aunt') - else if (ups === 1 && downs === 2) label = g(sex, 'Nephew', 'Niece', 'Nibling') - else if (ups === 1 && downs === 3) label = g(sex, 'Grandnephew', 'Grandniece', 'Grandnibling') - else if (ups >= 2 && downs >= 2) { + switch (downs) { + case 1: + label = g(sex, 'Son', 'Daughter', 'Child') + break; + default: + label = `${grule(downs)}${g(sex, 'son', 'daughter', 'child')}` + break; + } + } else if (downs == 1) { + switch (ups) { + case 1: + label = g(sex, 'Brother', 'Sister', 'Sibling') + break; + case 2: + label = g(sex, 'Uncle', 'Aunt', 'Uncle/Aunt') + break; + default: + label = `${grule(ups - 1)}${g(sex, 'uncle', 'aunt', 'uncle/aunt')}` + break; + } + } else if (ups === 1) { + switch (downs) { + case 2: + label = g(sex, 'Nephew', 'Niece', 'Nibling') + break; + default: + label = `${grule(downs - 1)}${g(sex, 'nephew', 'niece', 'nibling')}` + break; + } + } else if (ups >= 2 && downs >= 2) { const degree = Math.min(ups, downs) - 1 const removed = Math.abs(ups - downs) if (removed === 0) label = `${ordinal(degree)} cousin` diff --git a/frontend/src/utils/kinship/kinship.test.js b/frontend/src/utils/kinship/kinship.test.js index f052bee..69ad459 100644 --- a/frontend/src/utils/kinship/kinship.test.js +++ b/frontend/src/utils/kinship/kinship.test.js @@ -56,6 +56,8 @@ describe('nommage français', () => { describe('nommage anglais', () => { it('genre le mot quand le sexe est connu', () => { expect(bothEn(['up'])).toEqual(['Father', 'Mother', 'Parent']) + expect(bothEn(['up', 'up'])).toEqual(['Grandfather', 'Grandmother', 'Grandparent']) + expect(bothEn(['up', 'up', 'up', 'up'])).toEqual(['Great-great-grandfather', 'Great-great-grandmother', 'Great-great-grandparent']) expect(bothEn(['down', 'down'])).toEqual(['Grandson', 'Granddaughter', 'Grandchild']) expect(bothEn(['sibling'])).toEqual(['Brother', 'Sister', 'Sibling']) expect(bothEn(['up', 'sibling'])).toEqual(['Uncle', 'Aunt', 'Uncle/Aunt'])