Add simulation functionality

This commit is contained in:
gpt-engineer-app[bot] 2025-09-05 05:03:21 +00:00
parent ad9dfb54b0
commit 189c4bde54

View file

@ -4,7 +4,8 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/com
import { Badge } from '@/components/ui/badge';
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog';
import { Checkbox } from '@/components/ui/checkbox';
import { Dice1, Dice2, Dice3, Dice4, Dice5, Dice6, RotateCcw, Settings } from 'lucide-react';
import { Slider } from '@/components/ui/slider';
import { Dice1, Dice2, Dice3, Dice4, Dice5, Dice6, RotateCcw, Settings, Play } from 'lucide-react';
import SocialShare from '@/components/SocialShare';
interface CrapsGameProps {
@ -36,6 +37,16 @@ const CrapsGame: React.FC<CrapsGameProps> = ({ showSocialShare = false }) => {
const [isCustomRules, setIsCustomRules] = useState(false);
const [isRulesModalOpen, setIsRulesModalOpen] = useState(false);
// Simulation state
const [simulationRounds, setSimulationRounds] = useState([10]);
const [isSimulating, setIsSimulating] = useState(false);
const [simulationResults, setSimulationResults] = useState<{
wins: number;
losses: number;
averageTurns: number;
totalGames: number;
} | null>(null);
const rollDice = () => {
setIsRolling(true);
setGameResult(null);
@ -66,11 +77,75 @@ const CrapsGame: React.FC<CrapsGameProps> = ({ showSocialShare = false }) => {
}, 1000);
};
const simulateGame = () => {
const winSums = isCustomRules ? customWinSums : [7, 11];
const loseSums = isCustomRules ? customLoseSums : [2, 3, 12];
let turns = 1;
let point: number | null = null;
while (true) {
const die1 = Math.floor(Math.random() * 6) + 1;
const die2 = Math.floor(Math.random() * 6) + 1;
const sum = die1 + die2;
if (point === null) {
// First roll (come out roll)
if (loseSums.includes(sum)) {
return { result: 'lose', turns };
} else if (winSums.includes(sum)) {
return { result: 'win', turns };
} else {
point = sum;
turns++;
}
} else {
// Subsequent rolls
if (sum === point) {
return { result: 'win', turns };
} else if (sum === 7) {
return { result: 'lose', turns };
} else {
turns++;
}
}
}
};
const runSimulation = async () => {
setIsSimulating(true);
const numGames = simulationRounds[0];
let wins = 0;
let losses = 0;
let totalTurns = 0;
// Add small delays to show progress
for (let i = 0; i < numGames; i++) {
const game = simulateGame();
if (game.result === 'win') wins++;
else losses++;
totalTurns += game.turns;
// Add a small delay every 10 games to show progress
if (i % 10 === 0) {
await new Promise(resolve => setTimeout(resolve, 50));
}
}
setSimulationResults({
wins,
losses,
averageTurns: totalTurns / numGames,
totalGames: numGames
});
setIsSimulating(false);
};
const resetGame = () => {
setDice1(null);
setDice2(null);
setGameResult(null);
setRollCount(0);
setSimulationResults(null);
};
const sum = dice1 && dice2 ? dice1 + dice2 : null;
@ -127,6 +202,57 @@ const CrapsGame: React.FC<CrapsGameProps> = ({ showSocialShare = false }) => {
</CardDescription>
</CardHeader>
<CardContent className="space-y-6">
{/* Simulation Controls */}
<Card className="bg-accent/5">
<CardHeader>
<CardTitle className="text-lg">Simulation</CardTitle>
<CardDescription>
Run multiple games to analyze win/loss statistics
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<label className="text-sm font-medium">Number of games: {simulationRounds[0]}</label>
<Slider
value={simulationRounds}
onValueChange={setSimulationRounds}
max={25}
min={1}
step={1}
className="w-full"
/>
</div>
<Button
onClick={runSimulation}
disabled={isSimulating}
className="w-full gap-2"
>
<Play className="w-4 h-4" />
{isSimulating ? 'Simulating...' : 'Simulate'}
</Button>
{simulationResults && (
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mt-4 p-4 bg-muted/50 rounded-lg">
<div className="text-center">
<div className="text-2xl font-bold text-green-600">{simulationResults.wins}</div>
<div className="text-sm text-muted-foreground">Wins</div>
<div className="text-xs">({((simulationResults.wins / simulationResults.totalGames) * 100).toFixed(1)}%)</div>
</div>
<div className="text-center">
<div className="text-2xl font-bold text-red-600">{simulationResults.losses}</div>
<div className="text-sm text-muted-foreground">Losses</div>
<div className="text-xs">({((simulationResults.losses / simulationResults.totalGames) * 100).toFixed(1)}%)</div>
</div>
<div className="text-center">
<div className="text-2xl font-bold text-blue-600">{simulationResults.averageTurns.toFixed(1)}</div>
<div className="text-sm text-muted-foreground">Avg Turns</div>
<div className="text-xs">per game</div>
</div>
</div>
)}
</CardContent>
</Card>
{/* Rules */}
<Card className="bg-muted/50">
<CardHeader className="flex flex-row items-center justify-between">