Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I change javascript quiz results to weight based scoring?

Tags:

javascript

I'm trying to build a multiple choice test using javascript, that displays one question at a time (fading to the next question). after all the questions have been answered, then depending on your answers it gives you your results. The results of the actual questions don't need to be displayed just a score and explanation of that score as the result will be a bunch of text.

For example:

  • a score of 0-20 = result 1
  • 21-50 = result 2
  • 51-60 = result 3
  • 61-80 = result 4
  • 81 - 100 = result 5

Below is my code, how can I change it so that no answer is "correct" it simply gives a text result at the end of the quiz depending on the range of the score as stated above?

Javascript:

 (function() {
var questions = [{
question: "Question1",
choices: ["choice1", "choice2", "choice3"],
correctAnswer:0
}, {
question: "Question2",
choices: ["choice1", "choice2", "choice3"],
correctAnswer: 4
}, {
question: "Question3",
choices: ["choice1", "choice2", "choice3"],
correctAnswer: 0
}, {
question: "Question4",
choices: ["choice1", "choice2", "choice3"]
correctAnswer: 3
}, {
question: "Question5",
choices: ["choice1", "choice2", "choice3"],
correctAnswer: 4
}];

var questionCounter = 0; //Tracks question number
var selections = []; //Array containing user choices
var quiz = $('#quiz'); //Quiz div object

// Display initial question
displayNext();

// Click handler for the 'next' button
$('#next').on('click', function (e) {
e.preventDefault();

// Suspend click listener during fade animation
if(quiz.is(':animated')) {        
  return false;
}
choose();

// If no user selection, progress is stopped
if (isNaN(selections[questionCounter])) {
  alert('Please make a selection!');
} else {
  questionCounter++;
  displayNext();
}
});

// Click handler for the 'prev' button
$('#prev').on('click', function (e) {
e.preventDefault();

if(quiz.is(':animated')) {
  return false;
}
choose();
questionCounter--;
displayNext();
});

// Click handler for the 'Start Over' button
$('#start').on('click', function (e) {
e.preventDefault();

if(quiz.is(':animated')) {
  return false;
}
questionCounter = 0;
selections = [];
displayNext();
$('#start').hide();
});

 // Animates buttons on hover
 $('.button').on('mouseenter', function () {
 $(this).addClass('active');
 });
 $('.button').on('mouseleave', function () {
 $(this).removeClass('active');
 });

  // Creates and returns the div that contains the questions and 
  // the answer selections
  function createQuestionElement(index) {
  var qElement = $('<div>', {
  id: 'question'
  });

  var header = $('<h2>Question ' + (index + 1) + '</h2>');
  qElement.append(header);

  var question = $('<p>').append(questions[index].question);
  qElement.append(question);

  var radioButtons = createRadios(index);
  qElement.append(radioButtons);

  return qElement;
  }

  // Creates a list of the answer choices as radio inputs
  function createRadios(index) {
  var radioList = $('<ul>');
  var item;
  var input = '';
  for (var i = 0; i < questions[index].choices.length; i++) {
  item = $('<li>');
  input = '<input type="radio" name="answer" value=' + i + ' />';
  input += questions[index].choices[i];
  item.append(input);
  radioList.append(item);
   }
   return radioList;
   }

   // Reads the user selection and pushes the value to an array
   function choose() {
   selections[questionCounter] = +$('input[name="answer"]:checked').val();
   }

   // Displays next requested element
    function displayNext() {
    quiz.fadeOut(function() {
    $('#question').remove();

    if(questionCounter < questions.length){
    var nextQuestion = createQuestionElement(questionCounter);
    quiz.append(nextQuestion).fadeIn();
    if (!(isNaN(selections[questionCounter]))) {
     $('input[value='+selections[questionCounter]+']').prop('checked', true);
    }

    // Controls display of 'prev' button
    if(questionCounter === 1){
      $('#prev').show();
    } else if(questionCounter === 0){

      $('#prev').hide();
      $('#next').show();
    }
  }else {
    var scoreElem = displayScore();
    quiz.append(scoreElem).fadeIn();
    $('#next').hide();
    $('#prev').hide();
    $('#start').show();
  }
  });
  }

  // Computes score and returns a paragraph element to be displayed
  function displayScore() {
  var score = $('<p>',{id: 'question'});

  var numCorrect = 0;
  for (var i = 0; i < selections.length; i++) {
  if (selections[i] === questions[i].correctAnswer) {
    numCorrect++;
  }
}

score.append('You got ' + numCorrect + ' questions out of ' +
             questions.length + ' right!!!');
return score;
}
})();

