@BogdanMetelsky

Как определелить ребёнка от второго брака?

Код по построению графа (древа семьи). Нужно найти и преобразовать связи между узлами. Проблема в определении ребёнка от второго брака. ???
Создаю сайт по построению древа семьи. Использую react, react-flow для визуализации графа, dagre для расчёта координат узлов.

Не получается написать правильный код добавления детей к браку. Если у родителей был только один брак, то всё ок. Но если у кого-то из родителей был ребёнок от второго брака, то этот ребёнок может записаться не к тому браку. Нужно, чтобы ребёнок привязывался к браку, в котором муж и жена соответствуют обоим родителям.

Изначально данные связей получаю в таком виде:
spoiler
{ id: "8", source: "1", target: "4", types: "marriage", type: edgeType },  // связь брака от мужа к жене
    { id: "1", source: "1", target: "2", types: "children", type: edgeType },  // связь от одного родителя к ребёнку
    { id: "2", source: "4", target: "2", types: "children", type: edgeType },  // связь от другого родителя к ребёнку
    { id: "5", source: "5", target: "4", types: "marriage", type: edgeType },  // связь брака от мужа к жене (второй брак жены)
    { id: "6", source: "5", target: "1", types: "children", type: edgeType },  // связь от одного родителя к ребёнку
    { id: "7", source: "4", target: "1", types: "children", type: edgeType } // связь от другого родителя к ребёнку


Если из них построить древо без изменения связей, то оно будет выглядеть так:
spoiler
CYjfMduW.jpg?download=1&name=%D0%A1%D0%BA%D1%80%D0%B8%D0%BD%D1%88%D0%BE%D1%82%2011-05-2023%2002:17:05.jpg
Из скриншота видно, что муж на уровень выше своей жены, что нежелательно. От каждого родителя идут линии к каждому ребёнку, что создаёт хаос.

Для более симпатичного отображения решил преобразовать изначальные связи по следующим правилам:
1. Из связи с types: "marriage" создаю узел брака;
2. От мужа и жены создаю связи к браку;
3. В дальнейшем удаляю первоначальную связь от мужа к жене.
4. Создаю связь от брака родителей к ребёнку; - как раз на этом этапе возникает сложность!!!
5. В дальнейшем удаляю связь от родителей к ребёнку.

Теперь древо получается более понятным:
spoiler
uECB3ASc.jpg?download=1&name=%D0%A1%D0%BA%D1%80%D0%B8%D0%BD%D1%88%D0%BE%D1%82%2011-05-2023%2002:23:11.jpg

Однако связь к "Максиму" (в самом низу) должна идти от другого брака и тоже самое про ребёнка "Текля"

Код связей и узлов
const position = { x: 0, y: 0 };
const edgeType = "smoothstep";

export const initialNodes = [
    {
        id: "1",
        type: 'person',
        data: {
            lastName: "Метельский",
            firstName: "Геннадий",
            middleName: "Георгиевич",
            birthdate: '1992-04-25',
            birthPlace: "г. Киев, Украина",
            religion: "Orthodoxy",
            nationality: "Russian",
            isAlive: false,
            deathDate: '1292-04-25',
            deathPlace: "г. Киев, Украина",
            burialPlace: "Киевское кладбище",
            causeOfDeath: "тяжелое заболевание",
            photoUrl: 'https://www.geeksvgs.com/files/2019/02/dd85b_grandfather.thumb.png',
            event: ["vov", "plen", "rep"],
            sex: "m"
        },
        position: { x: 0, y: 0 },
    },
    {
        id: "2",
        type: 'person',
        data: {
            lastName: "Метельский",
            firstName: "Богдан",
            middleName: "Геннадьевич",
            birthdate: '25.04.1992',
            birthPlace: "г. Киев, Украина",
            religion: "Orthodoxy",
            nationality: "Ukrainian",
            isAlive: true,
            photoUrl: 'https://www.geeksvgs.com/files/2019/02/dd85b_grandfather.thumb.png',
            sex: "m"
        },
        position: { x: 0, y: 0 },
    },
    {
        id: "3",
        type: 'person',
        data: {
            lastName: "Метельская",
            firstName: "Алина",
            middleName: "Геннадьевна",
            birthdate: '25.04.1992',
            birthPlace: "г. Киев, Украина",
            religion: "Orthodoxy",
            nationality: "Ukrainian",
            isAlive: true,
            photoUrl: 'https://www.geeksvgs.com/files/2019/02/dd85b_grandfather.thumb.png',
            sex: "f"
        },
        position: { x: 0, y: 0 },
    },
    {
        id: "4",
        type: 'person',
        data: {
            lastName: "Метельская",
            firstName: "Татьяна",
            middleName: "Васильевна",
            birthdate: '24.02.1991',
            birthPlace: "г. Одесса, Украина",
            religion: "Catholicism",
            nationality: "Ukrainian",
            isAlive: true,
            photoUrl: 'https://www.geeksvgs.com/files/2019/02/dd85b_grandfather.thumb.png',
            sex: "f"
        },
        position: { x: 0, y: 0 }
    },
    {
        id: "5",
        type: 'person',
        data: {
            lastName: "Метельский",
            firstName: "Георгий",
            middleName: "Ясонович",
            birthdate: '24.02.1991',
            birthPlace: "г. Одесса, Украина",
            religion: "Catholicism",
            nationality: "Ukrainian",
            isAlive: true,
            photoUrl: 'https://www.geeksvgs.com/files/2019/02/dd85b_grandfather.thumb.png',
            sex: "m"
        },
        position: { x: 0, y: 0 },
    }
];


