130 lines
3.1 KiB
TypeScript
130 lines
3.1 KiB
TypeScript
import { tokenize, parse } from "./parser";
|
|
import { rollDicePool, roll } from "./roller";
|
|
import type { DicePool } from "./types";
|
|
|
|
/**
|
|
* 骰子引擎测试
|
|
* 在浏览器控制台运行:window.testDiceEngine()
|
|
*/
|
|
|
|
export function testDiceEngine() {
|
|
console.log("=== 骰子引擎测试 ===\n");
|
|
|
|
// 测试用例
|
|
const testCases: Array<{
|
|
name: string;
|
|
formula: string;
|
|
expected: {
|
|
hasPools: number;
|
|
hasModifier?: boolean;
|
|
};
|
|
}> = [
|
|
{
|
|
name: "标准骰子 3d6",
|
|
formula: "3d6",
|
|
expected: { hasPools: 1 },
|
|
},
|
|
{
|
|
name: "单个骰子 d20",
|
|
formula: "d20",
|
|
expected: { hasPools: 1 },
|
|
},
|
|
{
|
|
name: "骰池字面量 {d4,d8}",
|
|
formula: "{d4,d8}",
|
|
expected: { hasPools: 1 },
|
|
},
|
|
{
|
|
name: "带修饰符 3d6kh2",
|
|
formula: "3d6kh2",
|
|
expected: { hasPools: 1, hasModifier: true },
|
|
},
|
|
{
|
|
name: "带修饰符 4d6dl1",
|
|
formula: "4d6dl1",
|
|
expected: { hasPools: 1, hasModifier: true },
|
|
},
|
|
{
|
|
name: "组合骰池 3d6+5",
|
|
formula: "3d6+5",
|
|
expected: { hasPools: 2 },
|
|
},
|
|
{
|
|
name: "负数组合 3d6-2",
|
|
formula: "3d6-2",
|
|
expected: { hasPools: 2 },
|
|
},
|
|
{
|
|
name: "复杂公式 3d6+{d4,d8}kh2-5",
|
|
formula: "3d6+{d4,d8}kh2-5",
|
|
expected: { hasPools: 4, hasModifier: true },
|
|
},
|
|
{
|
|
name: "多个骰池 {d6,d8}+{d10,d12}",
|
|
formula: "{d6,d8}+{d10,d12}",
|
|
expected: { hasPools: 2 },
|
|
},
|
|
{
|
|
name: "Keep Lowest 5d6kl3",
|
|
formula: "5d6kl3",
|
|
expected: { hasPools: 1, hasModifier: true },
|
|
},
|
|
{
|
|
name: "Drop Highest 4d6dh1",
|
|
formula: "4d6dh1",
|
|
expected: { hasPools: 1, hasModifier: true },
|
|
},
|
|
];
|
|
|
|
let passed = 0;
|
|
let failed = 0;
|
|
|
|
for (const tc of testCases) {
|
|
try {
|
|
// 测试词法分析
|
|
const tokens = tokenize(tc.formula);
|
|
console.log(`\n公式:${tc.formula}`);
|
|
console.log(` 令牌:${tokens.length} 个`);
|
|
|
|
// 测试语法分析
|
|
const pools = parse(tokens);
|
|
console.log(` 骰池:${pools.length} 个`);
|
|
|
|
// 测试掷骰
|
|
const result = roll(tc.formula);
|
|
console.log(` 结果:${result.total}`);
|
|
console.log(` 详情:${result.detail}`);
|
|
|
|
// 验证
|
|
if (pools.length >= tc.expected.hasPools) {
|
|
console.log(` ✓ 通过`);
|
|
passed++;
|
|
} else {
|
|
console.log(` ✗ 失败:期望至少 ${tc.expected.hasPools} 个骰池,实际 ${pools.length} 个`);
|
|
failed++;
|
|
}
|
|
|
|
if (tc.expected.hasModifier) {
|
|
const hasMod = pools.some((p) => p.modifier !== undefined);
|
|
if (hasMod) {
|
|
console.log(` ✓ 修饰符正确`);
|
|
} else {
|
|
console.log(` ✗ 修饰符缺失`);
|
|
failed++;
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.log(` ✗ 错误:${e instanceof Error ? e.message : String(e)}`);
|
|
failed++;
|
|
}
|
|
}
|
|
|
|
console.log(`\n=== 测试完成:${passed} 通过,${failed} 失败 ===`);
|
|
return { passed, failed };
|
|
}
|
|
|
|
// 在浏览器环境下暴露到全局
|
|
if (typeof window !== "undefined") {
|
|
(window as any).testDiceEngine = testDiceEngine;
|
|
}
|