Fix presents puzzle buttons

Improve button functionality for Presents Puzzle by debugging and updating pause/step logic, ensuring proper initialization and synchronous pause handling, and aligning behavior with other interactives.

X-Lovable-Edit-ID: edt-39d880a1-7b02-467d-a083-abd2257f5e13
This commit is contained in:
gpt-engineer-app[bot] 2025-11-19 03:38:28 +00:00
commit 2bfc8603ca

View file

@ -1,4 +1,4 @@
import { useState } from 'react';
import { useState, useRef } from 'react';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
@ -23,7 +23,6 @@ const PresentsPuzzle = ({
const [aliceFound, setAliceFound] = useState(0);
const [bobFound, setBobFound] = useState(0);
const [isRunning, setIsRunning] = useState(false);
const [isPaused, setIsPaused] = useState(false);
const [currentStep, setCurrentStep] = useState(0);
const [aliceOrder, setAliceOrder] = useState<number[]>([]);
const [bobOrder, setBobOrder] = useState<number[]>([]);
@ -34,6 +33,7 @@ const PresentsPuzzle = ({
ties: 0
});
const [hasSimulated, setHasSimulated] = useState(false);
const isPausedRef = useRef(false);
// Generate random present positions
const generatePresents = (): Set<number> => {
@ -84,8 +84,24 @@ const PresentsPuzzle = ({
return 'tie'; // Default, though this should never happen
};
// Initialize simulation if not already initialized
const initializeSimulation = () => {
if (aliceOrder.length === 0) {
const presents = generatePresents();
setPresentBoxes(presents);
const newAliceOrder = getAliceOrder();
const newBobOrder = getBobOrder();
setAliceOrder(newAliceOrder);
setBobOrder(newBobOrder);
return { presents, aliceOrder: newAliceOrder, bobOrder: newBobOrder };
}
return { presents: presentBoxes, aliceOrder, bobOrder };
};
// Update display for a specific step
const updateStep = (step: number) => {
const { presents, aliceOrder: aOrder, bobOrder: bOrder } = initializeSimulation();
const aliceOpenedSet = new Set<number>();
const bobOpenedSet = new Set<number>();
let aliceCount = 0;
@ -93,13 +109,13 @@ const PresentsPuzzle = ({
let currentWinner: 'alice' | 'bob' | 'tie' | null = null;
for (let i = 0; i <= step; i++) {
const aliceBox = aliceOrder[i];
const bobBox = bobOrder[i];
const aliceBox = aOrder[i];
const bobBox = bOrder[i];
aliceOpenedSet.add(aliceBox);
bobOpenedSet.add(bobBox);
if (presentBoxes.has(aliceBox)) aliceCount++;
if (presentBoxes.has(bobBox)) bobCount++;
if (presents.has(aliceBox)) aliceCount++;
if (presents.has(bobBox)) bobCount++;
if (aliceCount === 26 && bobCount === 26) {
currentWinner = 'tie';
@ -120,10 +136,10 @@ const PresentsPuzzle = ({
// Animate a single simulation
const startSimulation = async () => {
if (currentStep === 0) {
if (currentStep === 0 || aliceOrder.length === 0) {
// Start new simulation
setIsRunning(true);
setIsPaused(false);
isPausedRef.current = false;
setWinner(null);
setAliceOpened(new Set());
setBobOpened(new Set());
@ -143,13 +159,14 @@ const PresentsPuzzle = ({
let currentWinner: 'alice' | 'bob' | 'tie' | null = null;
for (let i = 0; i < 100 && !currentWinner; i++) {
await new Promise(resolve => setTimeout(resolve, 50));
// Check if paused
while (isPaused) {
await new Promise(resolve => setTimeout(resolve, 100));
if (isPausedRef.current) {
setCurrentStep(i);
setIsRunning(false);
return;
}
await new Promise(resolve => setTimeout(resolve, 50));
const aliceBox = newAliceOrder[i];
const bobBox = newBobOrder[i];
setAliceOpened(prev => new Set(prev).add(aliceBox));
@ -180,19 +197,21 @@ const PresentsPuzzle = ({
} else {
// Resume from current step
setIsRunning(true);
setIsPaused(false);
isPausedRef.current = false;
let aliceCount = aliceFound;
let bobCount = bobFound;
let currentWinner: 'alice' | 'bob' | 'tie' | null = winner;
for (let i = currentStep + 1; i < 100 && !currentWinner; i++) {
await new Promise(resolve => setTimeout(resolve, 50));
while (isPaused) {
await new Promise(resolve => setTimeout(resolve, 100));
if (isPausedRef.current) {
setCurrentStep(i);
setIsRunning(false);
return;
}
await new Promise(resolve => setTimeout(resolve, 50));
const aliceBox = aliceOrder[i];
const bobBox = bobOrder[i];
setAliceOpened(prev => new Set(prev).add(aliceBox));
@ -224,28 +243,27 @@ const PresentsPuzzle = ({
};
const pauseSimulation = () => {
setIsPaused(true);
isPausedRef.current = true;
setIsRunning(false);
};
const stepNext = () => {
if (aliceOrder.length === 0 || currentStep >= 99 || winner) return;
if (currentStep >= 99 || winner) return;
updateStep(currentStep + 1);
};
const stepBack = () => {
if (aliceOrder.length === 0 || currentStep <= 0) return;
if (currentStep <= 0) return;
setWinner(null);
updateStep(currentStep - 1);
};
const stepToEnd = () => {
if (aliceOrder.length === 0) return;
updateStep(99);
};
const stepToStart = () => {
if (aliceOrder.length === 0) return;
initializeSimulation();
setAliceOpened(new Set());
setBobOpened(new Set());
setAliceFound(0);
@ -263,7 +281,7 @@ const PresentsPuzzle = ({
setBobFound(0);
setWinner(null);
setIsRunning(false);
setIsPaused(false);
isPausedRef.current = false;
setCurrentStep(0);
setAliceOrder([]);
setBobOrder([]);
@ -387,7 +405,7 @@ const PresentsPuzzle = ({
</Button>
<Button
onClick={stepToStart}
disabled={isRunning || aliceOrder.length === 0 || currentStep === 0}
disabled={isRunning || currentStep === 0}
variant="outline"
className="gap-2"
title="Step to start"
@ -396,7 +414,7 @@ const PresentsPuzzle = ({
</Button>
<Button
onClick={stepBack}
disabled={isRunning || aliceOrder.length === 0 || currentStep === 0}
disabled={isRunning || currentStep === 0}
variant="outline"
className="gap-2"
title="Step back"
@ -405,7 +423,7 @@ const PresentsPuzzle = ({
</Button>
<Button
onClick={stepNext}
disabled={isRunning || aliceOrder.length === 0 || currentStep >= 99 || winner !== null}
disabled={isRunning || currentStep >= 99 || winner !== null}
variant="outline"
className="gap-2"
title="Step next"
@ -414,7 +432,7 @@ const PresentsPuzzle = ({
</Button>
<Button
onClick={stepToEnd}
disabled={isRunning || aliceOrder.length === 0 || currentStep >= 99}
disabled={isRunning || currentStep >= 99}
variant="outline"
className="gap-2"
title="Step to end"