| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 |
- import { Injectable } from '@angular/core';
- import { Family } from '../models/family';
- import { MarriageRelation } from '../models/marriage-relation';
- import { Kakocho } from '../models/kakocho';
- import { FamilyUnit } from '../models/family-unit';
- import { FamilyUnitNode } from '../models/family-unit-node';
-
-
- export interface FamilyTreeNode {
- family: Family;
- kakocho?: Kakocho;
- isDeceased: boolean;
-
- spouses: FamilyTreeNode[];
- children: FamilyTreeNode[];
- parents: FamilyTreeNode[];
- }
-
- @Injectable({
- providedIn: 'root',
- })
- export class FamilyTreeBuilderService {
-
- build(
- families: Family[],
- marriages: MarriageRelation[],
- kakocholist: Kakocho[]
- ): FamilyTreeNode[] {
-
- const nodeMap = new Map<string, FamilyTreeNode>();
-
- const kakochoMap = new Map(
- kakocholist.map(k => [k.familyId, k])
- );
-
- // -----------------------------
- // ① ノード生成(ここで統合)
- // -----------------------------
- families.forEach((family) => {
-
- const kakocho = kakochoMap.get(family.id);
-
- nodeMap.set(family.id, {
- family,
- kakocho,
- isDeceased: !!kakocho,
-
- parents: [],
- children: [],
- spouses: [],
- });
-
- });
-
- // -----------------------------
- // ② 親子関係
- // -----------------------------
- families.forEach((family) => {
-
- const childNode = nodeMap.get(family.id);
- if (!childNode) return;
-
- if (family.fatherId) {
- const father = nodeMap.get(family.fatherId);
- if (father) {
- father.children.push(childNode);
- childNode.parents.push(father);
- }
- }
-
- if (family.motherId) {
- const mother = nodeMap.get(family.motherId);
- if (mother) {
- mother.children.push(childNode);
- childNode.parents.push(mother);
- }
- }
-
- });
-
- // -----------------------------
- // ③ 配偶者関係(current)
- // -----------------------------
- marriages
- .filter(m => m.status === 'current')
- .forEach((m) => {
-
- const p1 = nodeMap.get(m.person1Id);
- const p2 = nodeMap.get(m.person2Id);
-
- if (!p1 || !p2) return;
-
- if (!p1.spouses.some(s => s.family.id === p2.family.id)) {
- p1.spouses.push(p2);
- }
-
- });
-
- // -----------------------------
- // ④ spouseIdフォールバック
- // -----------------------------
- families.forEach((f) => {
-
- if (!f.spouseId) return;
-
- const a = nodeMap.get(f.id);
- const b = nodeMap.get(f.spouseId);
-
- if (!a || !b) return;
-
- if (!a.spouses.some(s => s.family.id === b.family.id)) {
- a.spouses.push(b);
- }
-
- });
-
- return [...nodeMap.values()];
- }
-
- // -----------------------------
- // Roots
- // -----------------------------
- getRoots(nodes: FamilyTreeNode[]): FamilyTreeNode[] {
-
- return nodes.filter(node => {
-
- if (node.parents.length > 0) return false;
-
- if (node.spouses.length > 0) {
- const spouseId = node.spouses[0].family.id;
- return node.family.id < spouseId;
- }
-
- return true;
- });
- }
-
- buildFamilyUnits(
- nodes: FamilyTreeNode[]
- ): FamilyUnit[] {
-
- const units: FamilyUnit[] = [];
-
- const processed =
- new Set<string>();
-
- for (const node of nodes) {
-
- if (node.spouses.length > 0) {
-
- const spouse =
- node.spouses[0];
-
- const key =
- [
- node.family.id,
- spouse.family.id
- ]
- .sort()
- .join('-');
-
- if (
- processed.has(key)
- ) {
- continue;
- }
-
- processed.add(key);
-
- const children =
- nodes
- .filter(child => {
-
- const fatherId =
- child.family.fatherId;
-
- const motherId =
- child.family.motherId;
-
- return (
- (
- fatherId === node.family.id &&
- motherId === spouse.family.id
- )
- ||
- (
- fatherId === spouse.family.id &&
- motherId === node.family.id
- )
- );
-
- })
- .map(child => child.family);
-
- units.push({
-
- id: key,
-
- husband:
- node.family.gender === 'male'
- ? node.family
- : spouse.family,
-
- wife:
- node.family.gender === 'female'
- ? node.family
- : spouse.family,
-
- children
-
- });
-
- } else {
-
- units.push({
-
- id:
- node.family.id,
-
- husband:
- node.family.gender === 'male'
- ? node.family
- : undefined,
-
- wife:
- node.family.gender === 'female'
- ? node.family
- : undefined,
-
- children: []
-
- });
-
- }
-
- }
-
- return units;
- }
-
- buildFamilyUnitTree(
- units: FamilyUnit[]
- ): FamilyUnitNode[] {
-
- const nodeMap =
- new Map<string, FamilyUnitNode>();
-
- units.forEach(unit => {
-
- nodeMap.set(unit.id, {
-
- unit,
-
- children: [],
-
- parents: []
-
- });
-
- });
-
- units.forEach(parentUnit => {
-
- parentUnit.children.forEach(child => {
-
- const childUnit =
- units.find(u => {
-
- return (
- u.husband?.id === child.id ||
- u.wife?.id === child.id
- );
-
- });
-
- if (!childUnit) {
- return;
- }
-
- const parentNode =
- nodeMap.get(parentUnit.id)!;
-
- const childNode =
- nodeMap.get(childUnit.id)!;
-
- parentNode.children.push(
- childNode
- );
-
- childNode.parents.push(
- parentNode
- );
-
- });
-
- });
-
- return [
- ...nodeMap.values()
- ];
- }
-
- getUnitRoots(
- nodes: FamilyUnitNode[]
- ): FamilyUnitNode[] {
-
- return nodes.filter(
- x =>
- x.parents.length === 0
- );
-
- }
- }
|