Color code hooks for RR

Add color-coding for generated hooks and mirror colors on RR partition.
- Introduce hookColors and baseHue state for pastel color shading.
- Generate random base color per run and derive diagonal hook colors across both diagrams.
- Apply consistent colors to Ferrers diagram highlights and Rogers-Ramanujan partition boxes.
- Ensure muted pastel shades traverse along the diagonal hooks and reflect on both views.

X-Lovable-Edit-ID: edt-8409dc4c-1a65-459a-9898-f0e32c8966a0
This commit is contained in:
gpt-engineer-app[bot] 2025-12-01 07:09:13 +00:00
commit b398f4864b

View file

@ -13,6 +13,8 @@ const FerrersRogersRamanujan = () => {
const [animatingHook, setAnimatingHook] = useState<{ row: number; col: number } | null>(null); const [animatingHook, setAnimatingHook] = useState<{ row: number; col: number } | null>(null);
const [animationStep, setAnimationStep] = useState(0); const [animationStep, setAnimationStep] = useState(0);
const [isAnimating, setIsAnimating] = useState(false); const [isAnimating, setIsAnimating] = useState(false);
const [hookColors, setHookColors] = useState<string[]>([]);
const [baseHue, setBaseHue] = useState(0);
useEffect(() => { useEffect(() => {
// Initialize sliders with all zeros // Initialize sliders with all zeros
@ -45,6 +47,7 @@ const FerrersRogersRamanujan = () => {
setAnimatingHook(null); setAnimatingHook(null);
setAnimationStep(0); setAnimationStep(0);
setIsAnimating(false); setIsAnimating(false);
setHookColors([]);
}; };
const generateRRPartition = () => { const generateRRPartition = () => {
@ -53,11 +56,25 @@ const FerrersRogersRamanujan = () => {
return; return;
} }
// Pick a random base hue (0-360)
const newBaseHue = Math.floor(Math.random() * 360);
setBaseHue(newBaseHue);
setHookColors([]);
setRRPartition([]); setRRPartition([]);
setAnimationStep(0); setAnimationStep(0);
setIsAnimating(true); setIsAnimating(true);
}; };
// Generate muted pastel color for current hook
const generateHookColor = (index: number, total: number) => {
// Move through shades of the base hue
const hueVariation = (index / Math.max(total - 1, 1)) * 60 - 30; // ±30 degrees
const hue = (baseHue + hueVariation + 360) % 360;
const saturation = 45 + (index % 3) * 10; // 45-65% for muted pastels
const lightness = 75 + (index % 2) * 5; // 75-80% for pastels
return `hsl(${hue}, ${saturation}%, ${lightness}%)`;
};
// Animation effect - traverse main diagonal only // Animation effect - traverse main diagonal only
useEffect(() => { useEffect(() => {
if (!isAnimating || committedPartition.length === 0) return; if (!isAnimating || committedPartition.length === 0) return;
@ -90,7 +107,12 @@ const FerrersRogersRamanujan = () => {
} }
const hookSize = boxesRight + boxesBelow + 1; const hookSize = boxesRight + boxesBelow + 1;
// Update RR partition // Generate color for this hook (estimate total hooks as partition length)
const estimatedTotalHooks = Math.min(partition.length, partition[0] || 0);
const color = generateHookColor(animationStep, estimatedTotalHooks);
// Update colors and RR partition
setHookColors(prev => [...prev, color]);
setRRPartition(prev => [...prev, hookSize]); setRRPartition(prev => [...prev, hookSize]);
// Schedule next step // Schedule next step
@ -99,9 +121,9 @@ const FerrersRogersRamanujan = () => {
}, 500); }, 500);
return () => clearTimeout(timeout); return () => clearTimeout(timeout);
}, [isAnimating, animationStep, committedPartition]); }, [isAnimating, animationStep, committedPartition, baseHue]);
const renderFerrersDiagram = (partition: number[], highlightHook?: { row: number; col: number }) => { const renderFerrersDiagram = (partition: number[], highlightHook?: { row: number; col: number }, isOriginal = true) => {
if (partition.length === 0) return null; if (partition.length === 0) return null;
const boxSize = 30; const boxSize = 30;
@ -112,18 +134,71 @@ const FerrersRogersRamanujan = () => {
{partition.map((count, rowIdx) => ( {partition.map((count, rowIdx) => (
<div key={rowIdx} className="flex gap-[2px] mb-[2px]"> <div key={rowIdx} className="flex gap-[2px] mb-[2px]">
{Array.from({ length: count }).map((_, colIdx) => { {Array.from({ length: count }).map((_, colIdx) => {
const isHook = highlightHook && let backgroundColor = 'bg-secondary';
((rowIdx === highlightHook.row && colIdx >= highlightHook.col) || let borderColor = 'border-border';
(colIdx === highlightHook.col && rowIdx >= highlightHook.row)); let extraClasses = 'hover:bg-secondary/80';
if (isOriginal) {
// Original diagram: color completed hooks on diagonal
if (rowIdx === colIdx && rowIdx < hookColors.length) {
const color = hookColors[rowIdx];
backgroundColor = '';
borderColor = '';
extraClasses = `scale-105 shadow-md`;
return (
<div
key={colIdx}
className={`w-[30px] h-[30px] border-2 transition-all duration-300 ${extraClasses}`}
style={{
backgroundColor: color,
borderColor: color
}}
/>
);
}
// Highlight current hook being processed
const isHook = highlightHook &&
((rowIdx === highlightHook.row && colIdx >= highlightHook.col) ||
(colIdx === highlightHook.col && rowIdx >= highlightHook.row));
if (isHook) {
backgroundColor = 'bg-primary';
borderColor = 'border-primary';
extraClasses = 'scale-110 shadow-lg';
}
}
return ( return (
<div <div
key={colIdx} key={colIdx}
className={`w-[30px] h-[30px] border-2 transition-all duration-300 ${ className={`w-[30px] h-[30px] border-2 transition-all duration-300 ${backgroundColor} ${borderColor} ${extraClasses}`}
isHook />
? 'bg-primary border-primary scale-110 shadow-lg' );
: 'bg-secondary border-border hover:bg-secondary/80' })}
}`} </div>
))}
</div>
);
};
const renderRRDiagram = (partition: number[]) => {
if (partition.length === 0) return null;
return (
<div className="inline-block p-4 bg-card rounded-lg border">
{partition.map((count, rowIdx) => (
<div key={rowIdx} className="flex gap-[2px] mb-[2px]">
{Array.from({ length: count }).map((_, colIdx) => {
const color = hookColors[rowIdx] || 'hsl(var(--secondary))';
return (
<div
key={colIdx}
className="w-[30px] h-[30px] border-2 transition-all duration-300 scale-105 shadow-md"
style={{
backgroundColor: color,
borderColor: color
}}
/> />
); );
})} })}
@ -230,7 +305,7 @@ const FerrersRogersRamanujan = () => {
<p className="text-sm text-muted-foreground mb-4"> <p className="text-sm text-muted-foreground mb-4">
{rrPartition.join(" + ")} = {n} (parts differ by 2) {rrPartition.join(" + ")} = {n} (parts differ by 2)
</p> </p>
{renderFerrersDiagram(rrPartition)} {renderRRDiagram(rrPartition)}
</div> </div>
)} )}
</div> </div>