File size: 2,884 Bytes
ebab432
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
92
93
94
95
96
97
98
99
100
101
102
103
104
import { useCallback, useEffect, useRef, useState } from 'react'

export default function useTestAnswerState({
  current,
  questions,
  currentQuestion,
  answersRef,
  timingsRef,
}) {
  const [answers, setAnswers] = useState({})
  const [timings, setTimings] = useState({})
  const [marked, setMarked] = useState(new Set())
  const [visited, setVisited] = useState(new Set())
  const [natInput, setNatInput] = useState('')

  const questionStartRef = useRef(Date.now())

  // Per-question elapsed timing effect
  useEffect(() => {
    const q = questions[current]
    if (!q) return
    questionStartRef.current = Date.now()
    return () => {
      const elapsed = Math.floor((Date.now() - questionStartRef.current) / 1000)
      if (elapsed > 0) {
        setTimings(t => {
          const updated = { ...t, [q.id]: (t[q.id] || 0) + elapsed }
          timingsRef.current = updated
          return updated
        })
      }
    }
  }, [current, questions, timingsRef])

  // Visited tracking effect
  useEffect(() => {
    const q = questions[current]
    if (q) setVisited(v => new Set([...v, q.id]))
  }, [current, questions])

  // NAT input sync effect
  useEffect(() => {
    const q = questions[current]
    if (q?.question_type === 'nat') setNatInput(answers[q.id] || '')
  }, [current, questions, answers])

  const setMCQ = useCallback((letter) => {
    if (!currentQuestion) return
    setAnswers(a => {
      const updated = { ...a, [currentQuestion.id]: a[currentQuestion.id] === letter ? undefined : letter }
      answersRef.current = updated
      return updated
    })
  }, [currentQuestion, answersRef])

  const toggleMSQ = useCallback((letter) => {
    if (!currentQuestion) return
    setAnswers(a => {
      const cur = (a[currentQuestion.id] || '').split(',').filter(Boolean)
      const next = cur.includes(letter) ? cur.filter(l => l !== letter) : [...cur, letter].sort()
      const updated = { ...a, [currentQuestion.id]: next.join(',') || undefined }
      answersRef.current = updated
      return updated
    })
  }, [currentQuestion, answersRef])

  const commitNAT = useCallback(() => {
    if (!currentQuestion) return
    setAnswers(a => {
      const updated = { ...a, [currentQuestion.id]: natInput.trim() || undefined }
      answersRef.current = updated
      return updated
    })
  }, [currentQuestion, natInput, answersRef])

  const clearResponse = useCallback(() => {
    if (!currentQuestion) return
    setAnswers(a => {
      const n = { ...a }
      delete n[currentQuestion.id]
      answersRef.current = n
      return n
    })
    setNatInput('')
  }, [currentQuestion, answersRef])

  return {
    answers,
    setAnswers,
    timings,
    setTimings,
    marked,
    setMarked,
    visited,
    setVisited,
    natInput,
    setNatInput,
    setMCQ,
    toggleMSQ,
    commitNAT,
    clearResponse,
    questionStartRef,
  }
}