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