import { useState } from 'react';
import { quizQuestions as allQuestions } from '../data/quizQuestions';
import { useSettingsStore } from '../store/useSettingsStore';
import { useResultsStore } from '../store/useResultsStore';
import { getCookieConsentValue } from 'react-cookie-consent';
const shuffleArray = (array) => {
let currentIndex = array.length, randomIndex;
while (currentIndex !== 0) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
[array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
}
return array;
};
/**
* Custom hook to manage the quiz state and logic.
* Handles question fetching, scoring, user answers, and quiz progression.
*
* @returns {Object} The quiz state and controller functions
* @property {string} status - Current status of the quiz ('ready', 'active', 'finished')
* @property {Object} currentQuestion - The currently displayed question object
* @property {number} totalQuestions - Total number of questions in the current session
* @property {number} score - Current calculated score (only available when finished)
* @property {number} currentIndex - Index of the current question
* @property {function(): void} startQuiz - Function to initialize and start the quiz based on settings
* @property {function(number): void} answerQuestion - Function to handle user answer submission
* @property {function(): void} restartQuiz - Function to reset the quiz to 'ready' state
*/
export const useQuiz = () => {
const { numQuestions, difficulty } = useSettingsStore();
const addResult = useResultsStore((state) => state.addResult);
const [status, setStatus] = useState('ready');
const [currentIndex, setCurrentIndex] = useState(0);
const [userAnswers, setUserAnswers] = useState([]);
const [questions, setQuestions] = useState([]);
const totalQuestions = questions.length;
const currentQuestion = questions[currentIndex];
const score = status === 'finished'
? userAnswers.reduce((acc, answer, index) => {
if (answer === questions[index].correctAnswer) {
return acc + 1;
}
return acc;
}, 0)
: 0;
const startQuiz = () => {
let filteredQuestions;
switch (difficulty) {
case 'hard':
filteredQuestions = allQuestions;
break;
case 'medium':
filteredQuestions = allQuestions.filter(
q => q.difficulty === 'easy' || q.difficulty === 'medium'
);
break;
case 'easy':
default:
filteredQuestions = allQuestions.filter(q => q.difficulty === 'easy');
break;
}
const sessionQuestions = shuffleArray(filteredQuestions).slice(0, Number(numQuestions));
setQuestions(sessionQuestions);
setCurrentIndex(0);
setUserAnswers([]);
setStatus('active');
};
const answerQuestion = (selectedIndex) => {
setUserAnswers((prevAnswers) => [...prevAnswers, selectedIndex]);
const isLastQuestion = currentIndex === totalQuestions - 1;
if (isLastQuestion) {
setStatus('finished');
const finalScore = userAnswers.reduce((acc, answer, index) => {
if (answer === questions[index].correctAnswer) return acc + 1;
return acc;
}, selectedIndex === questions[currentIndex].correctAnswer ? 1 : 0);
const consent = getCookieConsentValue('quizCookieConsent');
const username = consent === 'true'
? (localStorage.getItem('quizUsername') || 'noname')
: 'noname';
const resultData = {
score: finalScore,
total: totalQuestions,
difficulty: difficulty,
date: new Date().toISOString(),
};
addResult(username, resultData);
} else {
setCurrentIndex((prevIndex) => prevIndex + 1);
}
};
const restartQuiz = () => {
setStatus('ready');
};
return {
status,
currentQuestion,
totalQuestions,
score,
currentIndex,
startQuiz,
answerQuestion,
restartQuiz,
};
};