v18b: 修「配偶站到了我左边」—— 户的主位改用「与我的血缘距离」判定

用户上线后如果细看会发现的问题:线上真实数据里
  户 = [红围脖(妻子), 杨永全(我)] —— 妻子被当成了"本家血亲"排在我左边。

根因:服务端判"哪张卡是这一户的血亲位"用的是「**他有父母在本图上**」——
而一对夫妻**两边父母都可能在图上**(我的父母 + 妻子的父母),两边都成立,
于是取到第一个(妻子)。用真实数据量出来的证据:
  户4 = [(3 红围脖), (1 杨永全)],两边都有 parents。

修法:改成按「**与「我」的血缘距离**」判定 —— 先用一次**不带配偶边**的 BFS
算出本家血亲集合(与 Kinship::bloodRelatives 同义),两边都在集合里时,
取"离我更近"的那一位当主位。修完线上实测:
  户5 = [杨永全, 红围脖]  ← 我在左、妻子在右,符合参考实现「配偶排右手边」。

顺带把移动端几何里的卡片比例断言从 v17 的 118:92 更新到 v18 的 88:106
(卡片形状换了,旧常量会让它误报)。移动端几何 520 项全过。

验证:真实数据(11 人)渲染 —— 0 重叠、11 条连线、无 JS 报错;
位置核对:我在 751、妻子在我右 863、年长的姐姐在我左 458、
父母在我上方居中(665/777)、儿子在我右下(975)、外甥在姐姐下方。其余功能未动。
This commit is contained in:
2026-10-02 13:38:34 +08:00
parent 11c13a4e9d
commit 693eb64d65
+30 -12
View File
@@ -75,21 +75,39 @@ foreach ($units as $i => $u) {
if (!$cards) { if (!$cards) {
continue; continue;
} }
// ⚠️ 户内部:**血亲在前、配偶在后**(配偶排右手边)。 // ⚠️⚠️ 户内部:**本家血亲在前、配偶在后**(配偶排右手边,参考实现就是这样)。
// 只按长幼排会让"妻子排到丈夫左边",夫妻横线看着别扭。 //
$head = null; // "血亲"不能只按"他有父母在本图上"判定 —— 一对夫妻**两边父母都可能在图上**
foreach ($cards as $c) { // (我的父母 + 妻子的父母),那样两边都算血亲,取到第一个就成了"妻子当主位、
// 血亲 = 这个户里"有父母在本图上"的那一位;都没有就取第一位 // 我排在她右边"(实测线上就是这个症状:红围脖@639 在我的左边)。
if ($head === null) { //
$head = $c; // 正解:按「**与"我"的血缘距离**」判定 —— 这一户里离「我」更近的那一位才是主位。
} // 我用一次不带配偶边的 BFS 算出血亲集合(Kinship::bloodRelatives 语义),
foreach ($graph['parents'][(int)$c['id']] ?? [] as $par) { // 两边都在血亲集合里时,退到「与我的步数」比大小。
if (isset($unitOf[(int)$par]) && (int)$unitOf[(int)$par] !== $i) { $blood = [];
$head = $c; $bq = [$meId];
break 2; $blood[$meId] = true;
while ($bq) {
$bid = array_shift($bq);
foreach (array_merge($graph['parents'][$bid] ?? [], $graph['children'][$bid] ?? []) as $nb) {
$nb = (int)$nb;
if (!isset($blood[$nb])) {
$blood[$nb] = true;
$bq[] = $nb;
} }
} }
} }
$head = null;
$headScore = null;
foreach ($cards as $c) {
$cid = (int)$c['id'];
// 分数越小越"本家":0 = 血亲本身,1 = 配偶,2 = 其它
$sc = isset($blood[$cid]) ? 0 : 1;
if ($head === null || $sc < $headScore) {
$head = $c;
$headScore = $sc;
}
}
if ($head !== null) { if ($head !== null) {
$rest = []; $rest = [];
foreach ($cards as $c) { foreach ($cards as $c) {