HTML:

<div class="col-md-6" style="padding:10px;">
<h4 class="text-center lead" style="color:#333;font-size:28px;"> Relationship Test </h4>
<div class="test">
<a id="update" href="index.html" class="pull-right"><i style="color:#333;" class="glyphicon glyphicon-repeat glyphicon-repeat-animate"></i></a> 

<p id="quiz" class="lead quiz-1" style="color:#333;padding:20px;"> </p> 
</div>
 <div style="margin-top:5px;">

<a type="" id="next" href="#tellme" class="button btn btn-block testbuttons"  onclick="" >Next </a>
<a type="" id="prev" href="#tellme" class="button btn btn-block testbuttons"  onclick="" >Previous </a>
<a type="" id="start" href="#tellme" class="button btn btn-block testbuttons"  onclick="" >Start Over </a>
</div>
</div>
like image 490
Kerrial Beckett Newham Avatar asked Oct 19 '22 19:10

Kerrial Beckett Newham


1 Answers

Here is how your question's responses could have have "weight" in determining the final result on a range of 0-100 and what's in between:

var questions = [
    {
        question: "Question1",
        choices: [
                    "choice1",
                    "choice2",
                    "choice3"
                    ],
        weights: [10, 7, 3]
    },
    {
        question: "Question2",
        choices: [
                    "choice1",
                    "choice2",
                    "choice3"
                    ],
        weights: [3, 10, 7]
    },
    {
        question: "Question3",
        choices: [
                    "choice1":10,
                    "choice2":0,
                    "choice3":10
                    ],
        weights: [10, 0, 10]
    },
    {
        question: "Question4",
        choices: [
                    "choice1",
                    "choice2",
                    "choice3"
                    ],
        weights: [3, 10, 7]
    },
    {
        question: "Question5",
        choices: [
                    "choice1",
                    "choice2",
                    "choice3"
                    ],
        weights: [10, 3, 7]
    }
];

What I did is take the highest possible score, which is 100 and divide it by the number of question I'm giving, which is 5 in this case, then divide the 20 points per question unequally (and that's important) between the answers, giving more points to the "best" answer and less or 0 points to the "worst" answer.

Notice I always made sure all the points in any given question equal 20 so the that each question's choices will be "fair" in determining the score. I hope that solves the "no correct answer" part of your question.

UPDATE: I have updated the code to make it easier to process the answers.

In the "new" version, you have a "weights" array for each question, the weight numbers should correspond to each "choice" respectively. In your application, each question should be processed as such:

Fetch the "question" value and display it in an HTML tag. Get the choices from the "choices" array and display them inside an HTML select options tag, like this example:

<select id="response">
    <option value="10">Best answer</option>
    <option value="7">Moderate answer</option>
    <option value="3">Worst answer</option>
</select>

And the weight value should be in the value="x" of each option, just like the example above. You can use the each() function from jQuery (I assume you're using Bootstrap, so you already have it) to iterate through the questions.

Each questions "submit" button should call your choose() function, which should be updated to retrieve the value="x" value and add it to the selections[] array.

The, you should update the displayScore() function to just sum up the values from the selections[] array, in this way:

var total = 0;
for (var i = 0; i < selections.length; i++) {
    total += selections[i];
}

And compare the total variables to your result ranges (0-20, 21-40, 41-60, 61-80, 81-100) using if else if and for each if it should return the text "explanation" you want to give for the score, and probably the score itself.

Finally, you will just have to print the result of displayScore() using document.write() inside the HTML tag where you want to show the results the the user.

like image 93
Achraf Almouloudi Avatar answered Nov 15 '22 02:11

Achraf Almouloudi