clean mines component
This commit is contained in:
parent
5533669745
commit
ad1739f7f4
1 changed files with 58 additions and 136 deletions
|
|
@ -9,41 +9,19 @@
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle
|
CardTitle
|
||||||
} from '$lib/components/ui/card';
|
} from '$lib/components/ui/card';
|
||||||
import {
|
|
||||||
Select,
|
|
||||||
SelectContent,
|
|
||||||
SelectItem,
|
|
||||||
SelectTrigger
|
|
||||||
} from '$lib/components/ui/select';
|
|
||||||
import {
|
|
||||||
Dialog,
|
|
||||||
DialogContent,
|
|
||||||
DialogHeader,
|
|
||||||
DialogTitle,
|
|
||||||
DialogTrigger
|
|
||||||
} from '$lib/components/ui/dialog';
|
|
||||||
import confetti from 'canvas-confetti';
|
import confetti from 'canvas-confetti';
|
||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
import { formatValue, playSound, showConfetti, showSchoolPrideCannons } from '$lib/utils';
|
import { formatValue, playSound, showConfetti, showSchoolPrideCannons } from '$lib/utils';
|
||||||
import { volumeSettings } from '$lib/stores/volume-settings';
|
import { volumeSettings } from '$lib/stores/volume-settings';
|
||||||
import { onMount, onDestroy } from 'svelte';
|
import { onMount, onDestroy } from 'svelte';
|
||||||
import { ModeWatcher } from 'mode-watcher';
|
import { ModeWatcher } from 'mode-watcher';
|
||||||
import { Info } from 'lucide-svelte';
|
|
||||||
import { fetchPortfolioSummary } from '$lib/stores/portfolio-data';
|
import { fetchPortfolioSummary } from '$lib/stores/portfolio-data';
|
||||||
|
|
||||||
interface MinesResult {
|
|
||||||
won: boolean;
|
|
||||||
newBalance: number;
|
|
||||||
payout: number;
|
|
||||||
amountWagered: number;
|
|
||||||
sessionToken: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const GRID_SIZE = 5;
|
const GRID_SIZE = 5;
|
||||||
const TOTAL_TILES = GRID_SIZE * GRID_SIZE;
|
const TOTAL_TILES = GRID_SIZE * GRID_SIZE;
|
||||||
const MAX_BET_AMOUNT = 1000000;
|
const MAX_BET_AMOUNT = 1000000;
|
||||||
const MIN_MINES = 3;
|
const MIN_MINES = 3;
|
||||||
const AUTO_CASHOUT_TIME = 15; // 15 seconds total (10s game + 5s buffer)
|
const AUTO_CASHOUT_TIME = 15;
|
||||||
|
|
||||||
let {
|
let {
|
||||||
balance = $bindable(),
|
balance = $bindable(),
|
||||||
|
|
@ -60,7 +38,6 @@
|
||||||
let revealedTiles = $state<number[]>([]);
|
let revealedTiles = $state<number[]>([]);
|
||||||
let minePositions = $state<number[]>([]);
|
let minePositions = $state<number[]>([]);
|
||||||
let currentMultiplier = $state(1);
|
let currentMultiplier = $state(1);
|
||||||
let lastResult = $state<MinesResult | null>(null);
|
|
||||||
let autoCashoutTimer = $state(0);
|
let autoCashoutTimer = $state(0);
|
||||||
let autoCashoutProgress = $state(0);
|
let autoCashoutProgress = $state(0);
|
||||||
let sessionToken = $state<string | null>(null);
|
let sessionToken = $state<string | null>(null);
|
||||||
|
|
@ -87,27 +64,23 @@
|
||||||
for (let i = 0; i < picks; i++) {
|
for (let i = 0; i < picks; i++) {
|
||||||
probability *= (TOTAL_TILES - mines - i) / (TOTAL_TILES - i);
|
probability *= (TOTAL_TILES - mines - i) / (TOTAL_TILES - i);
|
||||||
}
|
}
|
||||||
|
return probability === 0 ? 1.0 : Math.max(1.0, 1 / probability);
|
||||||
if (probability === 0) return 1.0;
|
|
||||||
return Math.max(1.0, 1 / probability);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setBetAmount(amount: number) {
|
function setBetAmount(amount: number) {
|
||||||
const clampedAmount = Math.min(amount, Math.min(balance, MAX_BET_AMOUNT));
|
const clamped = Math.min(amount, Math.min(balance, MAX_BET_AMOUNT));
|
||||||
if (clampedAmount >= 0) {
|
if (clamped >= 0) {
|
||||||
betAmount = clampedAmount;
|
betAmount = clamped;
|
||||||
betAmountDisplay = clampedAmount.toLocaleString();
|
betAmountDisplay = clamped.toLocaleString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleBetAmountInput(event: Event) {
|
function handleBetAmountInput(event: Event) {
|
||||||
const target = event.target as HTMLInputElement;
|
const value = (event.target as HTMLInputElement).value.replace(/,/g, '');
|
||||||
const value = target.value.replace(/,/g, '');
|
const num = parseFloat(value) || 0;
|
||||||
const numValue = parseFloat(value) || 0;
|
const clamped = Math.min(num, Math.min(balance, MAX_BET_AMOUNT));
|
||||||
const clampedValue = Math.min(numValue, Math.min(balance, MAX_BET_AMOUNT));
|
betAmount = clamped;
|
||||||
|
betAmountDisplay = value;
|
||||||
betAmount = clampedValue;
|
|
||||||
betAmountDisplay = target.value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleBetAmountBlur() {
|
function handleBetAmountBlur() {
|
||||||
|
|
@ -115,16 +88,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetAutoCashoutTimer() {
|
function resetAutoCashoutTimer() {
|
||||||
if (autoCashoutInterval) {
|
if (autoCashoutInterval) clearInterval(autoCashoutInterval);
|
||||||
clearInterval(autoCashoutInterval);
|
|
||||||
}
|
|
||||||
autoCashoutTimer = 0;
|
autoCashoutTimer = 0;
|
||||||
autoCashoutProgress = 0;
|
autoCashoutProgress = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function startAutoCashoutTimer() {
|
function startAutoCashoutTimer() {
|
||||||
if (!hasRevealedTile) return;
|
if (!hasRevealedTile) return;
|
||||||
|
|
||||||
resetAutoCashoutTimer();
|
resetAutoCashoutTimer();
|
||||||
autoCashoutInterval = setInterval(() => {
|
autoCashoutInterval = setInterval(() => {
|
||||||
if (autoCashoutTimer < AUTO_CASHOUT_TIME) {
|
if (autoCashoutTimer < AUTO_CASHOUT_TIME) {
|
||||||
|
|
@ -141,46 +111,33 @@
|
||||||
|
|
||||||
async function handleTileClick(index: number) {
|
async function handleTileClick(index: number) {
|
||||||
if (!isPlaying || revealedTiles.includes(index) || !sessionToken) return;
|
if (!isPlaying || revealedTiles.includes(index) || !sessionToken) return;
|
||||||
|
|
||||||
lastClickedTile = index;
|
lastClickedTile = index;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/api/gambling/mines/reveal', {
|
const response = await fetch('/api/gambling/mines/reveal', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: { 'Content-Type': 'application/json' },
|
||||||
'Content-Type': 'application/json'
|
body: JSON.stringify({ sessionToken, tileIndex: index })
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
sessionToken,
|
|
||||||
tileIndex: index
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorData = await response.json();
|
const errorData = await response.json();
|
||||||
throw new Error(errorData.error || 'Failed to reveal tile');
|
throw new Error(errorData.error || 'Failed to reveal tile');
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
|
|
||||||
if (result.hitMine) {
|
if (result.hitMine) {
|
||||||
playSound('lose');
|
playSound('lose');
|
||||||
revealedTiles = [...revealedTiles, index];
|
revealedTiles = [...revealedTiles, index];
|
||||||
minePositions = result.minePositions;
|
minePositions = result.minePositions;
|
||||||
isPlaying = false;
|
isPlaying = false;
|
||||||
resetAutoCashoutTimer();
|
resetAutoCashoutTimer();
|
||||||
|
|
||||||
balance = result.newBalance;
|
balance = result.newBalance;
|
||||||
onBalanceUpdate?.(result.newBalance);
|
onBalanceUpdate?.(result.newBalance);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
playSound('flip');
|
playSound('flip');
|
||||||
revealedTiles = [...revealedTiles, index];
|
revealedTiles = [...revealedTiles, index];
|
||||||
clickedSafeTiles = [...clickedSafeTiles, index];
|
clickedSafeTiles = [...clickedSafeTiles, index];
|
||||||
currentMultiplier = result.currentMultiplier;
|
currentMultiplier = result.currentMultiplier;
|
||||||
hasRevealedTile = true;
|
hasRevealedTile = true;
|
||||||
startAutoCashoutTimer();
|
startAutoCashoutTimer();
|
||||||
|
|
||||||
if (result.status === 'won') {
|
if (result.status === 'won') {
|
||||||
showSchoolPrideCannons(confetti);
|
showSchoolPrideCannons(confetti);
|
||||||
showConfetti(confetti);
|
showConfetti(confetti);
|
||||||
|
|
@ -197,18 +154,12 @@
|
||||||
|
|
||||||
async function cashOut() {
|
async function cashOut() {
|
||||||
if (!isPlaying || !sessionToken) return;
|
if (!isPlaying || !sessionToken) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/api/gambling/mines/cashout', {
|
const response = await fetch('/api/gambling/mines/cashout', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: { 'Content-Type': 'application/json' },
|
||||||
'Content-Type': 'application/json'
|
body: JSON.stringify({ sessionToken })
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
sessionToken
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorData = await response.json();
|
const errorData = await response.json();
|
||||||
if (!isAutoCashout || errorData.error !== 'Invalid session') {
|
if (!isAutoCashout || errorData.error !== 'Invalid session') {
|
||||||
|
|
@ -216,15 +167,10 @@
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
balance = result.newBalance;
|
balance = result.newBalance;
|
||||||
onBalanceUpdate?.(balance);
|
onBalanceUpdate?.(balance);
|
||||||
|
if (result.payout > betAmount) showConfetti(confetti);
|
||||||
if (result.payout > betAmount) {
|
|
||||||
showConfetti(confetti);
|
|
||||||
}
|
|
||||||
|
|
||||||
playSound(result.isAbort ? 'flip' : 'win');
|
playSound(result.isAbort ? 'flip' : 'win');
|
||||||
isPlaying = false;
|
isPlaying = false;
|
||||||
hasRevealedTile = false;
|
hasRevealedTile = false;
|
||||||
|
|
@ -241,33 +187,23 @@
|
||||||
|
|
||||||
async function startGame() {
|
async function startGame() {
|
||||||
if (!canBet) return;
|
if (!canBet) return;
|
||||||
|
|
||||||
balance -= betAmount;
|
balance -= betAmount;
|
||||||
onBalanceUpdate?.(balance);
|
onBalanceUpdate?.(balance);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/api/gambling/mines/start', {
|
const response = await fetch('/api/gambling/mines/start', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: { 'Content-Type': 'application/json' },
|
||||||
'Content-Type': 'application/json'
|
body: JSON.stringify({ betAmount, mineCount })
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
betAmount,
|
|
||||||
mineCount
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorData = await response.json();
|
const errorData = await response.json();
|
||||||
balance += betAmount;
|
balance += betAmount;
|
||||||
onBalanceUpdate?.(balance);
|
onBalanceUpdate?.(balance);
|
||||||
throw new Error(errorData.error || 'Failed to start game');
|
throw new Error(errorData.error || 'Failed to start game');
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
isPlaying = true;
|
isPlaying = true;
|
||||||
hasRevealedTile = false;
|
hasRevealedTile = false;
|
||||||
lastResult = null;
|
|
||||||
revealedTiles = [];
|
revealedTiles = [];
|
||||||
clickedSafeTiles = [];
|
clickedSafeTiles = [];
|
||||||
currentMultiplier = 1;
|
currentMultiplier = 1;
|
||||||
|
|
@ -281,10 +217,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dynmaically fetch the correct balance.
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
volumeSettings.load();
|
volumeSettings.load();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = await fetchPortfolioSummary();
|
const data = await fetchPortfolioSummary();
|
||||||
if (data) {
|
if (data) {
|
||||||
|
|
@ -296,9 +230,7 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(resetAutoCashoutTimer);
|
||||||
resetAutoCashoutTimer();
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Card>
|
<Card>
|
||||||
|
|
@ -306,7 +238,6 @@
|
||||||
<CardTitle>Mines</CardTitle>
|
<CardTitle>Mines</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
Navigate through the minefield and cash out before hitting a mine!
|
Navigate through the minefield and cash out before hitting a mine!
|
||||||
<!-- Info popup and button removed -->
|
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
|
|
@ -325,20 +256,21 @@
|
||||||
<ModeWatcher />
|
<ModeWatcher />
|
||||||
<button
|
<button
|
||||||
class="mine-tile"
|
class="mine-tile"
|
||||||
class:revealed={revealedTiles.includes(index)}
|
|
||||||
class:mine={revealedTiles.includes(index) && minePositions.includes(index) && !clickedSafeTiles.includes(index)}
|
|
||||||
class:safe={revealedTiles.includes(index) && !minePositions.includes(index) && clickedSafeTiles.includes(index)}
|
|
||||||
class:light={document.documentElement.classList.contains('light')}
|
|
||||||
onclick={() => handleTileClick(index)}
|
onclick={() => handleTileClick(index)}
|
||||||
disabled={!isPlaying}
|
disabled={!isPlaying}
|
||||||
|
class:revealed={revealedTiles.includes(index)}
|
||||||
|
class:mine={revealedTiles.includes(index) &&
|
||||||
|
minePositions.includes(index) &&
|
||||||
|
!clickedSafeTiles.includes(index)}
|
||||||
|
class:safe={revealedTiles.includes(index) &&
|
||||||
|
!minePositions.includes(index) &&
|
||||||
|
clickedSafeTiles.includes(index)}
|
||||||
|
class:light={document.documentElement.classList.contains('light')}
|
||||||
|
aria-label="Tile"
|
||||||
>
|
>
|
||||||
{#if revealedTiles.includes(index)}
|
{#if revealedTiles.includes(index)}
|
||||||
{#if minePositions.includes(index)}
|
{#if minePositions.includes(index)}
|
||||||
<img
|
<img src="/facedev/avif/bussin.avif" alt="Mine" class="h-8 w-8 object-contain" />
|
||||||
src="/facedev/avif/bussin.avif"
|
|
||||||
alt="Mine"
|
|
||||||
class="h-8 w-8 object-contain"
|
|
||||||
/>
|
|
||||||
{:else}
|
{:else}
|
||||||
<img
|
<img
|
||||||
src="/facedev/avif/twoblade.avif"
|
src="/facedev/avif/twoblade.avif"
|
||||||
|
|
@ -351,27 +283,25 @@
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Right Side: Controls -->
|
||||||
<!-- Right Side: Controls Things -->
|
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<!-- Mine Count Selector -->
|
|
||||||
<div>
|
<div>
|
||||||
<label for="mine-count" class="block text-sm font-medium mb-2">Number of Mines</label>
|
<label for="mine-count" class="mb-2 block text-sm font-medium">Number of Mines</label>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
size="sm"
|
size="sm"
|
||||||
onclick={() => mineCount = Math.max(mineCount - 1, MIN_MINES)}
|
onclick={() => (mineCount = Math.max(mineCount - 1, MIN_MINES))}
|
||||||
disabled={isPlaying || mineCount <= MIN_MINES}
|
disabled={isPlaying || mineCount <= MIN_MINES}
|
||||||
aria-label="Decrease mines"
|
aria-label="Decrease mines">-</Button
|
||||||
>-</Button>
|
>
|
||||||
<Input
|
<Input
|
||||||
id="mine-count"
|
id="mine-count"
|
||||||
type="number"
|
type="number"
|
||||||
min={MIN_MINES}
|
min={MIN_MINES}
|
||||||
max={24}
|
max={24}
|
||||||
value={mineCount}
|
value={mineCount}
|
||||||
oninput={e => {
|
oninput={(e) => {
|
||||||
const target = e.target as HTMLInputElement | null;
|
const target = e.target as HTMLInputElement | null;
|
||||||
const val = Math.max(
|
const val = Math.max(
|
||||||
MIN_MINES,
|
MIN_MINES,
|
||||||
|
|
@ -385,30 +315,24 @@
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
size="sm"
|
size="sm"
|
||||||
onclick={() => mineCount = Math.min(mineCount + 1, 24)}
|
onclick={() => (mineCount = Math.min(mineCount + 1, 24))}
|
||||||
disabled={isPlaying || mineCount >= 24}
|
disabled={isPlaying || mineCount >= 24}
|
||||||
aria-label="Increase mines"
|
aria-label="Increase mines">+</Button
|
||||||
>+</Button>
|
>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-muted-foreground mt-1 text-xs">
|
<p class="text-muted-foreground mt-1 text-xs">
|
||||||
You will get
|
You will get
|
||||||
<span class="font-semibold text-success">
|
<span class="text-success font-semibold">
|
||||||
{(calculateRawMultiplier(
|
{calculateRawMultiplier(isPlaying ? revealedTiles.length + 1 : 1, mineCount).toFixed(
|
||||||
isPlaying ? revealedTiles.length + 1 : 1,
|
2
|
||||||
mineCount
|
)}x
|
||||||
)).toFixed(2)}x
|
|
||||||
</span>
|
</span>
|
||||||
per tile, probability of winning:
|
per tile, probability of winning:
|
||||||
<span class="font-semibold text-success">
|
<span class="text-success font-semibold">
|
||||||
{calculateProbability(
|
{calculateProbability(isPlaying ? 1 : 1, mineCount)}%
|
||||||
isPlaying ? 1 : 1,
|
|
||||||
mineCount
|
|
||||||
)}%
|
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Bet Amount -->
|
|
||||||
<div>
|
<div>
|
||||||
<label for="bet-amount" class="mb-2 block text-sm font-medium">Bet Amount</label>
|
<label for="bet-amount" class="mb-2 block text-sm font-medium">Bet Amount</label>
|
||||||
<Input
|
<Input
|
||||||
|
|
@ -424,8 +348,6 @@
|
||||||
Max bet: {MAX_BET_AMOUNT.toLocaleString()}
|
Max bet: {MAX_BET_AMOUNT.toLocaleString()}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Percentage Quick Actions -->
|
|
||||||
<div>
|
<div>
|
||||||
<div class="grid grid-cols-4 gap-2">
|
<div class="grid grid-cols-4 gap-2">
|
||||||
<Button
|
<Button
|
||||||
|
|
@ -450,32 +372,30 @@
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
onclick={() => setBetAmount(Math.floor(Math.min(balance, MAX_BET_AMOUNT)))}
|
onclick={() => setBetAmount(Math.floor(Math.min(balance, MAX_BET_AMOUNT)))}
|
||||||
disabled={isPlaying}>Max</Button>
|
disabled={isPlaying}>Max</Button
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Action Buttons -->
|
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
{#if !isPlaying}
|
{#if !isPlaying}
|
||||||
<Button class="h-12 flex-1 text-lg" onclick={startGame} disabled={!canBet}>
|
<Button class="h-12 flex-1 text-lg" onclick={startGame} disabled={!canBet}>
|
||||||
Start Game
|
Start Game
|
||||||
</Button>
|
</Button>
|
||||||
{:else}
|
{:else}
|
||||||
<!-- Auto Cashout Timer -->
|
|
||||||
{#if hasRevealedTile}
|
{#if hasRevealedTile}
|
||||||
<div class="space-y-1">
|
<div class="space-y-1">
|
||||||
<div class="h-px w-full bg-border"></div>
|
<div class="bg-border h-px w-full"></div>
|
||||||
<div class="text-center text-xs text-muted-foreground">
|
<div class="text-muted-foreground text-center text-xs">
|
||||||
Auto Cashout in {Math.ceil(AUTO_CASHOUT_TIME - autoCashoutTimer)}s
|
Auto Cashout in {Math.ceil(AUTO_CASHOUT_TIME - autoCashoutTimer)}s
|
||||||
</div>
|
</div>
|
||||||
<div class="h-1 w-full bg-muted rounded-full overflow-hidden">
|
<div class="bg-muted h-1 w-full overflow-hidden rounded-full">
|
||||||
<div
|
<div
|
||||||
class="h-full bg-primary transition-all duration-100"
|
class="bg-primary h-full transition-all duration-100"
|
||||||
class:urgent={autoCashoutTimer >= 7}
|
class:urgent={autoCashoutTimer >= 7}
|
||||||
style="width: {autoCashoutProgress}%"
|
style="width: {autoCashoutProgress}%"
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="h-px w-full bg-border"></div>
|
<div class="bg-border h-px w-full"></div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<Button class="h-12 flex-1 text-lg" onclick={cashOut} disabled={!isPlaying}>
|
<Button class="h-12 flex-1 text-lg" onclick={cashOut} disabled={!isPlaying}>
|
||||||
|
|
@ -493,7 +413,9 @@
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<span>Next Tile:</span>
|
<span>Next Tile:</span>
|
||||||
<span>
|
<span>
|
||||||
+{formatValue(betAmount * (calculateRawMultiplier(revealedTiles.length + 1, mineCount) - 1))}
|
+{formatValue(
|
||||||
|
betAmount * (calculateRawMultiplier(revealedTiles.length + 1, mineCount) - 1)
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
|
|
|
||||||
Reference in a new issue