1- const TIME_LIMIT = 15 ; // Total time for each question
1+ const TIME_LIMIT = 15 ; // seconds per question
22let timeLeft = TIME_LIMIT ;
3- let timerInterval = null ; // This will store the interval ID
3+ let timerInterval = null ;
44
5- // Get the timer element from the DOM
65const timerElement = document . getElementById ( "time" ) ;
76
8- const data = [ { q : '2 + 2 = ?' , a : [ '3' , '4' , '5' ] , c : 1 } , { q : 'Capital of France?' , a : [ 'Berlin' , 'Paris' , 'Rome' ] , c : 1 } ] ;
7+ let questions = [ ] ; // API-loaded questions
98let i = 0 , score = 0 ;
9+
1010const q = document . getElementById ( 'q' ) ,
1111 answers = document . getElementById ( 'answers' ) ,
1212 result = document . getElementById ( 'result' ) ;
1313
14- // Function to handle moving to the next question when time runs out
15- function handleNextQuestion ( ) {
16- i ++ ;
17- render ( ) ;
14+ /** Decode HTML entities from API */
15+ function decodeHTML ( str ) {
16+ const txt = document . createElement ( 'textarea' ) ;
17+ txt . innerHTML = str ;
18+ return txt . value ;
19+ }
20+
21+ /** Shuffle array */
22+ function shuffle ( arr ) {
23+ return arr . sort ( ( ) => Math . random ( ) - 0.5 ) ;
24+ }
25+
26+ /** Fetch questions from Open Trivia DB API */
27+ async function loadQuestions ( ) {
28+ try {
29+ const res = await fetch ( 'https://opentdb.com/api.php?amount=5&type=multiple' ) ;
30+ const data = await res . json ( ) ;
31+ questions = data . results . map ( q => ( {
32+ q : decodeHTML ( q . question ) ,
33+ a : shuffle ( [ decodeHTML ( q . correct_answer ) , ...q . incorrect_answers . map ( decodeHTML ) ] ) ,
34+ c : null , // correct answer index
35+ correctAnswer : decodeHTML ( q . correct_answer )
36+ } ) ) ;
37+ // Compute correct answer index
38+ questions . forEach ( qObj => {
39+ qObj . c = qObj . a . findIndex ( ans => ans === qObj . correctAnswer ) ;
40+ } ) ;
41+ } catch ( err ) {
42+ console . error ( 'Failed to load questions' , err ) ;
43+ q . textContent = 'Failed to load questions 😢' ;
44+ answers . innerHTML = '' ;
45+ }
1846}
1947
48+ /** Start timer for each question */
2049function startTimer ( ) {
21- // Clear any existing timer before starting a new one
2250 clearInterval ( timerInterval ) ;
23-
24- // Make sure the timer is visible at the start of a question
2551 timerElement . parentElement . style . display = 'block' ;
26-
27- // Reset the time left for the new question
2852 timeLeft = TIME_LIMIT ;
2953 timerElement . textContent = timeLeft ;
30- timerElement . parentElement . classList . remove ( 'warning' ) ; // Remove warning color
54+ timerElement . parentElement . classList . remove ( 'warning' ) ;
3155
3256 timerInterval = setInterval ( ( ) => {
3357 timeLeft -- ;
3458 timerElement . textContent = timeLeft ;
3559
36- // Add a visual warning when time is low
3760 if ( timeLeft <= 5 ) {
3861 timerElement . parentElement . classList . add ( 'warning' ) ;
3962 }
@@ -45,37 +68,47 @@ function startTimer() {
4568 } , 1000 ) ;
4669}
4770
71+ /** Move to next question */
72+ function handleNextQuestion ( ) {
73+ i ++ ;
74+ render ( ) ;
75+ }
76+
77+ /** Render current question */
4878function render ( ) {
49- if ( i >= data . length ) {
50- clearInterval ( timerInterval ) ; // Stop timer at the end
51-
52- // Hide the timer element
79+ if ( ! questions . length ) return ;
80+
81+ if ( i >= questions . length ) {
82+ clearInterval ( timerInterval ) ;
5383 timerElement . parentElement . style . display = 'none' ;
54-
55- q . textContent = 'Done!' ;
84+ q . textContent = '🎉 Quiz Complete!' ;
5685 answers . innerHTML = '' ;
57- result . textContent = `Score: ${ score } /${ data . length } ` ;
86+ result . textContent = `Score: ${ score } /${ questions . length } ` ;
5887 return ;
5988 }
6089
61- // Start the timer each time a new question is rendered
6290 startTimer ( ) ;
6391
64- const cur = data [ i ] ;
92+ const cur = questions [ i ] ;
6593 q . textContent = cur . q ;
6694 answers . innerHTML = '' ;
95+ result . textContent = '' ;
96+
6797 cur . a . forEach ( ( ans , idx ) => {
6898 const b = document . createElement ( 'button' ) ;
6999 b . textContent = ans ;
70100 b . addEventListener ( 'click' , ( ) => {
71101 clearInterval ( timerInterval ) ;
72102 if ( idx === cur . c ) score ++ ;
73- i ++ ;
74- render ( ) ;
103+ handleNextQuestion ( ) ;
75104 } ) ;
76105 answers . appendChild ( b ) ;
77106 } ) ;
78107}
79108
80- // Initial call to start the quiz
81- render ( ) ;
109+ /** Initialize quiz */
110+ ( async function init ( ) {
111+ result . textContent = 'Loading questions...' ;
112+ await loadQuestions ( ) ;
113+ render ( ) ;
114+ } ) ( ) ;
0 commit comments