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:
commit
b398f4864b
1 changed files with 87 additions and 12 deletions
|
|
@ -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>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue