Refactor Binary Search Trick interactive

- Move share elements to the bottom.
- Center "How it works" button.
- Add one-by-one and all-at-once modes.
- Randomize card numbers on load.
This commit is contained in:
gpt-engineer-app[bot] 2025-07-19 14:55:51 +00:00
parent 27f179e517
commit 325b0dd139

View file

@ -1,8 +1,10 @@
import { useState } from 'react'; import { useState, useEffect } from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox'; import { Checkbox } from '@/components/ui/checkbox';
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog'; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog';
import { Switch } from '@/components/ui/switch';
import { Label } from '@/components/ui/label';
import { HelpCircle, RefreshCw } from 'lucide-react'; import { HelpCircle, RefreshCw } from 'lucide-react';
import SocialShare from '@/components/SocialShare'; import SocialShare from '@/components/SocialShare';
@ -14,35 +16,78 @@ const BinarySearchTrick = ({ showSocialShare = true }: BinarySearchTrickProps) =
const [selectedCards, setSelectedCards] = useState<number[]>([]); const [selectedCards, setSelectedCards] = useState<number[]>([]);
const [result, setResult] = useState<number | null>(null); const [result, setResult] = useState<number | null>(null);
const [showResult, setShowResult] = useState(false); const [showResult, setShowResult] = useState(false);
const [isOneByOne, setIsOneByOne] = useState(false);
const [visibleCards, setVisibleCards] = useState<number[]>([]);
const [cards, setCards] = useState<Array<{id: number; title: string; numbers: number[]}>>([]);
// Define the 5 binary cards // Function to shuffle array
const cards = [ const shuffleArray = <T,>(array: T[]): T[] => {
{ const shuffled = [...array];
id: 16, for (let i = shuffled.length - 1; i > 0; i--) {
title: "Card 16", const j = Math.floor(Math.random() * (i + 1));
numbers: [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31] [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
},
{
id: 8,
title: "Card 8",
numbers: [8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31]
},
{
id: 4,
title: "Card 4",
numbers: [4, 5, 6, 7, 12, 13, 14, 15, 20, 21, 22, 23, 28, 29, 30, 31]
},
{
id: 2,
title: "Card 2",
numbers: [2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31]
},
{
id: 1,
title: "Card 1",
numbers: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]
} }
]; return shuffled;
};
// Generate cards with randomized numbers but maintaining binary logic
const generateCards = () => {
const baseCards = [
{
id: 16,
title: "Card 16",
numbers: [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
},
{
id: 8,
title: "Card 8",
numbers: [8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31]
},
{
id: 4,
title: "Card 4",
numbers: [4, 5, 6, 7, 12, 13, 14, 15, 20, 21, 22, 23, 28, 29, 30, 31]
},
{
id: 2,
title: "Card 2",
numbers: [2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31]
},
{
id: 1,
title: "Card 1",
numbers: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]
}
];
// Randomize the order of numbers within each card
return baseCards.map(card => ({
...card,
numbers: shuffleArray(card.numbers)
}));
};
// Initialize cards on component mount
useEffect(() => {
setCards(generateCards());
setVisibleCards([16, 8, 4, 2, 1]); // All cards visible by default
}, []);
// Handle mode toggle
const handleModeToggle = (checked: boolean) => {
setIsOneByOne(checked);
if (checked) {
// Start one-by-one mode - show first card
setVisibleCards([16]);
setTimeout(() => setVisibleCards(prev => [...prev, 8]), 500);
setTimeout(() => setVisibleCards(prev => [...prev, 4]), 1000);
setTimeout(() => setVisibleCards(prev => [...prev, 2]), 1500);
setTimeout(() => setVisibleCards(prev => [...prev, 1]), 2000);
} else {
// Show all cards immediately
setVisibleCards([16, 8, 4, 2, 1]);
}
};
const handleCardToggle = (cardId: number) => { const handleCardToggle = (cardId: number) => {
setSelectedCards(prev => setSelectedCards(prev =>
@ -72,7 +117,7 @@ const BinarySearchTrick = ({ showSocialShare = true }: BinarySearchTrickProps) =
<CardTitle className="text-3xl font-bold bg-gradient-to-r from-primary to-primary/70 bg-clip-text text-transparent"> <CardTitle className="text-3xl font-bold bg-gradient-to-r from-primary to-primary/70 bg-clip-text text-transparent">
Binary Search Magic Trick Binary Search Magic Trick
</CardTitle> </CardTitle>
<div className="flex items-center justify-center gap-4"> <div className="flex justify-center mt-4">
<Dialog> <Dialog>
<DialogTrigger asChild> <DialogTrigger asChild>
<Button variant="outline" size="sm"> <Button variant="outline" size="sm">
@ -122,13 +167,6 @@ const BinarySearchTrick = ({ showSocialShare = true }: BinarySearchTrickProps) =
</DialogHeader> </DialogHeader>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
{showSocialShare && (
<SocialShare
title="Binary Search Magic Trick"
description="Learn how binary numbers work through this amazing magic trick! Can you figure out how it works?"
/>
)}
</div> </div>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
@ -136,15 +174,31 @@ const BinarySearchTrick = ({ showSocialShare = true }: BinarySearchTrickProps) =
<p className="text-lg text-muted-foreground"> <p className="text-lg text-muted-foreground">
Think of a number between 1 and 31, then select all the cards that contain your number: Think of a number between 1 and 31, then select all the cards that contain your number:
</p> </p>
<div className="flex items-center justify-center gap-3 pt-4">
<Label htmlFor="mode-toggle" className="text-sm font-medium">
All at once
</Label>
<Switch
id="mode-toggle"
checked={isOneByOne}
onCheckedChange={handleModeToggle}
/>
<Label htmlFor="mode-toggle" className="text-sm font-medium">
One by one
</Label>
</div>
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 gap-4">
{cards.map((card) => ( {cards
.filter(card => visibleCards.includes(card.id))
.map((card) => (
<Card <Card
key={card.id} key={card.id}
className={`cursor-pointer transition-all duration-200 hover:shadow-lg ${ className={`cursor-pointer transition-all duration-500 hover:shadow-lg animate-fade-in ${
selectedCards.includes(card.id) selectedCards.includes(card.id)
? 'ring-2 ring-primary bg-primary/5' ? 'ring-2 ring-primary bg-primary/5'
: 'hover:bg-muted/50' : 'hover:bg-muted/50'
@ -210,6 +264,15 @@ const BinarySearchTrick = ({ showSocialShare = true }: BinarySearchTrickProps) =
</CardContent> </CardContent>
</Card> </Card>
)} )}
{showSocialShare && (
<div className="flex justify-center pt-6">
<SocialShare
title="Binary Search Magic Trick"
description="Learn how binary numbers work through this amazing magic trick! Can you figure out how it works?"
/>
</div>
)}
</div> </div>
</div> </div>
); );