Files
InfoRSI/tests/rules-fixtures-helpers.ts
T
iomgaa 60c21ae346 feat: 研究规则 rules 模块(任务书 02)
rules 是纯计算,src/rules 共 1761 行:方法.md 第六部分的全部公式、第七部分的余额与扣次、4.2 的入口分配,以及种子与规则登记表。

预期值有三个来源:方法.md 的手算例;tests/fixtures/rules/ 下不看实现写的 Python 脚本;参考项目 calc15、calc14b 里与现行方法一致的部分。审阅做了两轮,每轮都换一个全新上下文的子 Agent,提出的问题都已修复或写明不修的理由。

用户确认的约定(原话"1–8 都同意"):入池、采纳、消融中发现都用严格不等号;成本用 max(0, ĝ₀);没测的格附"含它的最好组合"的净值;战绩在分数原值上判。三个数改为严格递增后,删掉了尖峰的全部专门处理(bfb96ba)。vocab 里 Range 的说明同步改为严格递增。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 01:50:21 -04:00

66 lines
2.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import type { Range } from "../src/vocab/index.ts";
// tests/fixtures/rules/ 下的预期值由独立的 Python 脚本照 docs/方法.md 和约定表算出(脚本开头注释写了格式)。
// 这里只负责读文件和比较数字;把场景映射到 rules 的函数上,在各个 rules-fixtures-*.test.ts 里做。
export interface Scenario {
name: string;
section: string;
params: Record<string, any>;
input: Record<string, any>;
expected: any;
note: string;
}
export interface FixtureFile {
generator: string;
tolerance: Record<string, any>;
models?: Record<string, { params: Record<string, any>; input: Record<string, any> }>;
scenarios: Scenario[];
}
export function loadFixture(file: string): FixtureFile {
return JSON.parse(readFileSync(new URL(`./fixtures/rules/${file}`, import.meta.url), "utf8")) as FixtureFile;
}
/** 按名字取场景,并登记"已覆盖";每个测试文件最后核对 JSON 里的场景都被取过。 */
export function scenarioPicker(fixture: FixtureFile): {
get: (name: string) => Scenario;
unused: () => string[];
} {
const used = new Set<string>();
return {
get(name) {
const s = fixture.scenarios.find((x) => x.name === name);
assert.ok(s, `JSON 里没有场景 ${name}`);
used.add(name);
return s;
},
unused: () => fixture.scenarios.map((s) => s.name).filter((n) => !used.has(n)),
};
}
/** 绝对误差 tol 以内算相同。 */
export function close(actual: number, expected: number, tol: number, what: string): void {
assert.ok(
Number.isFinite(actual) && Math.abs(actual - expected) <= tol,
`${what}:实现 ${actual},预期 ${expected},差 ${actual - expected},容差 ${tol}`,
);
}
/** 网格值:|差| ≤ 1e-12 + 1e-9·|值|(ablation.json tolerance.grid)。 */
export function closeGrid(actual: number, expected: number, what: string): void {
close(actual, expected, 1e-12 + 1e-9 * Math.abs(expected), what);
}
export function closeArray(actual: readonly number[], expected: readonly number[], tol: number, what: string): void {
assert.equal(actual.length, expected.length, `${what}:长度`);
actual.forEach((a, i) => close(a, expected[i]!, tol, `${what}[${i}]`));
}
export function range(r: { q1: number; q5: number; q9: number }): Range {
return { q1: r.q1, q5: r.q5, q9: r.q9 };
}