Home > Blockchain >  Shuffle Quiz API answers with JavaScript
Shuffle Quiz API answers with JavaScript

Time:10-13

I'm pulling 10 random questions from an API but currently, the correct answer is set to always be 'D'. I'm struggling to find a way to randomize the answers so that the correct answer is not always 'D' or any other option I set in the code. The JSON is an array of objects but because incorrect_answers is an inner array within the object separate from correct_answer, this is where I'm getting confused. If I shuffle the inner array, that just shuffles options A, B and C. D remains a separate property outside of that that inner array.

Hope someone can help. Thanks in advance. see app screenshot here

This is a sample from the JSON

{
  "response_code": 0,
  "results": [
    {
      "category": "Entertainment: Video Games",
      "type": "multiple",
      "difficulty": "easy",
      "question": "What is the most expensive weapon in Counter-Strike: Global Offensive?",
      "correct_answer": "Scar-20/G3SG1",
      "incorrect_answers": [
      "M4A1",
      "AWP",
      "R8 Revolver"
      ]
    },
    {
      "category": "Entertainment: Cartoon & Animations",
      "type": "multiple",
      "difficulty": "easy",
      "question": "Who is the only voice actor to have a speaking part in all of the Disney Pixar feature films? ",
      "correct_answer": "John Ratzenberger",
      "incorrect_answers": [
      "Tom Hanks",
      "Dave Foley",
      "Geoffrey Rush"
      ]
    }
}

This is my code so far

const main = () => {
       let score = 0;
       let questionCounter = 0;
       let availableQuestions = [];
       let currentQuestion = {};

// target DOM elements
     const question = document.querySelector(".question-container");

     const choices = document.querySelectorAll(".choice-txt");

     const selection = document.querySelectorAll(".choice-container");

// API endpoint     
     const endPoint = `https://opentdb.com/api.php?amount=10&difficulty=easy&type=multiple`;

// fetch data from the API
     fetch(endPoint)
     .then((res)=>{
            return res.json();
     })
     .then((json)=>{
            question.innerHTML = `<p>
            ${json.results[0].question}
            </p>`

            // populate the 4 answer options
            // currently the correct answer is always D
            choices[0].innerText = `${json.results[0].incorrect_answers[0]}`
            choices[1].innerText = `${json.results[0].incorrect_answers[1]}`
            choices[2].innerText = `${json.results[0].incorrect_answers[2]}`
            choices[3].innerText = `${json.results[0].correct_answer}`
     })
     .catch((err)=>{
            console.log(`An error occured ${err}`);
     })



     selection[0].addEventListener("click",()=>{
       console.log(`Answer "A" selected`)
     })
     selection[1].addEventListener("click",()=>{
       console.log(`Answer "B" selected`)
     })
     selection[2].addEventListener("click",()=>{
       console.log(`Answer "C" selected`)
     })
     selection[3].addEventListener("click",()=>{
       console.log(`Answer "D" selected`)
     })
}
main();

CodePudding user response:

For my answer I'm not using the fetch so you can see the results.

My answer gets the correct and incorrect answers and throws them into an array. Then that array gets randomized.

let json = {
  "response_code": 0,
  "results": [{
      "category": "Entertainment: Video Games",
      "type": "multiple",
      "difficulty": "easy",
      "question": "What is the most expensive weapon in Counter-Strike: Global Offensive?",
      "correct_answer": "Scar-20/G3SG1",
      "incorrect_answers": [
        "M4A1",
        "AWP",
        "R8 Revolver"
      ]
    },
    {
      "category": "Entertainment: Cartoon & Animations",
      "type": "multiple",
      "difficulty": "easy",
      "question": "Who is the only voice actor to have a speaking part in all of the Disney Pixar feature films? ",
      "correct_answer": "John Ratzenberger",
      "incorrect_answers": [
        "Tom Hanks",
        "Dave Foley",
        "Geoffrey Rush"
      ]
    }
  ]
};

let answers = [];
let test = json.results[0];

answers.push({
  "correct": 1,
  "answer": test["correct_answer"]
});

test.incorrect_answers.forEach(function(a) {
  answers.push({
    "correct": 0,
    "answer": a
  });
});

answers.sort(() => (Math.random() > 0.5) ? 1 : -1)

console.log(answers)

CodePudding user response:

For this, you need to put together correct/incorrect answers into an object array. (Making normalization)

I used the Fisher-Yates shuffle. Take a look at here


Shuffling Part:

function shuffle(array) {
  let currentIndex = array.length, randomIndex;

  // While there remain elements to shuffle.
  while (currentIndex != 0) {

    // Pick a remaining element.
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex--;

    // And swap it with the current element.
    [array[currentIndex], array[randomIndex]] = [
      array[randomIndex], array[currentIndex]];
  }

  return array;
}

Also, I made improvements to the code for readability.

Normalization Part:

// fetch data from the API
fetch(endPoint)
  .then((res) => {
    return res.json();
  }).then((json) => {
    question.innerHTML = 
    `<p>
      ${json.results[0].question}
    </p>`
    let answers = json.results[0].incorrect_answers.map(f => {
      return {
        isCorrect: false,
        text: f
      }
    });

    answers.push({
      isCorrect: true,
      text: json.results[0].correct_answer
    });

    // populate the shuffled 4 answer options
    shuffle(answers).forEach((answer, index) => {
      choices[index].innerText = `${answer.text}`
    })
  })
  .catch((err) => {
    console.log(`An error occured ${err}`);
  })

Test Part:

function shuffle(array) {
  let currentIndex = array.length, randomIndex;

  // While there remain elements to shuffle.
  while (currentIndex != 0) {

// Pick a remaining element.
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;

// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
  array[randomIndex], array[currentIndex]];
  }

  return array;
}

// Create sample data.
const results = [
  {
"category": "Entertainment: Video Games",
"type": "multiple",
"difficulty": "easy",
"question": "What is the most expensive weapon in Counter-Strike: Global Offensive?",
"correct_answer": "Scar-20/G3SG1",
"incorrect_answers": [
  "M4A1",
  "AWP",
  "R8 Revolver"
]
  },
  {
"category": "Entertainment: Cartoon & Animations",
"type": "multiple",
"difficulty": "easy",
"question": "Who is the only voice actor to have a speaking part in all of the Disney Pixar feature films? ",
"correct_answer": "John Ratzenberger",
"incorrect_answers": [
  "Tom Hanks",
  "Dave Foley",
  "Geoffrey Rush"
]
  }
];

// Putting wrong answers
let answers = results[0].incorrect_answers.map(f => {
  return {
isCorrect: false,
text: f
  }
});
// Also putting correct answer
answers.push({
  isCorrect: true,
  text: results[0].correct_answer
});

//Logging shuffled answers
shuffle(answers).forEach((answer, index) => {
  console.log(answer);
})

  • Related