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 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | /**
* Struggle Detection Hook
*
* Monitors user search behavior and automatically advances to the next hint
* when the user appears to be struggling (based on time spent searching).
*/
import { useEffect, useRef } from 'react'
// Thresholds for triggering next hint
const STRUGGLE_TIME_THRESHOLD = 30000 // 30 seconds per hint level
const STRUGGLE_CHECK_INTERVAL = 5000 // Check every 5 seconds
export interface UseStruggleDetectionOptions {
/** Whether hot/cold feedback is enabled (implies we're tracking search metrics) */
effectiveHotColdEnabled: boolean
/** Whether there are more hints available to show */
hasMoreHints: boolean
/** Current region prompt ID */
currentPrompt: string | null
/** Function to get search metrics */
getSearchMetrics: (startTime: number) => { timeToFind: number }
/** Function to advance to next hint */
nextHint: () => void
/** Ref to prompt start time */
promptStartTime: React.RefObject<number>
}
/**
* Hook that detects when a user is struggling to find a region and
* automatically advances to the next hint level.
*
* Hint levels are based on time:
* - Level 0 = first 30 seconds
* - Level 1 = 30-60 seconds
* - Level 2 = 60-90 seconds
* - etc.
*/
export function useStruggleDetection({
effectiveHotColdEnabled,
hasMoreHints,
currentPrompt,
getSearchMetrics,
nextHint,
promptStartTime,
}: UseStruggleDetectionOptions): void {
// Track which hint level triggered last hint
const lastHintLevelRef = useRef(0)
// Check for struggle and advance hint
useEffect(() => {
// Only run if hot/cold is enabled (means we're tracking search metrics)
if (!effectiveHotColdEnabled || !hasMoreHints || !currentPrompt) return
const checkStruggle = () => {
const metrics = getSearchMetrics(promptStartTime.current ?? Date.now())
// Calculate which hint level we should be at based on time
// Level 0 = first 30 seconds, Level 1 = 30-60 seconds, etc.
const expectedHintLevel = Math.floor(metrics.timeToFind / STRUGGLE_TIME_THRESHOLD)
// If we should be at a higher hint level than last triggered, give next hint
if (expectedHintLevel > lastHintLevelRef.current && hasMoreHints) {
lastHintLevelRef.current = expectedHintLevel
nextHint()
}
}
const intervalId = setInterval(checkStruggle, STRUGGLE_CHECK_INTERVAL)
return () => clearInterval(intervalId)
}, [
effectiveHotColdEnabled,
hasMoreHints,
currentPrompt,
getSearchMetrics,
nextHint,
promptStartTime,
])
// Reset hint level tracking when prompt changes
useEffect(() => {
lastHintLevelRef.current = 0
}, [currentPrompt])
}
|