tarinai/js/ui_family_data.js
2026-07-01 14:41:05 +09:00

71 lines
3 KiB
JavaScript

"use strict";
function lineageEdgeFamily(family = world.family || {}) {
return family || {};
}
let lineageRelationIndexCache = { family: null, version: null, index: null };
function lineageAddParentEdge(childId, parentId, known, parentsByChild, childrenByParent) {
return globalThis.TarinaiFamilyGraph.addParentEdge(childId, parentId, known, parentsByChild, childrenByParent);
}
function lineageBuildRelationIndex(family) {
return globalThis.TarinaiFamilyGraph.buildRelationIndex(family);
}
function lineageRelationIndex(family = world.family || {}) {
family = lineageEdgeFamily(family);
if (family !== (world.family || {})) return lineageBuildRelationIndex(family);
const version = world.familyVersion || 0;
if (lineageRelationIndexCache.family !== family || lineageRelationIndexCache.version !== version) {
lineageRelationIndexCache = { family, version, index: lineageBuildRelationIndex(family) };
}
return lineageRelationIndexCache.index;
}
function lineageMutualParentIds(n, family = world.family || {}, idSet = null) {
const seen = new Set();
const parents = [];
if (!n?.id) return parents;
const relationIndex = lineageRelationIndex(family);
const candidates = new Set((n.parents || []).filter(Boolean));
// Runtime updates can briefly touch one side first; recover the reciprocal
// edge from the relation index so the archive does not flicker.
for (const parentId of relationIndex.parentsByChild.get(n.id) || []) candidates.add(parentId);
for (const id of candidates) {
if (!id || id === n.id || seen.has(id)) continue;
if (idSet && !idSet.has(id)) continue;
const parent = family[id];
if (!parent) continue;
const childListsParent = Array.isArray(n.parents) && n.parents.includes(id);
const parentListsChild = Array.isArray(parent.children) && parent.children.includes(n.id);
if (!childListsParent && !parentListsChild) continue;
seen.add(id);
parents.push(id);
}
parents.sort((a, b) => lineageNodeSort(family[a], family[b]));
return parents;
}
function lineageMutualChildIds(n, family = world.family || {}, idSet = null) {
const seen = new Set();
const children = [];
if (!n?.id) return children;
const relationIndex = lineageRelationIndex(family);
const candidates = new Set((n.children || []).filter(Boolean));
// Same recovery as above, in the opposite direction.
for (const childId of relationIndex.childrenByParent.get(n.id) || []) candidates.add(childId);
for (const id of candidates) {
if (!id || id === n.id || seen.has(id)) continue;
if (idSet && !idSet.has(id)) continue;
const child = family[id];
if (!child) continue;
const parentListsChild = Array.isArray(n.children) && n.children.includes(id);
const childListsParent = Array.isArray(child.parents) && child.parents.includes(n.id);
if (!parentListsChild && !childListsParent) continue;
seen.add(id);
children.push(id);
}
children.sort((a, b) => lineageNodeSort(family[a], family[b]));
return children;
}