// ★ 第二刀的验收读数:【打平的那些 case,tier 和 ceiling 真的都一样吗?】 // 老板逐字:「⚠ 验证我这个判断:穷举里,打平的那些 case,tier 和 ceiling 真的都一样吗? // 有没有「tier 一样但 ceiling 不一样」的?那种不是打平,那种引擎有理由(位阶即杠杆)。 // 跑出来,别信我。」 // ⚠ 读数全部出自引擎自己的 r.kai(产物),不是复算。 import { DYNASTIES, computeRank, computeAxes } from '../src/dynasties.js'; import { SUB_REGISTRY } from '../src/talents.js'; const SUBS = SUB_REGISTRY.map((s) => s.id); const WANGS = [0, 29, 30, 54, 55, 74, 75, 100]; // 每一条【开着但没走】的路,按 (tier 关系, ceiling 关系) × lostAt 交叉列表 const X = {}; // key: `${tierRel}|${ceilRel}` → { lostAt: n } const bump = (tr, cr, lostAt) => { const k = `${tr}|${cr}`; (X[k] || (X[k] = {}))[lostAt] = ((X[k] || {})[lostAt] || 0) + 1; }; // zelu.options 的自检 let optBad = 0, optN = 0, optTierDiff = 0, optCeilDiff = 0; // 引擎的排序器是不是一个自洽的全序:ranked[i] 必须真的赢 ranked[j] (i k.walked); for (const k of r.kai) { if (k.walked) continue; totalNotWalked++; const tr = k.tier === walked.tier ? '=' : k.tier < walked.tier ? '<' : '>'; const cr = k.ceiling === walked.ceiling ? '=' : k.ceiling < walked.ceiling ? '<' : '>'; bump(tr, cr, k.lostAt); if (tr === '=' && cr === '=') SAME[k.lostAt] = (SAME[k.lostAt] || 0) + 1; } // zelu.tie:里面的每一条,tier 与 ceiling 必须与走的那条【全部相同】 const opts = (r.zelu.tie || []).map((t) => t.channelId); if (opts.length > 1) { optN++; for (const id of opts) { const k = r.kai.find((x) => x.channelId === id); if (!k) { optBad++; continue; } if (k.tier !== walked.tier) optTierDiff++; if (k.ceiling !== walked.ceiling) optCeilDiff++; } } // 排序自洽性:kai 的次序就是 ranked 的次序 for (let i = 0; i < r.kai.length; i++) for (let j = i + 1; j < r.kai.length; j++) if (r.kai[j].tier > r.kai[i].tier || (r.kai[j].tier === r.kai[i].tier && r.kai[j].ceiling > r.kai[i].ceiling)) sortViol++; } } const secs = ((Date.now() - t0) / 1000).toFixed(0); const N = (n) => n.toLocaleString(); console.log(`\n══ 【开着但没走】的路:(tier, ceiling) × 输在哪一级 ── ${N(totalNotWalked)} 条次 / ${secs}s ══\n`); console.log('tier ceiling │ ' + ['ceiling', 'tier', 'lex', 'idx', 'unsorted'].map((s) => s.padStart(10)).join('') + ' 合计'); console.log('─'.repeat(78)); for (const key of Object.keys(X).sort()) { const [tr, cr] = key.split('|'); const row = X[key]; const tot = Object.values(row).reduce((a, b) => a + b, 0); console.log(` ${tr} ${cr} │ ` + ['ceiling', 'tier', 'lex', 'idx', 'unsorted'].map((s) => N(row[s] || 0).padStart(10)).join('') + ' ' + N(tot).padStart(10)); } console.log('\n★ 【tier 一样 && ceiling 一样】的条次,按输在哪一级分:'); const sameTot = Object.values(SAME).reduce((a, b) => a + b, 0); for (const k of Object.keys(SAME)) console.log(` ${k.padEnd(10)} ${N(SAME[k]).padStart(11)} (${(SAME[k] / sameTot * 100).toFixed(1)}% of ${N(sameTot)})`); console.log(`\n★ zelu.options:${N(optN)} 格有 >1 个选项;` + `其中 tier 不同 ${N(optTierDiff)} 次、ceiling 不同 ${N(optCeilDiff)} 次、kai 里找不到 ${N(optBad)} 次`); console.log(`★ 排序自洽性(kai 次序里出现「后面的 tier/ceiling 反而更高」):${N(sortViol)} 次`);