chore: clean up dice roller
This commit is contained in:
parent
1f5ee24a0f
commit
b49de62e2c
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
点击下面的骰子来掷骰:
|
点击下面的骰子来掷骰:
|
||||||
|
|
||||||
:md-dice[2d6]
|
:md-dice[2d6] :md-dice[{d4, d8}]
|
||||||
|
|
||||||
:md-dice[3d6kh1] :md-dice[3d6dl2-1]
|
:md-dice[3d6kh1] :md-dice[3d6dl2-1]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,8 @@ const App: Component = () => {
|
||||||
<h1 class="text-2xl font-bold text-gray-900">TTRPG Tools</h1>
|
<h1 class="text-2xl font-bold text-gray-900">TTRPG Tools</h1>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<main class="max-w-4xl mx-auto px-4 py-8 pt-20 md:ml-64 print:p-0">
|
<main class="max-w-4xl mx-auto px-4 py-8 pt-20 md:ml-64 2xl:ml-auto flex justify-center items-center">
|
||||||
<Article class="prose-sm" src={currentPath()} />
|
<Article class="prose-sm max-w-none flex-1" src={currentPath()} />
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,129 +1,11 @@
|
||||||
import { customElement, noShadowDOM } from "solid-element";
|
import { customElement, noShadowDOM } from "solid-element";
|
||||||
import { createSignal, onMount } from "solid-js";
|
import { createSignal, onMount } from "solid-js";
|
||||||
|
import {rollFormula} from "./md-commander/hooks";
|
||||||
|
|
||||||
export interface DiceProps {
|
export interface DiceProps {
|
||||||
key?: string;
|
key?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RollResult {
|
|
||||||
total: number;
|
|
||||||
rolls: number[];
|
|
||||||
detail: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
function rollDice(formula: string): RollResult {
|
|
||||||
const allRolls: number[] = [];
|
|
||||||
let total = 0;
|
|
||||||
const details: string[] = [];
|
|
||||||
|
|
||||||
// 解析骰子公式,支持 + 和 - 运算符
|
|
||||||
// 先按 + 和 - 分割,但保留运算符
|
|
||||||
const tokens = formula
|
|
||||||
.split(/([+-])/)
|
|
||||||
.map((t) => t.trim())
|
|
||||||
.filter((t) => t.length > 0);
|
|
||||||
|
|
||||||
let sign = 1;
|
|
||||||
|
|
||||||
for (let i = 0; i < tokens.length; i++) {
|
|
||||||
const token = tokens[i];
|
|
||||||
|
|
||||||
if (token === "+") {
|
|
||||||
sign = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (token === "-") {
|
|
||||||
sign = -1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理 kh/kl/dh/dl 运算符
|
|
||||||
let processedToken = token;
|
|
||||||
let keepHigh = false;
|
|
||||||
let keepLow = false;
|
|
||||||
let dropHigh = false;
|
|
||||||
let dropLow = false;
|
|
||||||
let keepCount = 0;
|
|
||||||
let dropCount = 0;
|
|
||||||
|
|
||||||
const khMatch = token.match(/^(.+?)kh(\d+)$/i);
|
|
||||||
const klMatch = token.match(/^(.+?)kl(\d+)$/i);
|
|
||||||
const dhMatch = token.match(/^(.+?)dh(\d+)$/i);
|
|
||||||
const dlMatch = token.match(/^(.+?)dl(\d+)$/i);
|
|
||||||
|
|
||||||
if (khMatch) {
|
|
||||||
processedToken = khMatch[1];
|
|
||||||
keepHigh = true;
|
|
||||||
keepCount = parseInt(khMatch[2]);
|
|
||||||
} else if (klMatch) {
|
|
||||||
processedToken = klMatch[1];
|
|
||||||
keepLow = true;
|
|
||||||
keepCount = parseInt(klMatch[2]);
|
|
||||||
} else if (dhMatch) {
|
|
||||||
processedToken = dhMatch[1];
|
|
||||||
dropHigh = true;
|
|
||||||
dropCount = parseInt(dhMatch[2]);
|
|
||||||
} else if (dlMatch) {
|
|
||||||
processedToken = dlMatch[1];
|
|
||||||
dropLow = true;
|
|
||||||
dropCount = parseInt(dlMatch[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
const match = processedToken.match(/^(\d+)?d(\d+)$/i);
|
|
||||||
if (match) {
|
|
||||||
const count = parseInt(match[1] || "1");
|
|
||||||
const sides = parseInt(match[2]);
|
|
||||||
const rolls: number[] = [];
|
|
||||||
|
|
||||||
for (let j = 0; j < count; j++) {
|
|
||||||
rolls.push(Math.floor(Math.random() * sides) + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
let processedRolls = [...rolls];
|
|
||||||
let detail = `${count}d${sides}`;
|
|
||||||
|
|
||||||
// 处理 keep/drop 运算符
|
|
||||||
if (keepHigh || keepLow || dropHigh || dropLow) {
|
|
||||||
const sorted = [...processedRolls].sort((a, b) => a - b);
|
|
||||||
|
|
||||||
if (dropHigh && dropCount > 0) {
|
|
||||||
processedRolls = sorted.slice(0, sorted.length - dropCount);
|
|
||||||
detail += `d${dropCount}h`;
|
|
||||||
} else if (dropLow && dropCount > 0) {
|
|
||||||
processedRolls = sorted.slice(dropCount);
|
|
||||||
detail += `d${dropCount}l`;
|
|
||||||
} else if (keepHigh && keepCount > 0) {
|
|
||||||
processedRolls = sorted.slice(-keepCount);
|
|
||||||
detail += `kh${keepCount}`;
|
|
||||||
} else if (keepLow && keepCount > 0) {
|
|
||||||
processedRolls = sorted.slice(0, keepCount);
|
|
||||||
detail += `kl${keepCount}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const partTotal = processedRolls.reduce((a, b) => a + b, 0);
|
|
||||||
total += sign * partTotal;
|
|
||||||
allRolls.push(...processedRolls);
|
|
||||||
details.push(
|
|
||||||
`${detail}=[${processedRolls.join(",")}]${sign < 0 ? " (负)" : ""}`,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// 处理固定数字
|
|
||||||
const num = parseInt(token);
|
|
||||||
if (!isNaN(num)) {
|
|
||||||
total += sign * num;
|
|
||||||
details.push(`${num}${sign < 0 ? " (负)" : ""}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
total,
|
|
||||||
rolls: allRolls,
|
|
||||||
detail: details.join(" + "),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从 URL 参数获取骰子结果
|
// 从 URL 参数获取骰子结果
|
||||||
function getDiceResultFromUrl(key: string): number | null {
|
function getDiceResultFromUrl(key: string): number | null {
|
||||||
if (typeof window === "undefined") return null;
|
if (typeof window === "undefined") return null;
|
||||||
|
|
@ -174,7 +56,7 @@ customElement("md-dice", { key: "" }, (props, { element }) => {
|
||||||
|
|
||||||
const handleRoll = () => {
|
const handleRoll = () => {
|
||||||
// 点击骰子图标:总是重 roll
|
// 点击骰子图标:总是重 roll
|
||||||
const rollResult = rollDice(formula);
|
const rollResult = rollFormula(formula).result;
|
||||||
setResult(rollResult.total);
|
setResult(rollResult.total);
|
||||||
setRollDetail(rollResult.detail);
|
setRollDetail(rollResult.detail);
|
||||||
setIsRolled(true);
|
setIsRolled(true);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue