Skip to content
Snippets Groups Projects
Commit be455959 authored by Stevan Beljic's avatar Stevan Beljic
Browse files

Update 7 files

- /src/quizmenu.html
- /src/startpage.html
- /src/scripts/startpage.js
- /src/scripts/quizmenu.js
- /src/stylesheets/quizmenu.css
- /src/stylesheets/startpage.css
- /index.html
parent 8d556d46
No related branches found
No related tags found
No related merge requests found
//Stevan's Trivia Game - hosted on https://seng513a2.pages.dev
//Stevan Beljic - SENG 513 Assignment 2
/*
* Quiz class
* Used for executing the game
*/
const MAX_QUESTIONS = 10;
class Quiz {
//class fields
score = 0;
attempts = 0;
quizQuestions;
......@@ -8,47 +19,52 @@ class Quiz {
num_answered = 0;
difficulties = ['easy', 'medium', 'hard'];
//method used to format questions properly into Question objects
formatQuestion(obj) {
return new Question(obj.question, obj.correct_answer, obj.incorrect_answers[0], obj.incorrect_answers[1], obj.incorrect_answers[2], obj.difficulty);
}
//increments attempts properly, ensuring the index does not go over the length of the array
incrementAttempts(){
this.attempts++;
if(this.attempts > this.quizQuestions.length){
this.attempts = 1;
if(this.attempts >= this.quizQuestions.length){
this.attempts = 0;
}
}
/*
* Question generator method
* Pulls a question and checks if its of the desired difficulty, if not, it will pull a new question. It will do this
* until a valid question is found, and it will then yield it.
*/
*questionGenerator(){
while(true){
let tempQuestion = this.quizQuestions[this.attempts];
if(this.gotCorrect === true){
//console.log("diff index: "+this.difficulties[this.diffIndex]);
if(tempQuestion.difficulty !== this.difficulties[this.diffIndex]){
this.incrementAttempts();
continue;
}
this.incrementAttempts();
yield tempQuestion;
this.incrementAttempts();
} else {
//console.log("diff index: "+this.difficulties[this.diffIndex]);
if(tempQuestion.difficulty !== this.difficulties[this.diffIndex]){
this.incrementAttempts();
continue;
}
this.incrementAttempts();
yield tempQuestion;
this.incrementAttempts();
}
this.attempts++;
yield tempQuestion;
}
}
/*
* Method to fetch the quiz questions from the Open Trivia DB
*/
async fetchQuiz() {
await fetch('https://opentdb.com/api.php?amount=40&type=multiple')
//currently fetching geography questions
await fetch('https://opentdb.com/api.php?amount=50&category=22&type=multiple')
.then(response => response.json())
.then(data => {
const questions = [];
......@@ -58,11 +74,17 @@ class Quiz {
this.quizQuestions = questions;
})
.catch(error => console.error('Error:', error));
.catch(error => {
throw "Error connecting to database";
}); //notify user of failure to obtain quiz
}
}
/*
* Question class
* Contains question info, such as text, correct answer, incorrect answers, and difficulty
*/
class Question{
questionText = "";
......@@ -95,6 +117,10 @@ class Question{
}
/*
* User class
* Can be expanded to contain further user info. Currently only keeps track of the user's name.
*/
class User {
username = "";
......@@ -108,6 +134,11 @@ class User {
}
}
/*
* Function: init
* Called onload of body element. Sets scorecard and options to invisible as to only display initial welcome message. Reads the users
* name from local storage and displays it in a welcome message.
*/
function init(){
const tmp = localStorage.getItem('User');
const user = JSON.parse(tmp);
......@@ -121,21 +152,23 @@ function init(){
optionsDiv.style.display = "none";
}
function printName(){
let username = localStorage.getItem('username');
document.getElementById('namep').innerHTML = username+' is here';
}
/*
* function: displayQuestion
* Must be called using the .call() function
* Displays the question text and its answers randomly across the four buttons
*/
function displayQuestion(){
document.getElementById('question').innerHTML = this.questionText;
const occupiedSpaces = [];
//Uncomment this to see the difficulty of each question displayed
//console.log("Question difficulty: "+this.difficulty);
let placement = Math.floor((Math.random() * 4) + 1);
document.getElementById('option'+placement).innerHTML = this.correctOption;
occupiedSpaces.push(placement);
for(let x = 1; x <= 3; x++){
while (occupiedSpaces.includes(placement)){
while (occupiedSpaces.includes(placement)){ //generates a new number between 1 and 4 until a non-selected placement has been generated
placement = Math.floor((Math.random() * 4) + 1);
}
document.getElementById('option'+placement).innerHTML = this['incorrect'+x];
......@@ -143,20 +176,35 @@ function displayQuestion(){
}
}
/*
* function: updateScore
* Updates the scorecard element.
*/
function updateScore(score){
document.getElementById('scorecard').innerHTML = 'Score: '+score;
}
/*
* function: gameOver
* Ends the game by hiding all clickable buttons and informing the user what their final score was.
*/
function gameOver(score){
const optionsDiv = document.getElementById('optionsDiv');
optionsDiv.style.display = "none";
const scorecard = document.getElementById('scorecard');
scorecard.innerHTML = 'Your final score was '+score+'<br>Thanks for playing!';
scorecard.innerHTML = 'Your final score was '+score+'<br>Thanks for playing, '+JSON.parse(localStorage.getItem('User')).username+'!';
scorecard.style.fontSize = '30px';
scorecard.style.textAlign = 'center';
}
/*
* function: highlightCorrect
* Parameters: correctButton, selection
* Takes the button containing the correct answer and the button the user selected.
* Appropriately highlights the user's selection, displaying green if they were correct, yellow on the user's selecton if it was incorrect,
* and grey for all other buttons.
*/
function highlightCorrect(correctButton, selection) {
const buttons = document.getElementsByClassName('option');
......@@ -178,6 +226,12 @@ function highlightCorrect(correctButton, selection) {
}, 1000);
}
/*
* function: start
* Called upon clicking of start button.
* Initializes the game by creating a new quiz object. Initializes event listeners for four button options
* and hides initial welcome message.
*/
async function start(){
const game = new Quiz();
......@@ -188,15 +242,23 @@ async function start(){
scoreCard.style.display = "block";
const optionsDiv = document.getElementById('optionsDiv');
optionsDiv.style.display = "grid";
document.getElementById("question").style.gridColumn = "1/3";
optionsDiv.style.gridTemplateColumns = "repeat(2, 1fr)";
await game.fetchQuiz();
const wrap = document.getElementById('buttonwrap');
optionsDiv.style.display = "initial";
//try catch around fetch quiz. If unable to fetch quiz, display the error to the user and terminate.
try{
await game.fetchQuiz();
} catch (error){
document.getElementById('scorecard').innerHTML = error;
const optionsDiv = document.getElementById('optionsDiv');
optionsDiv.style.display = "none";
console.log("Error connecting to database.");
return;
}
//https://stackoverflow.com/questions/49680484/how-to-add-one-event-listener-for-all-buttons
//used source to create an event listener for all buttons within the wrap container
const wrap = document.getElementById('buttonwrap');
const questionGenerator = game.questionGenerator();
wrap.addEventListener('click', (event) => {
const isButton = event.target.nodeName === 'BUTTON';
if (!isButton){
......@@ -205,44 +267,45 @@ async function start(){
game.num_answered++;
const selected = event.target.innerHTML;
const correctSelection = game.quizQuestions[game.attempts-1].correctOption;
const correctSelection = game.quizQuestions[game.attempts].correctOption;
if (selected === correctSelection){
game.score+=10;
updateScore(game.score);
if (selected === correctSelection){ //right answer selected
updateScore((game.score+=10));
highlightCorrect(correctSelection, selected);
game.diffIndex = Math.min(2, game.diffIndex+1);
game.diffIndex = Math.min(2, game.diffIndex+1); //increase difficulty
game.gotCorrect = true;
if(game.num_answered > 9) {
gameOver(game.score);
}
let questionGenerated = questionGenerator.next();
const question = questionGenerated.value;
//set a timeout, allowing the highlight to be displayed before showing the next question
setTimeout(() => {
let questionGenerated = game.questionGenerator().next();
const question = questionGenerated.value;
if(game.num_answered >= MAX_QUESTIONS) {//end the game if 10 questions have been answered
gameOver(game.score);
}
//set target of "this" to be question when calling displayQuestion
displayQuestion.call(question);
}, 1000);
} else {
} else { //wrong answer selected
highlightCorrect(correctSelection, selected);
game.diffIndex = Math.max(0, game.diffIndex-1);
game.diffIndex = Math.max(0, game.diffIndex-1); //decrease difficulty
game.gotCorrect = false;
if(game.num_answered > 9) {
gameOver(game.score);
}
let questionGenerated = questionGenerator.next();
const question = questionGenerated.value;
setTimeout(() => {
let questionGenerated = game.questionGenerator().next();
const question = questionGenerated.value;
if(game.num_answered >= MAX_QUESTIONS) { //end the game if 10 questions have been answered
gameOver(game.score);
}
//set target of "this" to be question when calling displayQuestion
displayQuestion.call(question);
}, 1000);
}
})
const questionGenerator = game.questionGenerator();
//display initial question
let questionGenerated = questionGenerator.next();
const question = questionGenerated.value;
displayQuestion.call(question);
displayQuestion.call(question); //set target of "this" to be question when calling displayQuestion
}
\ No newline at end of file
/*
* function readName
* Reads the users name and saves it to local storage
*/
function readName(){
let tempname = document.getElementById('name').value;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment