From 8944a5e485c0aeb82584d700252631e19f0ee719 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Thu, 21 Aug 2025 11:20:19 +0000 Subject: [PATCH] Refine Bulgarian Solitaire columns Adjusted column width in Bulgarian Solitaire to be just wider than block width. Implemented sorting of columns by height (tallest to left) after simulation starts. Added visual feedback: highlighting top boxes red, animating their movement to form the last column, and then visually displaying the sorting process. --- src/components/BulgarianSolitaire.tsx | 46 +++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/src/components/BulgarianSolitaire.tsx b/src/components/BulgarianSolitaire.tsx index cff1632..5d3343a 100644 --- a/src/components/BulgarianSolitaire.tsx +++ b/src/components/BulgarianSolitaire.tsx @@ -21,6 +21,8 @@ const BulgarianSolitaire: React.FC = ({ showSocialShare const [draggedBox, setDraggedBox] = useState(null); const [step, setStep] = useState(0); const [isComplete, setIsComplete] = useState(false); + const [highlightedBoxes, setHighlightedBoxes] = useState>(new Set()); + const [isAnimating, setIsAnimating] = useState(false); const totalBoxes = (n * (n + 1)) / 2; @@ -115,6 +117,18 @@ const BulgarianSolitaire: React.FC = ({ showSocialShare stepCount++; setStep(stepCount); + // Highlight top boxes that will be moved + const topBoxes = new Set(); + currentColumns.forEach(col => { + if (col.length > 0) { + topBoxes.add(col[col.length - 1]); + } + }); + + setHighlightedBoxes(topBoxes); + setIsAnimating(true); + await sleep(800); // Show highlighting + // Create new pile from non-empty columns const newPile: number[] = []; const updatedColumns = currentColumns.map(col => { @@ -136,7 +150,21 @@ const BulgarianSolitaire: React.FC = ({ showSocialShare break; } - currentColumns = updatedColumns; + // Clear highlighting and animation + setHighlightedBoxes(new Set()); + setIsAnimating(false); + + // Sort columns by height (tallest to left) + const columnData = updatedColumns.map((col, index) => ({ col, originalIndex: index })) + .filter(item => item.col.length > 0) + .sort((a, b) => b.col.length - a.col.length); + + const sortedColumns = Array.from({ length: updatedColumns.length }, () => []); + columnData.forEach((item, index) => { + sortedColumns[index] = item.col; + }); + + currentColumns = sortedColumns; setColumns(currentColumns); // Update box positions @@ -149,7 +177,7 @@ const BulgarianSolitaire: React.FC = ({ showSocialShare return box; })); - await sleep(1000); // Wait 1 second between steps + await sleep(1200); // Wait to see the sorted result } setIsComplete(isTriangularConfiguration(currentColumns)); @@ -172,6 +200,8 @@ const BulgarianSolitaire: React.FC = ({ showSocialShare setStep(0); setIsComplete(false); setIsPlaying(false); + setHighlightedBoxes(new Set()); + setIsAnimating(false); }; const containerBoxes = boxes.filter(box => box.columnIndex === null); @@ -233,22 +263,26 @@ const BulgarianSolitaire: React.FC = ({ showSocialShare )} -
+
{columns.map((column, index) => (
handleDrop(e, index)} - className="border border-muted-foreground rounded-lg min-h-[100px] p-2 bg-background/50 flex flex-col-reverse gap-1" + className="border border-muted-foreground rounded-lg min-h-[100px] w-12 p-1 bg-background/50 flex flex-col-reverse gap-1 transition-all duration-500" > -
+
{index + 1}
{column.map((boxId, boxIndex) => (
handleDoubleClick(boxId)} - className="w-6 h-6 bg-primary rounded cursor-pointer hover:bg-primary/80 transition-colors flex items-center justify-center text-primary-foreground text-xs font-medium mx-auto" + className={`w-8 h-8 rounded cursor-pointer transition-all duration-300 flex items-center justify-center text-xs font-medium mx-auto ${ + highlightedBoxes.has(boxId) + ? 'bg-red-500 text-white shadow-lg scale-110' + : 'bg-primary text-primary-foreground hover:bg-primary/80' + } ${isAnimating && highlightedBoxes.has(boxId) ? 'animate-pulse' : ''}`} title="Double-click to return to container" > {boxId + 1}