export const initialEdges = [
    { id: "8", source: "1", target: "4", types: "marriage", type: edgeType },
    { id: "1", source: "1", target: "2", types: "children", type: edgeType },
    { id: "4", source: "4", target: "2", types: "children", type: edgeType },
    { id: "5", source: "5", target: "4", types: "marriage", type: edgeType },
    { id: "6", source: "4", target: "3", types: "children", type: edgeType },
    { id: "7", source: "5", target: "3", types: "children", type: edgeType },
];


Часть кода преобразования связей и создания узлов брака
const getLayoutedElements = (nodes, edges/*, direction = "TB"*/) => {
    /*dagreGraph.setGraph({ rankdir: direction });*/

    //nodes.forEach((node) => {
    //    dagregraph.setnode(node.id, { width: nodewidth, height: nodeheight });
    //});

    const childMarriages = {};

    edges.forEach((edge) => {
        if (edge.types === "marriage") {
            const marriageId = `${edge.source}-marriage-${edge.target}`;
            const marriageNode = {
                id: marriageId,
                types: "marriage",
                position,
                data: {
                    husband: edge.source,
                    wife: edge.target,
                    children: [],
                },
            };

            const husbandToMarriage = {
                id: `${edge.source}-to-${marriageId}`,
                source: edge.source,
                target: marriageId,
                type: edgeType,
            };
            const wifeToMarriage = {
                id: `${edge.target}-to-${marriageId}`,
                source: edge.target,
                target: marriageId,
                type: edgeType,
            };
            // Переносим фильтрацию связей типа "children" внутрь map
            const childrenFromMarriage = edges
                .filter((childEdge) => childEdge.types === "children")
                .map((childEdge) => {
                    const childNode = nodes.find((node) => node.id === childEdge.target);
                    if (childNode) {
                        const childId = childNode.id;
                        // Проверяем, принадлежит ли ребенок к данному браку
                        if (
                            (childEdge.source === edge.source ||
                                childEdge.source === edge.target) &&
                            childMarriages[childId] === undefined // Проверяем, что у ребенка еще нет браков
                        ) {
                            childMarriages[childId] = marriageId;
                            marriageNode.data.children.push(childId);
                            return {
                                id: `${marriageId}-to-${childId}`,
                                source: marriageId,
                                target: childId,
                                type: "smoothstep",
                            };
                        }
                    }
                    return null;
                })
                .filter(Boolean);

            nodes.push(marriageNode);
            edges.push(husbandToMarriage);
            edges.push(wifeToMarriage);
            childrenFromMarriage.forEach((edge) => edges.push(edge));
        }
    });
    edges = edges.filter((edge) => edge.types !== "children");
    edges = edges.filter((edge) => edge.types !== "marriage");

    return { nodes, edges };
};


Ещё я пробовал решить вопрос указыванием в связи родителя с ребёнком где отец, а где мать ,чтобы коду было проще найти брак в котором отец = муж и мать = жена. Но у меня ничего не получилось.
spoiler
{ id: "8", source: "1", target: "4", types: "marriage", type: edgeType },
    { id: "1", source: "1", target: "2", types: "Father", type: edgeType },
    { id: "3", source: "4", target: "2", types: "Mother", type: edgeType}

  • Вопрос задан
  • 556 просмотров
Пригласить эксперта
Ответы на вопрос 2
есть формат GEDCOM
а впереди у вас ещё варианты приёмных детей, сирот и другие "прелести" генеалогических древ
Ответ написан
@Dementor
программист, архитектор, аналитик
Посмотрите как сделано у ведущих экспертов в этой области - у www.myheritage.com и скопипасте себе их идеи. Если кратко, то у одного человека может быть несколько семейных древ - по каждому на пару родителей.

А вот с парами родителей там затык - слишком привязываются к биологии: нельзя сделать М+М, Ж+Ж, Ж+М+Ж, МММ и прочие популярные комбинации. Вам если эту недоработку в своем сайте исправить, то пользователи с Европы попрут - там сейчас это тренд.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы