From 9dff3e7b7b1ca46ea7f19a48135124b80c5182c0 Mon Sep 17 00:00:00 2001 From: Thomas Hallock Date: Mon, 20 Oct 2025 10:57:12 -0500 Subject: [PATCH] feat(levels): progressive animation speed for Dan levels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Increase abacus animation speed as Dan levels advance, creating a visual representation of increasing mastery and speed. Animation interval changes from 500ms at Kyu/Pre-1st Dan to 50ms at 10th Dan. Changes: - Kyu levels (10th-1st): constant 500ms animation interval - Dan levels: linear interpolation from 500ms to 50ms - Pre-1st Dan (index 10): 500ms - 10th Dan (index 20): 50ms - Effect now depends on currentIndex to update interval dynamically - Add getAnimationInterval() helper for calculating speed This creates a dramatic visual effect where the abacus becomes a blur of movement at the highest mastery levels. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- apps/web/src/app/levels/page.tsx | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/apps/web/src/app/levels/page.tsx b/apps/web/src/app/levels/page.tsx index 2b22db40..a5f8c570 100644 --- a/apps/web/src/app/levels/page.tsx +++ b/apps/web/src/app/levels/page.tsx @@ -198,8 +198,25 @@ export default function LevelsPage() { setAnimatedDigits(generateRandomDigits(currentLevel.digits)) }, [currentLevel.digits]) - // Animate abacus calculations every 0.5 seconds + // Animate abacus calculations - speed increases with Dan level useEffect(() => { + // Calculate animation speed based on level + // Kyu levels: 500ms + // Dan levels: interpolate from 500ms (Pre-1st Dan) to 50ms (10th Dan) + const getAnimationInterval = () => { + if (currentIndex < 10) { + // Kyu levels: constant 500ms + return 500 + } + // Dan levels: speed up from 500ms to 50ms + // Index 10 (Pre-1st Dan) → 500ms + // Index 20 (10th Dan) → 50ms + const danProgress = (currentIndex - 10) / 10 // 0.0 to 1.0 + return 500 - danProgress * 450 // 500ms down to 50ms + } + + const intervalMs = getAnimationInterval() + const interval = setInterval(() => { setAnimatedDigits((prev) => { const digits = prev.split('').map(Number) @@ -216,10 +233,10 @@ export default function LevelsPage() { return digits.join('') }) - }, 500) + }, intervalMs) return () => clearInterval(interval) - }, []) + }, [currentIndex]) // Auto-advance slider position every 3 seconds (unless pane is hovered) useEffect(() => {