Files
tangfamily/debug-sort.js
2026-06-24 22:13:01 +08:00

194 lines
10 KiB
JavaScript

const members = [{"id":"4661dd7b-f3b9-42d1-bf00-b14899e2a92e","name":"唐治明","birthYear":1960,"gender":"男","generation":"父亲","fatherId":"f24a95c7-fa68-4f56-b0ed-e1f7fb2c91e1"},{"id":"d4498bfb-c0ce-4218-bc8f-3f0cc0cf6984","name":"舒邦莲","birthYear":1960,"gender":"女","generation":"父亲"},{"id":"f24a95c7-fa68-4f56-b0ed-e1f7fb2c91e1","name":"唐有奎","birthYear":1900,"gender":"男","generation":"祖父"},{"id":"1be537aa-88cb-4b82-8c09-e18e05922499","name":"唐治安","birthYear":1960,"gender":"男","generation":"父亲","fatherId":"f24a95c7-fa68-4f56-b0ed-e1f7fb2c91e1"},{"id":"e6d9c5b3-6397-4d88-878b-e22e5c9f512b","name":"万华群","birthYear":1960,"gender":"女","generation":"父亲"},{"name":"唐治芳","birthYear":1960,"gender":"女","generation":"父亲","fatherId":"f24a95c7-fa68-4f56-b0ed-e1f7fb2c91e1","id":"4b78f55d-34b0-4407-a672-3d6b3e826f0f"},{"name":"邓能春","birthYear":1960,"gender":"男","generation":"父亲","id":"a7bcc3b5-c4fc-4fca-8bd4-44cf6078d678"},{"id":"208fb133-6a0b-4540-a1ff-ad8ce154c33f","name":"唐伟","birthYear":1990,"gender":"男","generation":"自己","fatherId":"4661dd7b-f3b9-42d1-bf00-b14899e2a92e","motherId":"d4498bfb-c0ce-4218-bc8f-3f0cc0cf6984"},{"name":"唐永洪","birthYear":1990,"gender":"男","generation":"自己","fatherId":"4661dd7b-f3b9-42d1-bf00-b14899e2a92e","motherId":"d4498bfb-c0ce-4218-bc8f-3f0cc0cf6984","id":"ab86880b-502c-4249-9ce4-ff3327c3fd1b"},{"id":"de8e2fc8-2a1e-4dc1-b010-cd29b9312105","name":"唐雪","birthYear":1990,"gender":"女","generation":"自己","fatherId":"1be537aa-88cb-4b82-8c09-e18e05922499","motherId":"e6d9c5b3-6397-4d88-878b-e22e5c9f512b"},{"name":"唐波","birthYear":1990,"gender":"男","generation":"自己","fatherId":"1be537aa-88cb-4b82-8c09-e18e05922499","motherId":"e6d9c5b3-6397-4d88-878b-e22e5c9f512b","id":"08a22bcd-5af6-4589-8739-9ea796c41a01"},{"name":"邓静","birthYear":1990,"gender":"女","generation":"自己","fatherId":"a7bcc3b5-c4fc-4fca-8bd4-44cf6078d678","motherId":"4b78f55d-34b0-4407-a672-3d6b3e826f0f","id":"1ebd23c6-dadf-4cec-98fe-5bff971bc591"},{"id":"4c3f6e87-8756-48de-9141-5881778974ce","name":"邓正悦","birthYear":1990,"gender":"女","generation":"自己","fatherId":"a7bcc3b5-c4fc-4fca-8bd4-44cf6078d678","motherId":"4b78f55d-34b0-4407-a672-3d6b3e826f0f"},{"name":"张红","birthYear":1990,"gender":"女","generation":"自己","id":"a74c5ba0-5fe1-4862-a651-f81b641deb72"},{"name":"郭思琪","birthYear":1990,"gender":"女","generation":"自己","id":"95672071-9f60-4728-9209-00a24a01fb3a"},{"id":"a1fa7080-3e49-49bb-b2d7-ec94e005369f","name":"唐世宁","birthYear":2020,"gender":"女","generation":"子女","fatherId":"ab86880b-502c-4249-9ce4-ff3327c3fd1b","motherId":"95672071-9f60-4728-9209-00a24a01fb3a"},{"id":"74ab3d7a-3dad-4279-aecb-13e7ef12c0ff","name":"唐瑾瑜","birthYear":2020,"gender":"女","generation":"子女","fatherId":"08a22bcd-5af6-4589-8739-9ea796c41a01","motherId":"a74c5ba0-5fe1-4862-a651-f81b641deb72"},{"id":"6365ca6a-f31f-4b7a-b233-bc5a101f7025","name":"唐世严","birthYear":2020,"gender":"男","generation":"子女","fatherId":"08a22bcd-5af6-4589-8739-9ea796c41a01","motherId":"a74c5ba0-5fe1-4862-a651-f81b641deb72"}];
const GEN_ORDER = ['鼻祖','远祖','太祖','烈祖','天祖','高祖','曾祖','祖父','父亲','自己','子女','孙辈','曾孙','玄孙','来孙','晜孙','仍孙','云孙','耳孙'];
const map = {};
members.forEach(m => map[m.id] = m);
const childrenOf = {};
members.forEach(m => {
if (m.fatherId && map[m.fatherId]) (childrenOf[m.fatherId] = childrenOf[m.fatherId] || []).push(m.id);
if (m.motherId && map[m.motherId]) (childrenOf[m.motherId] = childrenOf[m.motherId] || []).push(m.id);
});
Object.keys(childrenOf).forEach(pid => { childrenOf[pid] = [...new Set(childrenOf[pid])]; });
const rankOf = {};
members.forEach(m => {
if (m.generation) {
const idx = GEN_ORDER.indexOf(m.generation);
rankOf[m.id] = (idx >= 0 ? idx : 9) * 1000;
}
});
const bfsQueue = Object.keys(rankOf);
const visitedBFS = new Set(bfsQueue);
let qi = 0;
while (qi < bfsQueue.length) {
const pid = bfsQueue[qi++];
(childrenOf[pid] || []).forEach(cid => {
const needed = Math.max(
map[cid].fatherId && rankOf[map[cid].fatherId] !== undefined ? rankOf[map[cid].fatherId] + 1000 : 0,
map[cid].motherId && rankOf[map[cid].motherId] !== undefined ? rankOf[map[cid].motherId] + 1000 : 0
);
if (rankOf[cid] === undefined || needed > rankOf[cid]) rankOf[cid] = needed;
if (!visitedBFS.has(cid)) { visitedBFS.add(cid); bfsQueue.push(cid); }
});
}
members.forEach(m => { if (rankOf[m.id] === undefined) rankOf[m.id] = 9 * 1000; });
const uniqueRanks = [...new Set(Object.values(rankOf))].sort((a, b) => a - b);
const rankToRow = {};
uniqueRanks.forEach((r, i) => { rankToRow[r] = i; });
const rowOf = {};
members.forEach(m => { rowOf[m.id] = rankToRow[rankOf[m.id]]; });
const families = {};
const familyKeyOfChild = {};
members.forEach(child => {
const fatherId = child.fatherId && map[child.fatherId] ? child.fatherId : '';
const motherId = child.motherId && map[child.motherId] ? child.motherId : '';
if (!fatherId && !motherId) return;
const key = `${fatherId}|${motherId}`;
familyKeyOfChild[child.id] = key;
if (!families[key]) families[key] = { fatherId: fatherId || null, motherId: motherId || null, children: [] };
families[key].children.push(child.id);
});
const familyOrderList = Object.keys(families)
.map(key => {
const fam = families[key];
const fatherYear = fam.fatherId ? map[fam.fatherId].birthYear : -Infinity;
const motherYear = fam.motherId ? map[fam.motherId].birthYear : -Infinity;
return { key, orderYear: Math.max(fatherYear, motherYear) };
})
.sort((a, b) => b.orderYear - a.orderYear || a.key.localeCompare(b.key));
const familyOrderIndex = {};
familyOrderList.forEach((item, idx) => { familyOrderIndex[item.key] = idx; });
const parentFamilyIndices = {};
Object.keys(families).forEach(key => {
const fam = families[key];
const idx = familyOrderIndex[key];
if (fam.fatherId) (parentFamilyIndices[fam.fatherId] = parentFamilyIndices[fam.fatherId] || []).push(idx);
if (fam.motherId) (parentFamilyIndices[fam.motherId] = parentFamilyIndices[fam.motherId] || []).push(idx);
});
const parentPrimaryFamilyKey = {};
Object.keys(parentFamilyIndices).forEach(pid => {
const indices = parentFamilyIndices[pid];
const minIdx = Math.min(...indices);
parentPrimaryFamilyKey[pid] = familyOrderList[minIdx] ? familyOrderList[minIdx].key : null;
});
function compareByBirthName(a, b) {
if (a.birthYear !== b.birthYear) return b.birthYear - a.birthYear;
return a.name.localeCompare(b.name, 'zh-Hans-CN');
}
function sortRowWithParentOrder(row, prevOrderIndex) {
const memberSet = new Set(row.map(m => m.id));
// 找出当前行中的配偶关系(双方都在当前行)
const spouseOf = {};
Object.keys(families).forEach(key => {
const fam = families[key];
if (!fam || !fam.fatherId || !fam.motherId) return;
if (memberSet.has(fam.fatherId) && memberSet.has(fam.motherId)) {
spouseOf[fam.fatherId] = fam.motherId;
spouseOf[fam.motherId] = fam.fatherId;
}
});
// 按父母分组
const parentGroups = {};
row.forEach(m => {
const key = familyKeyOfChild[m.id] || `solo:${m.id}`;
if (!parentGroups[key]) parentGroups[key] = [];
parentGroups[key].push(m);
});
// 计算每个父母组的排序索引
function getParentGroupIndex(key) {
if (key.startsWith('solo:')) return null;
const parts = key.split('|');
const fId = parts[0] || null;
const mId = parts[1] || null;
const indices = [];
if (fId && prevOrderIndex[fId] !== undefined) indices.push(prevOrderIndex[fId]);
if (mId && prevOrderIndex[mId] !== undefined) indices.push(prevOrderIndex[mId]);
return indices.length > 0 ? Math.min(...indices) : null;
}
// 对父母组排序
const sortedGroupKeys = Object.keys(parentGroups).sort((a, b) => {
const aIdx = getParentGroupIndex(a);
const bIdx = getParentGroupIndex(b);
if (aIdx !== null && bIdx !== null && aIdx !== bIdx) return aIdx - bIdx;
if (aIdx !== null && bIdx === null) return -1;
if (aIdx === null && bIdx !== null) return 1;
return a.localeCompare(b);
});
// 展开每个父母组,先放兄弟姐妹,再放他们的配偶
const result = [];
const processed = new Set();
sortedGroupKeys.forEach(groupKey => {
const groupMembers = parentGroups[groupKey].slice().sort(compareByBirthName);
const spousesToAdd = [];
// 先添加所有兄弟姐妹
groupMembers.forEach(m => {
if (processed.has(m.id)) return;
result.push(m);
processed.add(m.id);
// 记录需要添加的配偶(如果配偶不在当前组)
const spouseId = spouseOf[m.id];
if (spouseId && memberSet.has(spouseId) && !processed.has(spouseId)) {
const spouseKey = familyKeyOfChild[spouseId] || `solo:${spouseId}`;
if (spouseKey !== groupKey) {
spousesToAdd.push(map[spouseId]);
}
}
});
// 然后添加配偶
spousesToAdd.forEach(spouse => {
if (!processed.has(spouse.id)) {
result.push(spouse);
processed.add(spouse.id);
}
});
});
return result;
}
function sortTopRow(row) {
const sorted = row.slice().sort((a, b) => {
const aKey = parentPrimaryFamilyKey[a.id];
const bKey = parentPrimaryFamilyKey[b.id];
if (aKey && bKey && aKey === bKey) {
const fam = families[aKey];
if (fam && fam.fatherId === a.id && fam.motherId === b.id) return -1;
if (fam && fam.motherId === a.id && fam.fatherId === b.id) return 1;
}
return compareByBirthName(a, b);
});
return sorted;
}
const maxRow = Math.max(...Object.values(rowOf));
const gens = [];
let prevOrderIndex = {};
for (let g = 0; g <= maxRow; g++) {
const rowMembers = members.filter(m => rowOf[m.id] === g);
const ordered = g === 0 ? sortTopRow(rowMembers) : sortRowWithParentOrder(rowMembers, prevOrderIndex);
gens.push(ordered);
prevOrderIndex = {};
ordered.forEach((m, idx) => { prevOrderIndex[m.id] = idx; });
console.log(`${g}行排序结果: ${ordered.map(m => m.name).join(', ')}`);
}