From de81e2e1118247c83c7482bf2c7ba10779c56ef0 Mon Sep 17 00:00:00 2001 From: satoshi Date: Sun, 10 May 2026 17:23:41 +0300 Subject: [PATCH] Replace best share subtitle with luck indicator Shows luck as best_share / total_work * 100%. Green for >100% (lucky), red for <100% (unlucky), multiplier format for >=1000%. Hover tooltip explains the metric. --- ui/src/lib/PoolOverview.svelte | 53 +++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/ui/src/lib/PoolOverview.svelte b/ui/src/lib/PoolOverview.svelte index 82c9aa3..57d2a7c 100644 --- a/ui/src/lib/PoolOverview.svelte +++ b/ui/src/lib/PoolOverview.svelte @@ -56,6 +56,20 @@ const totalHashes = $derived(data.cumulative_shares * 2 ** 32); + // Luck: best_share / cumulative_work * 100%. + // 100% = exactly expected, >100% = lucky, <100% = unlucky. + const luckPct = $derived.by(() => { + const best = data.best_diff; + const work = data.cumulative_shares; + if (!best || !work || work <= 0) return 0; + return (best / work) * 100; + }); + const luckLabel = $derived.by(() => { + if (!data.best_diff || !data.cumulative_shares) return "—"; + if (luckPct >= 1000) return `${(luckPct / 100).toFixed(1)}x`; + return luckPct.toFixed(0) + "%"; + }); + // Block-height flash on network-wide new block. let prevHeight = $state(0); let heightFlash = $state(false); @@ -84,7 +98,15 @@
Best share
{formatDifficulty(data.best_diff)}
-
all-time pool record
+
100} + class:unlucky={luckPct > 0 && luckPct < 100} + title="Luck = best share / total work. 100% means your best share matches the work done. Above 100% is lucky (found a harder share than expected), below is unlucky." + > + {luckLabel} + luck +
@@ -194,6 +216,35 @@ color: var(--bad); } + .luck-sub { + display: flex; + align-items: baseline; + gap: 0.4em; + margin-top: 0.45em; + cursor: help; + } + .luck-value { + font-size: 1.15rem; + font-weight: 700; + font-variant-numeric: tabular-nums; + letter-spacing: -0.01em; + } + .luck-label { + color: var(--fg-dim); + font-size: 0.85rem; + font-weight: 400; + text-transform: uppercase; + letter-spacing: 0.04em; + } + .luck-sub.lucky .luck-value { + color: var(--good); + text-shadow: 0 0 10px rgba(92, 224, 168, 0.35); + } + .luck-sub.unlucky .luck-value { + color: var(--bad); + text-shadow: 0 0 10px rgba(255, 107, 107, 0.25); + } + .height-card { transition: box-shadow 0.3s, border-color 0.3s; }