refactor: format
This commit is contained in:
parent
cc22b89226
commit
0a2c756213
|
|
@ -1,5 +1,5 @@
|
||||||
import { customElement, noShadowDOM } from 'solid-element';
|
import { customElement, noShadowDOM } from "solid-element";
|
||||||
import { createSignal, onMount } from 'solid-js';
|
import { createSignal, onMount } from "solid-js";
|
||||||
|
|
||||||
interface RollResult {
|
interface RollResult {
|
||||||
total: number;
|
total: number;
|
||||||
|
|
@ -7,11 +7,6 @@ interface RollResult {
|
||||||
detail: string;
|
detail: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DiceOperator {
|
|
||||||
pattern: RegExp;
|
|
||||||
handler: (match: RegExpMatchArray, rolls: number[]) => { value: number; rolls: number[]; detail: string };
|
|
||||||
}
|
|
||||||
|
|
||||||
function rollDice(formula: string): RollResult {
|
function rollDice(formula: string): RollResult {
|
||||||
const allRolls: number[] = [];
|
const allRolls: number[] = [];
|
||||||
let total = 0;
|
let total = 0;
|
||||||
|
|
@ -19,18 +14,21 @@ function rollDice(formula: string): RollResult {
|
||||||
|
|
||||||
// 解析骰子公式,支持 + 和 - 运算符
|
// 解析骰子公式,支持 + 和 - 运算符
|
||||||
// 先按 + 和 - 分割,但保留运算符
|
// 先按 + 和 - 分割,但保留运算符
|
||||||
const tokens = formula.split(/([+-])/).map(t => t.trim()).filter(t => t.length > 0);
|
const tokens = formula
|
||||||
|
.split(/([+-])/)
|
||||||
|
.map((t) => t.trim())
|
||||||
|
.filter((t) => t.length > 0);
|
||||||
|
|
||||||
let sign = 1;
|
let sign = 1;
|
||||||
|
|
||||||
for (let i = 0; i < tokens.length; i++) {
|
for (let i = 0; i < tokens.length; i++) {
|
||||||
const token = tokens[i];
|
const token = tokens[i];
|
||||||
|
|
||||||
if (token === '+') {
|
if (token === "+") {
|
||||||
sign = 1;
|
sign = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (token === '-') {
|
if (token === "-") {
|
||||||
sign = -1;
|
sign = -1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -69,7 +67,7 @@ function rollDice(formula: string): RollResult {
|
||||||
|
|
||||||
const match = processedToken.match(/^(\d+)?d(\d+)$/i);
|
const match = processedToken.match(/^(\d+)?d(\d+)$/i);
|
||||||
if (match) {
|
if (match) {
|
||||||
const count = parseInt(match[1] || '1');
|
const count = parseInt(match[1] || "1");
|
||||||
const sides = parseInt(match[2]);
|
const sides = parseInt(match[2]);
|
||||||
const rolls: number[] = [];
|
const rolls: number[] = [];
|
||||||
|
|
||||||
|
|
@ -102,13 +100,15 @@ function rollDice(formula: string): RollResult {
|
||||||
const partTotal = processedRolls.reduce((a, b) => a + b, 0);
|
const partTotal = processedRolls.reduce((a, b) => a + b, 0);
|
||||||
total += sign * partTotal;
|
total += sign * partTotal;
|
||||||
allRolls.push(...processedRolls);
|
allRolls.push(...processedRolls);
|
||||||
details.push(`${detail}=[${processedRolls.join(',')}]${sign < 0 ? ' (负)' : ''}`);
|
details.push(
|
||||||
|
`${detail}=[${processedRolls.join(",")}]${sign < 0 ? " (负)" : ""}`,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// 处理固定数字
|
// 处理固定数字
|
||||||
const num = parseInt(token);
|
const num = parseInt(token);
|
||||||
if (!isNaN(num)) {
|
if (!isNaN(num)) {
|
||||||
total += sign * num;
|
total += sign * num;
|
||||||
details.push(`${num}${sign < 0 ? ' (负)' : ''}`);
|
details.push(`${num}${sign < 0 ? " (负)" : ""}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -116,36 +116,32 @@ function rollDice(formula: string): RollResult {
|
||||||
return {
|
return {
|
||||||
total,
|
total,
|
||||||
rolls: allRolls,
|
rolls: allRolls,
|
||||||
detail: details.join(' + ')
|
detail: details.join(" + "),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成唯一 ID
|
|
||||||
let diceCounter = 0;
|
|
||||||
function generateDiceId(): string {
|
|
||||||
return `dice-${Date.now()}-${diceCounter++}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从 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;
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
const value = params.get(`dice-${key}`);
|
const value = params.get(`dice-${key}`);
|
||||||
return value ? parseInt(value) : null;
|
return value ? parseInt(value) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
customElement('md-dice', { key: '' }, (props, { element }) => {
|
// TODO:使用history.pushState
|
||||||
|
function setDiceResultToUrl(key: string, value: number) {}
|
||||||
|
|
||||||
|
customElement("md-dice", { key: "" }, (props, { element }) => {
|
||||||
noShadowDOM();
|
noShadowDOM();
|
||||||
const [result, setResult] = createSignal<number | null>(null);
|
const [result, setResult] = createSignal<number | null>(null);
|
||||||
const [isRolled, setIsRolled] = createSignal(false);
|
const [isRolled, setIsRolled] = createSignal(false);
|
||||||
const [rollDetail, setRollDetail] = createSignal<string>('');
|
const [rollDetail, setRollDetail] = createSignal<string>("");
|
||||||
const [diceId] = createSignal(generateDiceId());
|
|
||||||
|
|
||||||
// 从 element 的 textContent 获取骰子公式
|
// 从 element 的 textContent 获取骰子公式
|
||||||
const formula = element?.textContent?.trim() || '';
|
const formula = element?.textContent?.trim() || "";
|
||||||
|
|
||||||
// 使用的 key(如果没有提供则使用生成的 ID)
|
// 使用的 key(如果没有提供则使用生成的 ID)
|
||||||
const effectiveKey = () => props.key || diceId();
|
const effectiveKey = () => props.key;
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
// 初始化时检查 URL 参数
|
// 初始化时检查 URL 参数
|
||||||
|
|
@ -164,13 +160,15 @@ customElement('md-dice', { key: '' }, (props, { element }) => {
|
||||||
setResult(rollResult.total);
|
setResult(rollResult.total);
|
||||||
setRollDetail(rollResult.detail);
|
setRollDetail(rollResult.detail);
|
||||||
setIsRolled(true);
|
setIsRolled(true);
|
||||||
|
// TODO:保存结果到url
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleTextClick = () => {
|
const handleTextClick = () => {
|
||||||
// 点击文本:总是重置为公式
|
// 点击文本:总是重置为公式
|
||||||
setResult(null);
|
setResult(null);
|
||||||
setIsRolled(false);
|
setIsRolled(false);
|
||||||
setRollDetail('');
|
setRollDetail("");
|
||||||
|
// TODO:从url中移除结果
|
||||||
};
|
};
|
||||||
|
|
||||||
const displayText = () => (isRolled() ? `${result()}` : formula);
|
const displayText = () => (isRolled() ? `${result()}` : formula);
|
||||||
|
|
@ -178,24 +176,26 @@ customElement('md-dice', { key: '' }, (props, { element }) => {
|
||||||
return (
|
return (
|
||||||
<span class="inline-flex items-center gap-1">
|
<span class="inline-flex items-center gap-1">
|
||||||
<a
|
<a
|
||||||
href={effectiveKey() && isRolled() ? `?dice-${effectiveKey()}=${result()}` : '#'}
|
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
handleRoll();
|
handleRoll();
|
||||||
}}
|
}}
|
||||||
class="text-blue-600 hover:text-blue-800 cursor-pointer"
|
class="text-blue-600 hover:text-blue-800 cursor-pointer"
|
||||||
title={rollDetail() || '掷骰子'}
|
title={rollDetail() || "掷骰子"}
|
||||||
>
|
>
|
||||||
🎲
|
🎲
|
||||||
</a>
|
</a>
|
||||||
<span
|
<span
|
||||||
onClick={handleTextClick}
|
onClick={handleTextClick}
|
||||||
class={isRolled() ? 'cursor-pointer text-gray-700 hover:text-gray-900' : 'text-gray-600'}
|
class={
|
||||||
title={isRolled() ? '点击重置为公式' : formula}
|
isRolled()
|
||||||
|
? "cursor-pointer text-gray-700 hover:text-gray-900"
|
||||||
|
: "text-gray-600"
|
||||||
|
}
|
||||||
|
title={isRolled() ? "点击重置为公式" : formula}
|
||||||
>
|
>
|
||||||
{displayText()}
|
{displayText()}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue