Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | /** * Celebration Classification Utility * * Determines the type of celebration based on how the user found the region. * Uses search metrics from the hot/cold feedback system to classify: * - Lightning: Fast and direct find * - Standard: Normal discovery * - Hard-earned: Extensive searching, shows perseverance */ import type { SearchMetrics } from '../hooks/useHotColdFeedback' import type { CelebrationType } from '../Provider' // Thresholds for classification const LIGHTNING_TIME_MS = 3000 // Under 3 seconds const LIGHTNING_EFFICIENCY = 0.7 // Very direct path const HARD_EARNED_TIME_MS = 20000 // Over 20 seconds const HARD_EARNED_EFFICIENCY = 0.3 // Wandered a lot const HARD_EARNED_REVERSALS = 10 // Many direction changes const HARD_EARNED_NEAR_MISSES = 2 // Got close multiple times /** * Classify the celebration type based on search metrics. * * @param metrics - Search metrics from useHotColdFeedback * @returns The celebration type: 'lightning', 'standard', or 'hard-earned' */ export function classifyCelebration(metrics: SearchMetrics): CelebrationType { // Lightning: Fast and direct // Kid knew exactly where to look - reward the speed! if (metrics.timeToFind < LIGHTNING_TIME_MS && metrics.searchEfficiency > LIGHTNING_EFFICIENCY) { return 'lightning' } // Hard-earned: Any of these indicate real effort // Kid really worked for it - acknowledge the perseverance! if ( metrics.timeToFind > HARD_EARNED_TIME_MS || metrics.searchEfficiency < HARD_EARNED_EFFICIENCY || metrics.directionReversals > HARD_EARNED_REVERSALS || metrics.nearMissCount > HARD_EARNED_NEAR_MISSES ) { return 'hard-earned' } // Standard: Normal discovery return 'standard' } // Celebration timing configuration export const CELEBRATION_TIMING = { lightning: { flashDuration: 400, confettiDuration: 600, soundDuration: 200, totalDuration: 600, }, standard: { flashDuration: 600, confettiDuration: 1000, soundDuration: 400, totalDuration: 1000, }, 'hard-earned': { flashDuration: 800, confettiDuration: 1500, soundDuration: 600, totalDuration: 1500, }, } as const // Confetti configuration per celebration type export const CONFETTI_CONFIG = { lightning: { count: 12, spread: 60, colors: ['#fbbf24', '#fcd34d', '#fef3c7'], // Gold sparkles }, standard: { count: 20, spread: 90, colors: ['#fbbf24', '#22c55e', '#3b82f6', '#f472b6'], // Colorful mix }, 'hard-earned': { count: 35, spread: 120, colors: ['#fbbf24', '#22c55e', '#8b5cf6', '#ec4899', '#f97316'], // Big party! }, } as const |