From da06ce7dcf8ad037fda844d9be179cf2f001c5d7 Mon Sep 17 00:00:00 2001 From: chukwudiokolomansion Date: Wed, 29 Apr 2026 05:53:08 +0200 Subject: [PATCH] pairprojectwithRachel --- index.html | 11 +- src/index.js | 355 ++++++++++++++++++++++++++++++++++++++--------- src/question.js | 87 +++++++++++- src/quiz.js | 93 +++++++++++-- styles/style.css | 201 ++++++++++++++------------- 5 files changed, 560 insertions(+), 187 deletions(-) diff --git a/index.html b/index.html index 534cd886..8ebb6046 100644 --- a/index.html +++ b/index.html @@ -1,4 +1,4 @@ - + @@ -28,7 +28,7 @@

JavaScript Quiz

- + - - - \ No newline at end of file + diff --git a/src/index.js b/src/index.js index 03737ba3..b6efa7b3 100644 --- a/src/index.js +++ b/src/index.js @@ -10,63 +10,155 @@ document.addEventListener("DOMContentLoaded", () => { const questionContainer = document.querySelector("#question"); const choiceContainer = document.querySelector("#choices"); const nextButton = document.querySelector("#nextButton"); - + const restartButton = document.querySelector("#restartButton"); + //restartButton.addEventListener("click", restartQuiz); + //document.querySelector("#timeRemaining span").innerText = + //`${minutes}:${seconds}`;*/ // End view elements const resultContainer = document.querySelector("#result"); - /************ SET VISIBILITY OF VIEWS ************/ // Show the quiz view (div#quizView) and hide the end view (div#endView) + restartButton.style.display = "flex"; quizView.style.display = "block"; endView.style.display = "none"; - + //restartButton.style.display = "none"; /************ QUIZ DATA ************/ - + // Array with the quiz questions const questions = [ - new Question("What is 2 + 2?", ["3", "4", "5", "6"], "4", 1), - new Question("What is the capital of France?", ["Miami", "Paris", "Oslo", "Rome"], "Paris", 1), - new Question("Who created JavaScript?", ["Plato", "Brendan Eich", "Lea Verou", "Bill Gates"], "Brendan Eich", 2), - new Question("What is the mass–energy equivalence equation?", ["E = mc^2", "E = m*c^2", "E = m*c^3", "E = m*c"], "E = mc^2", 3), + /*new Question("What is 2 + 2?", ["3", "4", "5", "6"], "4", 1), + new Question( + "What is the capital of France?", + ["Miami", "Paris", "Oslo", "Rome"], + "Paris", + 1, + ), + new Question( + "Who created JavaScript?", + ["Plato", "Brendan Eich", "Lea Verou", "Bill Gates"], + "Brendan Eich", + 2, + ), + new Question( + "What is the mass–energy equivalence equation?", + ["E = mc^2", "E = m*c^2", "E = m*c^3", "E = m*c"], + "E = mc^2", + 3, + ),*/ // Add more questions here + new Question( + "Which country does Sara Faltas come from?", + ["Germany", "Egypt", "Netherlands", "Algeria"], + "Egypt", + 1, + ), + new Question( + "What is Dante Besong's country of origin?", + ["Nigeria", "Germany", "Benin", "Cameroon"], + "Cameroon", + 2, + ), + new Question( + "What is Rachel Akodo's country of origin?", + ["Nigeria", "France", "Benin", "Cameroon"], + "Benin", + 3, + ), + new Question( + "What is the country of origin of Jordi Font?", + ["Italy", "Spain", "Costa Rica", "Venezuela"], + "Spain", + 2, + ), + new Question( + "What other language can Jorge Berrizbeitia speak?", + ["Swahili", "Deutsch", "French", "Spanish"], + "Spanish", + 2, + ), + new Question( + "What is the country of origin of Chukwudi Okolo?", + ["Nigeria", "Germany", "Benin", "Cameroon"], + "Nigeria", + 2, + ), + new Question( + "Jorge Berrizbeitia is a native of which country?", + ["Italy", "Spain", "Costa Rica", "Venezuela"], + "Venezuela", + 2, + ), + new Question( + "Which country is Aybike Celebi Visser originally from?", + ["Netherlands", "Germany", "Turkey", "Georgia"], + "Turkey", + 3, + ), ]; const quizDuration = 120; // 120 seconds (2 minutes) - /************ QUIZ INSTANCE ************/ - + // Create a new Quiz instance object const quiz = new Quiz(questions, quizDuration, quizDuration); + // Shuffle the quiz questions quiz.shuffleQuestions(); - + let timer; /************ SHOW INITIAL CONTENT ************/ + function startTimer() { + timer = setInterval(function () { + // decrease time + quiz.timeRemaining--; + const minutes = Math.floor(quiz.timeRemaining / 60) + .toString() + .padStart(2, "0"); + const seconds = (quiz.timeRemaining % 60).toString().padStart(2, "0"); + + // Display the time remaining in the time remaining container + //const timeRemainingContainer = document.getElementById("timeRemaining"); + //timeRemainingContainer.innerText = `${minutes}:${seconds}`; + + /*// convert to minutes and seconds + const minutes = Math.floor(quiz.timeRemaining / 60) + .toString() + .padStart(2, "0"); + + const seconds = (quiz.timeRemaining % 60).toString().padStart(2, "0"); + + // update UI*/ + const timeRemainingContainer = document.getElementById("timeRemaining"); + timeRemainingContainer.innerText = `${minutes}:${seconds}`; + + // stop when time is up + if (quiz.timeRemaining <= 0) { + quiz.timeRemaining = 0; + clearInterval(timer); + showResults(); + } + }, 1000); // runs every 1 second + } // Convert the time remaining in seconds to minutes and seconds, and pad the numbers with zeros if needed - const minutes = Math.floor(quiz.timeRemaining / 60).toString().padStart(2, "0"); - const seconds = (quiz.timeRemaining % 60).toString().padStart(2, "0"); - - // Display the time remaining in the time remaining container - const timeRemainingContainer = document.getElementById("timeRemaining"); - timeRemainingContainer.innerText = `${minutes}:${seconds}`; // Show first question showQuestion(); + startTimer(); /************ TIMER ************/ - let timer; - + //let timer; /************ EVENT LISTENERS ************/ nextButton.addEventListener("click", nextButtonHandler); - + restartButton.addEventListener("click", restartQuiz); /************ FUNCTIONS ************/ @@ -74,8 +166,6 @@ document.addEventListener("DOMContentLoaded", () => { // nextButtonHandler() - Handles the click on the next button // showResults() - Displays the end view and the quiz results - - function showQuestion() { // If the quiz has ended, show the results if (quiz.hasEnded()) { @@ -87,88 +177,215 @@ document.addEventListener("DOMContentLoaded", () => { questionContainer.innerText = ""; choiceContainer.innerHTML = ""; - // Get the current question from the quiz by calling the Quiz class method `getQuestion()` - const question = quiz.getQuestion(); + // Get the current question from the quiz by calling the Qui0 + // Shuffle the choices of the current question by calling the method 'shuffleChoices()' on the question object + const question = quiz.getQuestion(); question.shuffleChoices(); - - // YOUR CODE HERE: - // + // console.log(quiz); + //console.log(question); // 1. Show the question + const questionElement = document.getElementById("question"); + questionElement.style.display = "block"; + questionElement.innerText = question.text; + + //console.log(questionDisplay); + // Update the inner text of the question container element and show the question text - // 2. Update the green progress bar // Update the green progress bar (div#progressBar) width so that it shows the percentage of questions answered - - progressBar.style.width = `65%`; // This value is hardcoded as a placeholder + const progressBar = document.getElementById("progressBar"); + const progressingPercent = + ((quiz.currentQuestionIndex + 1) / quiz.questions.length) * 100; + progressBar.style.width = progressingPercent + "%"; + //progressBar.style.width = progressPercent + "%"; + //progressPercent + "%"; + //progressBar.style.width = `65%`; // This value is hardcoded as a placeholder + + // 3. Update the question count text + // Update the question count (div#questionCount) show the current question out of total questions + const progressText = document.getElementById("questionCount"); + progressText.innerText = + "Question-" + + (quiz.currentQuestionIndex + 1) + + "-of-" + + quiz.questions.length; + //questionCount.innerText = `Question 1 of 10`; // This value is hardcoded as a placeholder + //Display choices + // const choicesList = document.getElementById("choices"); + /// clear old choices + // choicesList.innerHTML = ""; - // 3. Update the question count text - // Update the question count (div#questionCount) show the current question out of total questions - - questionCount.innerText = `Question 1 of 10`; // This value is hardcoded as a placeholder + /// create
  • + // create radio input - // 4. Create and display new radio input element with a label for each choice. + // create radio input + + question.choices.forEach((choice, index) => { + const li = document.createElement("li"); + + const element = document.createElement("input"); //li element and radio input + element.type = "radio"; + element.name = "choice"; + element.value = choice; // This value is hardcoded as a placeholder + element.id = "choice" + index; + + const label = document.createElement("label"); + label.setAttribute("for", element.id); + label.innerText = choice; // This value is hardcoded as a placeholder + + li.appendChild(element); + li.appendChild(label); + + // Append the radio input and label to the choice container + choiceContainer.appendChild(li); + }); + + // const element = document.createElement("element"); + /// loop through choices + // question.choices.forEach((eachChoice) => { + + //const li = document.createElement("li"); + + // label = document.createElement("label"); + //label.setAttribute("for", element.id); + //label.textContent = choice; + //console.log(eachChoice); + + // element.type = "radio"; + // element.name = "choice"; + // element.value = CHOICE TEXT HERE; + //element.id = "choice" + index; + // }); + // Loop through the current question `choices`. - // For each choice create a new radio input with a label, and append it to the choice container. - // Each choice should be displayed as a radio input element with a label: - /* + // For each choice create a new radio input with a label, and append it to the choice container. + // Each choice should be displayed as a radio input element with a label: + /*
    */ - // Hint 1: You can use the `document.createElement()` method to create a new element. - // Hint 2: You can use the `element.type`, `element.name`, and `element.value` properties to set the type, name, and value of an element. - // Hint 3: You can use the `element.appendChild()` method to append an element to the choices container. - // Hint 4: You can use the `element.innerText` property to set the inner text of an element. + //const label = document.createElement("label"); + //label.setAttribute("for", element.id); + //label.textContent = choice; - } - - - - function nextButtonHandler () { - let selectedAnswer; // A variable to store the selected answer value + //li.appendChild(element); + //li.appendChild(label); + //choicesList.appendChild(li); + //}); + } + // Hint 1: You can use the `document.createElement()` method to create a new element. + // Hint 2: You can use the `element.type`, `element.name`, and `element.value` properties to set the type, name, and value of an element. + // Hint 3: You can use the `element.appendChild()` method to append an element to the choices container. + // Hint 4: You can use the `element.innerText` property to set the inner text of an element. + //} + //startTimer(); + function nextButtonHandler() { + const choices = document.querySelectorAll(`input[name="choice"]`); // A variable to store the selected answer value // YOUR CODE HERE: - // + let selectedAnswer = null; // // 1. Get all the choice elements. You can use the `document.querySelectorAll()` method. - // 2. Loop through all the choice elements and check which one is selected - // Hint: Radio input elements have a property `.checked` (e.g., `element.checked`). - // When a radio input gets selected the `.checked` property will be set to true. - // You can use check which choice was selected by checking if the `.checked` property is true. - - - // 3. If an answer is selected (`selectedAnswer`), check if it is correct and move to the next question - // Check if selected answer is correct by calling the quiz method `checkAnswer()` with the selected answer. - // Move to the next question by calling the quiz method `moveToNextQuestion()`. - // Show the next question by calling the function `showQuestion()`. - } - - - + choices.forEach((choice) => { + if (choice.checked) { + selectedAnswer = choice.value; + } + }); + + if (selectedAnswer) { + quiz.checkAnswer(selectedAnswer); + quiz.moveToNextQuestion(); + showQuestion(); + } + } + /*if (selectedAnswer) { + quiz.checkAnswer(selectedAnswer); + showQuestion(); + } else { + quiz.moveToNextQuestion(); + showQuestion(); + }*/ + // Hint: Radio input elements have a property `.checked` (e.g., `element.checked`). + // When a radio input gets selected the `.checked` property will be set to true. + // You can use check which choice was selected by checking if the `.checked` property is true. + + // 3. If an answer is selected (`selectedAnswer`), check if it is correct and move to the next question + // Check if selected answer is correct by calling the quiz method `checkAnswer()` with the selected answer. + // Move to the next question by calling the quiz method `moveToNextQuestion()`. + // Show the next question by calling the function `showQuestion()`. + // restartButton.addEventListener("click", restartQuiz); function showResults() { - // YOUR CODE HERE: + // stop timer + clearInterval(timer); + /*quizView.style.display = "none"; + endView.style.display = "flex";*/ + + //resultContainer.innerText = + //`You scored ${quiz.correctAnswers} out of ${quiz.questions.length} correct answers!`;*/ // // 1. Hide the quiz view (div#quizView) quizView.style.display = "none"; // 2. Show the end view (div#endView) endView.style.display = "flex"; - - // 3. Update the result container (div#result) inner text to show the number of correct answers out of total questions - resultContainer.innerText = `You scored 1 out of 1 correct answers!`; // This value is hardcoded as a placeholder + + //restartButton.style.display = "block"; + + // 3. Update the result container (div#result) inner text to show the number of correct answers out of total + resultContainer.innerText = `You scored ${quiz.correctAnswers} out of ${quiz.questions.length} correct answers!`; + //resultContainer.innerText = `You scored 1 out of 1 correct answers!`; // This value is hardcoded as a placeholder + //restartButton(); } - -}); \ No newline at end of file + function restartQuiz() { + // 1. Reset quiz data + quiz.currentQuestionIndex = 0; + quiz.correctAnswers = 0; + + // 2. Reset time + quiz.timeRemaining = quiz.timeLimit; + + // 3. Update timer display + const minutes = Math.floor(quiz.timeRemaining / 60) + .toString() + .padStart(2, "0"); + + const seconds = (quiz.timeRemaining % 60).toString().padStart(2, "0"); + + document.getElementById("timeRemaining").innerText = + `${minutes}:${seconds}`; + + // 4. Reset views + endView.style.display = "none"; + quizView.style.display = "block"; + restartButton.style.display = "block"; + + // 5. Restart timer + clearInterval(timer); + startTimer(); + /*if (restartButton) { + restartButton.addEventListener("click", restartQuiz); + }*/ + //restartButton(); + + // 6. Show first question again + showQuestion(); + } + + //restartQuiz(); + + //restartButton.addEventListener("click", restartQuiz); +}); diff --git a/src/question.js b/src/question.js index 68f6631a..8e026ce7 100644 --- a/src/question.js +++ b/src/question.js @@ -1,7 +1,84 @@ +//class Question { +// YOUR CODE HERE: +// +// 1. constructor (text, choices, answer, difficulty) + +// 2. shuffleChoices() class Question { - // YOUR CODE HERE: - // - // 1. constructor (text, choices, answer, difficulty) + // YOUR CODE HERE: + // + // 1. constructor (questions, timeLimit, timeRemaining) + constructor(text, choices, answer, difficulty) { + this.text = text; // string + this.choices = choices; + this.answer = answer; //string + this.difficulty = difficulty; //number between 1 (easiest) - 3 (hardest) + } + + //methods + + shuffleChoices() { + const questionChoices = this.choices; + + for (let i = questionChoices.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + + // swap elements + let temp = questionChoices[i]; + questionChoices[i] = questionChoices[j]; + questionChoices[j] = temp; + } + + return questionChoices; + } + + // Quiz { + //constructor(questions, timeLimite,timeRemaining,) + //this.questions = questions + //this.timeLimit = timeLimit + //.timeRemaining = timeRemaining + //this.correctAnswers = 0 + //this.currentQuestionIndex = 0 + + //getQuestion () { + //method :Returns the question from the questions array at the position of currentQuestionIndex. + //project = this.currentQuestionIndex.push(Question) + //return project + + //} + + //moveToNextQuestion() { + //for (let i= 0 ; i < project.lenght; i++) + // let project1 = project[i]return project1 += 1 + + //} + + //shuffleQuestions() { + //questions.forEach(eachQuestion) => { + + //} + //checkAnswer (checkWord) { + //for (j = 0; j = questions.length ; j++) { + //Let project2 = questions[i] + //if( + //correct answer === "project2" + //return correctAnswer += 1 + //} + //hasEnded () { + //if (this.currentQuestionIndex === questions.length ) { + //return truee } + //else { + // false + //} + //} + //return} + + //} - // 2. shuffleChoices() -} \ No newline at end of file + //} + // 2. getQuestion() + // 3. moveToNextQuestion() + // 4. shuffleQuestions() + // 5. checkAnswer(answer) + // 6. hasEnded() +} diff --git a/src/quiz.js b/src/quiz.js index d94cfd14..651dc501 100644 --- a/src/quiz.js +++ b/src/quiz.js @@ -1,15 +1,88 @@ class Quiz { - // YOUR CODE HERE: - // - // 1. constructor (questions, timeLimit, timeRemaining) + // YOUR CODE HERE: + /// Quiz { - // 2. getQuestion() - - // 3. moveToNextQuestion() + // 1. constructor (questions, timeLimit, timeRemaining) + constructor(questions, timeLimit, timeRemaining) { + this.questions = questions; + this.timeLimit = timeLimit; + this.timeRemaining = timeRemaining; + this.correctAnswers = 0; + this.currentQuestionIndex = 0; + } - // 4. shuffleQuestions() + // 2. getQuestion() + getQuestion() { + return this.questions[this.currentQuestionIndex]; + //return currentQuestionIndex; + } - // 5. checkAnswer(answer) + // 3. moveToNextQuestion() + moveToNextQuestion() { + return this.currentQuestionIndex++; + } + // 4. shuffleQuestions() + shuffleQuestions() { + const questionShuffle = this.questions; - // 6. hasEnded() -} \ No newline at end of file + for (let k = questionShuffle.length - 1; k > 0; k--) { + const m = Math.floor(Math.random() * (k + 1)); + + // swap elements + let temp1 = questionShuffle[k]; + questionShuffle[k] = questionShuffle[m]; + questionShuffle[m] = temp1; + } + + return questionShuffle; + } + + // 5. checkAnswer(answer) + checkAnswer(answer) { + if (answer === this.getQuestion().answer) { + return this.correctAnswers++; + } + } + // 6. hasEnded() + hasEnded() { + if (this.currentQuestionIndex >= this.questions.length) { + return true; + } else { + return false; + } + } + + // 7. filterQuestionsByDifficulty() + filterQuestionsByDifficulty(difficulty) { + if (typeof difficulty !== "number" || difficulty < 1 || difficulty > 3) { + return; + } + + // filter and update questions + this.questions = this.questions.filter((question) => { + return question.difficulty === difficulty; + }); + } + //let filterQuestion = this.questions.filter((eachDifficulty) => { + // return eachDifficulty.difficulty >= 1 && eachDifficulty.difficulty <= 3; + // }); + //return filterQuestion === difficulty; + //this.questions.push(eachDifficulty.difficulty); + ///return filterQuestion; + + //if (difficulty => 1 || difficulty =< 3) { + ////return "difficulty must be a number between 1 and 3"; + //} + // this.questions.filter((question) => { + //question.difficulty === difficulty); + //} + + averageDifficulty() { + let sum = this.questions.reduce( + (total, question) => total + question.difficulty, + 0, + ); + let average = sum / this.questions.length; + return average; + } +} diff --git a/styles/style.css b/styles/style.css index 8de97e38..460d4b05 100644 --- a/styles/style.css +++ b/styles/style.css @@ -1,172 +1,177 @@ /* CSS Reset */ * { - margin: 0; - padding: 0; - box-sizing: border-box; + margin: 0; + padding: 0; + box-sizing: border-box; } body { - font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; - background-color: #f4f4f4; - color: #333; - line-height: 1.6; - padding: 20px; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + background-color: #f4f4f4; + color: #333; + line-height: 1.6; + padding: 20px; } header { - padding: 0 20px; + padding: 0 20px; } .container { - height: 540px; - max-width: 600px; - margin: auto; - padding: 20px; - background: #fff; - box-shadow: 0 5px 15px rgba(0,0,0,0.1); -} - -#quizView, #endView { - overflow-y: auto; - padding: 20px; - box-sizing: border-box; - display: flex; - flex-direction: column; - justify-content: space-between; - align-items: center; + height: 540px; + max-width: 600px; + margin: auto; + padding: 20px; + background: #fff; + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); +} + +#quizView, +#endView, +#restartButton { + overflow-y: auto; + padding: 20px; + box-sizing: border-box; + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; } .view { - text-align: center; - margin-top: 20px; + text-align: center; + margin-top: 20px; } button { - color: white; - border: none; - border-radius: 5px; - padding: 10px 20px; - cursor: pointer; - font-size: 16px; - width: 160px; + color: white; + border: none; + border-radius: 5px; + padding: 10px 20px; + cursor: pointer; + font-size: 16px; + width: 160px; } .button-primary { - background-color: #4caf50; + background-color: #4caf50; } .button-primary:hover { - background-color: #46a049; + background-color: #46a049; } .button-secondary { - background-color: #333; + background-color: #333; } .button-secondary:hover { - background-color: #1e1e1e; + background-color: #1e1e1e; } .title { - margin-top: 20px; - margin-bottom: -12px; + margin-top: 20px; + margin-bottom: -12px; } - button:hover { - background-color: #4cae4c; + background-color: #4cae4c; } ul { - list-style-type: none; - padding: 0; + list-style-type: none; + padding: 0; } li { - margin: 10px 0; + margin: 10px 0; } input[type="radio"] { - margin-right: 10px; + margin-right: 10px; } -.emphasis, #startQuestionsCount, #questionCount, #resultQuestionsCount { - font-size: 16px; - font-weight: bold; - margin: 0 auto; - margin-bottom: 10px; +.emphasis, +#startQuestionsCount, +#questionCount, +#resultQuestionsCount { + font-size: 16px; + font-weight: bold; + margin: 0 auto; + margin-bottom: 10px; } .content { - min-height: 300px; - display: flex; - flex-direction: column; + min-height: 300px; + display: flex; + flex-direction: column; } #choices { - min-width: 25px; - margin: 0 auto; - text-align: left; + min-width: 25px; + margin: 0 auto; + text-align: left; } -#quizDescription, #question, #result { - font-size: 18px; - font-style: italic; - color: #333; - margin: 0 auto; - margin-top: 20px; - margin-bottom: 12px; +#quizDescription, +#question, +#result { + font-size: 18px; + font-style: italic; + color: #333; + margin: 0 auto; + margin-top: 20px; + margin-bottom: 12px; } #quizDescription { - margin-bottom: 20px; + margin-bottom: 20px; } - #progress { - width: 100%; - background-color: #ddd; - border-radius: 8px; - overflow: hidden; - margin-bottom: 5px; + width: 100%; + background-color: #ddd; + border-radius: 8px; + overflow: hidden; + margin-bottom: 5px; } #progressBar { - height: 20px; - background-color: #4caf50; - width: 0%; - border-radius: 8px; + height: 20px; + background-color: #4caf50; + width: 0%; + border-radius: 8px; } #result-progress { - width: 100%; - background-color: #ddd; - border-radius: 8px; - overflow: hidden; - margin-bottom: 5px; + width: 100%; + background-color: #ddd; + border-radius: 8px; + overflow: hidden; + margin-bottom: 5px; } .divider { - width: 100%; - height: 20px; - background-color: #ddd; - border-radius: 8px; - overflow: hidden; - margin-bottom: 5px; + width: 100%; + height: 20px; + background-color: #ddd; + border-radius: 8px; + overflow: hidden; + margin-bottom: 5px; } #resultProgressBar { - width: 100%; - height: 20px; - background-color: #4caf50; - width: 100%; - border-radius: 8px; + width: 100%; + height: 20px; + background-color: #4caf50; + width: 100%; + border-radius: 8px; } #timeRemaining { - font-size: 14px; - font-style: italic; - color: #333; - margin: 0 auto; - margin-top: -35px; - margin-bottom: 12px; -} \ No newline at end of file + font-size: 14px; + font-style: italic; + color: #333; + margin: 0 auto; + margin-top: -35px; + margin-bottom: 12px; +}