We help IT Professionals succeed at work.

How to write an online quiz?

on
Hello, I am needing some inspiration on how to go about writing a quiz.  Since my quiz is in a form I am supposing that I will need to use php, which I am familiar with.  Or maybe javascript?  You can see the demo of my quiz here:

http://mydreamlayout.com/color_quiz.html

Basically, its a personality quiz.  And the answers the person gives dictates which color will be chosen.  Whatever that person clicks the most of in one category, that color will be chosen.  Once the submit button is clicked it will go to the next page, which would display the person's results.  I will have all of the answer ready for whatever one matches best which answers the person chooses.  The problem for me is how to get it to only display one result on the next page?  And how do I get the form to determine the result?  It would be which ever one got the most hits, but how to tell a form that? If anyone has any advice I could really use the insight!!
Comment
Watch Question

View Solutions Only

Top Expert 2015

Commented:
Obviously it does not really matter what color the quiz produces as long as it produces consistant results based on the choices made. I'm assuming you don't want to pass judgement on users by assigning dark ugly colors to attributes you deem undesirable or vice versa.
Here's how I would approach it. Divide the choices into three groups at random. If you have 75 total choices then there are 25 in each group. For each choice assign a random number between 0 and 255. When the user clicks submit, add the values submitted, keeping the three totals from the three groups separate. Divide each total by the number of choices made in that group. Now you are left with three numbers, each between 0 and 255. Use those three numbers to create an rgb value and that's the color your soul is painted. To avoid the possibility of pure white or pure black, limit your number assignments to something other than 0 to 255 like 50 to 200.
Top Expert 2015

Commented:
...If you want to produce only vivid colors, avoiding browns and grays and pale colors, assign only numbers between say 0 and 75. Divide the three separate totals by the number of choices in each group, same as before, but then add say 150 to the group with the most choices. That way, your result will be an rgb value with two low numbers and one high number which will produce a more vivid color from one of the three color groups (red, green, blue).

Commented:
Well, I am doing all of the colors, including black, brown, and gray, but that doesn't matter.  I am not understanding about dividing and random numbers.  And no ugly colors for bad personalities :)  All of the colors mean something good.  The results will be displayed with a pictures of that color and the definition of that color.  It would possibly display like a div with an image inside and words underneath.

There are 10 different possibilities, 10 different color results that is.  But only one of them would appear on the next page, because out of all the answers chosen they matched that result the most.  What I am curious about is how to tell the form that there are 10 separate categories and all of the answers for each question must fall into one category and the category with the most hits will display on the next page.  I cannot even think of a way to go about writing the code for this.  I am sure its very simple I am just making it hard, but I'm stuck.  Can this all be done with just html and php?  would javascript be better?  I am familiar with both, use them in my websites, but I am by no means an expert yet.
Top Expert 2015

Commented:
If there are only 10 possibilities you could do this all with Javascript just by loading an array with ten HEX values or by assigning them to ten variables. If the descriptions are long you could pull them from a flat file with PHP based on the resulting color.
As far as determining the resulting color, you will have to pre-determine which choices produce which colors. You simply assign one of the ten colors to each of the 75 choices. The most choices selected for any one of the ten colors and that's the color your soul is painted. Pity the fool who's soul turns out to be painted black!
Since there are only ten possibilities and you are pre-determining what the colors mean, you have greatly simplified the job of determining the final color. That leaves you to concentrate on the presentation. Personally, I would use only vivid colors and I would present the results in some dynamic way to make getting to the result more fun for the user. How about on the results page you have an eye with the pupil and iris in the resulting color. Or, maybe you incorporate the top three results with number one as the most prominent (attached image).
Have some fun with it and make it fun for users! By the way, you should indicate somewhere on the quiz that the user can make multiple selections for each question. It was not immediately apparent to me when I tried it.
Eye.jpg

Commented:
Here you can see which answers go with which colors:  http://mydreamlayout.com/color_quiz.html
And here you can view a sample of what I want the results to look like:  http://mydreamlayout.com/color_results.php

The first question throws things off because more than one color falls under the elments.  How would using an array help determine which color gets choosen?  I am familiar with javascript and php, but I am not very good at them. . .
Top Expert 2015

Commented:
I don't think it matters if some selections have more than one color associated with them. When you loop through your radio buttons to see which are selected and you come to Fire, Water, Air, or Earth, simply add 1 to each of the colors that are associated with that item. I don't think an array will help here except maybe to hold your color variables. You just create a variable for each of your colors and increment the appropriate color variable by 1 each time a selection calls for that color. Then determine which color variable has the highest value and that's THE color.

Commented:
Alright, well I know how to create variables, so I can assign a result to each color.  How do I increment the variables by one?  They would gain a point each time a radio button is clicked, but I mean I wouldnt do a seperate onclick function for every button right?
Top Expert 2015
Commented:
You don't need a separate onClick for each radio button.
Copy the code below to a new page, run it and click some radio buttons and then click the test button.
``````<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Color Quiz</title>

</head>

<body>
<form id="colorForm" method="post">
<input type="button" value="Test" onclick="javascript:DisplayFormValues();" />
<br />
<input type="radio" value="0~1" />
Fire (red, orange)<br />
<input type="radio" value="3~4" />
Water (blue, gray)<br />
<input type="radio" value="2~5" />
Air (yellow, pink)<br />
<input type="radio" value="9~7~8~6" />
Earth
(purple, green, brown, black)<br />
<input type="radio" value="5" />
Successful (pink)<br />
<input type="radio" value="7" />
Lucky (green)<br />
<input type="radio" value="0" />
Passionate (red)<br />
<input type="radio" value="9" />
Perplexing (purple)<br />
<input type="radio" value="1" />
Changing (orange)<br />
<input type="radio" value="6" />
Mysterious (black)<br />
<input type="radio" value="8" />
Impoverished (brown)<br />
<input type="radio" value="2" />
Hopeful (yellow)<br />
<input type="radio" value="4" />
Modest
(grey)
</form>
<hr />
<div id="lblValues">
</div>
<script language="javascript" type="text/javascript">
function DisplayFormValues() {
var str = '';
var red=0, orange=0, yellow=0, blue=0, grey=0, pink=0, black=0, green=0, brown=0, purple=0;
var colors = new Array(red, orange, yellow, blue, grey, pink, black, green, brown, purple);
var colorNames = new Array("red","orange","yellow","blue","grey","pink","black","green","brown","purple")
var elem = document.getElementById('colorForm').elements;
for(var i = 0; i < elem.length; i++) {
if (elem[i].type == "radio") {
if (elem[i].checked) {
var radioValue = elem[i].value
if (radioValue.indexOf('~') != -1) {
var valueArray = radioValue.split('~');
for(var j = 0; j < valueArray.length; j++) {
colors[parseInt(valueArray[j])] ++;
}
} else {
colors[parseInt(radioValue)] ++;
}
}
}
}
for (i = 0; i < colors.length; i++) {
str += colorNames[i] + " value = " + colors[i] + "<br />";
}
document.getElementById('lblValues').innerHTML = str;
}
</script>
</body>
</html>
``````
Most Valuable Expert 2011
Top Expert 2016

Commented:
If you want the information from your quiz to be "stateful" - that is, to survive from one page load to the next or to survive from one client to the next, you probably want to use a data base to record the choices.  You can do this with the \$_SESSION array but it will only persist as long as a PHP session remains alive.

Javascript validation is really just a convenience for the client.  As you are probably aware, clients can have JS turned off, and hackers can bypass JS entirely, sending malicious strings and arrays into your script.  So whatever "validation" you may do with the client-side processing must be re-done in the server after the forms are submitted.  There is no way around this if you want a dependable application.

Here is a good book to help you get a foundation in PHP and MySQL (the most popular data base for keeping data like this):
http://www.sitepoint.com/books/phpmysql4/

In a moment I will post a script that shows you how to use the PHP session handler to keep count of radio buttons.  Extending this to the data base model is not hard.  Hopefully the design pattern will be useful to you.

Best regards, ~Ray
Most Valuable Expert 2011
Top Expert 2016

Commented:
Try running this script so you can see the moving parts, then please post back with any questions.  HTH, ~Ray
``````<?php // RAY_radio_button_counter.php
error_reporting(E_ALL);

// ALWAYS START THE SESSION ON EVERY PAGE
session_start();

// MAKE IT EASY TO READ
echo "<pre>" . PHP_EOL;

// INITIALIZATION VALUES FOR THE SESSION - SET EMPTY COUNTERS TO ZERO
if (!isset(\$_SESSION["r"])) \$_SESSION["r"] = 0;
if (!isset(\$_SESSION["g"])) \$_SESSION["g"] = 0;
if (!isset(\$_SESSION["b"])) \$_SESSION["b"] = 0;

// HAS ANYTHING BEEN POSTED?
if (!empty(\$_GET))
{
// INCREMENT THE COUNTERS FOR THE INFORMATION THAT HAS BEEN POSTED
if (!empty(\$_GET["r"])) \$_SESSION["r"]++;
if (!empty(\$_GET["g"])) \$_SESSION["g"]++;
if (!empty(\$_GET["b"])) \$_SESSION["b"]++;
}

// REPORT THE INFORMATION ABOUT OUR CURRENT COUNTS
echo PHP_EOL . \$_SESSION["r"] . " RED";
echo PHP_EOL . \$_SESSION["g"] . " GREEN";
echo PHP_EOL . \$_SESSION["b"] . " BLUE";

// END OF PHP - PUT UP THE 'GET' FORM TO COLLECT RADIO BUTTON INPUT
?>
<form>
CHOOSE A COLOR:
<input type="radio" name="r" /> RED
<input type="radio" name="g" /> GREEN
<input type="radio" name="b" /> BLUE
<input type="submit" value="GO!" />
</form>
``````

Commented:
Ray I put it on here:  http://mydreamlayout.com/color_example.php
But I am less familiar with php so I was not sure how to incorporate into my quiz yet.  Thanks for the recommendation of the book, I will be sure to read it.

TommyBoy I put what you did with javascript into my quiz:  http://mydreamlayout.com/color_quiz.html
Now that the counter works, how do I make it tell the form which result to display?

Top Expert 2015
Commented:
First, find the highest color value (see example javascript).
For displaying the proper result, the easy way would be to create a webpage for each color result. Then redirect the quiz page to the proper result page with window.location (see example).
Alternately, you could always direct to the same results page but add a querystring to the url to instruct some PHP code as to what images and descriptions to return with the results page. The URL with query would look something like this: http://www.mydreamlayout.com?color=pink
There's one thing you have not addresses yet. What to do in the event of a tie for first.
``````var highest = 0;
var highestName = '';
for (x = 0; x < colors.length; x++) {
if (colors[x] > highest) {
highest = colors[x];
highestName = colorNames[x];
}
}
window.location = "http://www.mydreamlayout.com/" + highestName + ".htm";
``````
Most Valuable Expert 2011
Top Expert 2016

Commented:
Looks like the script you installed is not the same as the one I posted - when I ran it, I saw this warning message.

Warning: session_start() [function.session-start]: Cannot send session cookie - headers already sent...

It means that you have some kind of HTML output before the session_start() command (Line 5 in my script).  That is not allowed - the session handler sends cookies, and cookies are part of the HTTP header.  All headers must precede any browser output - that is a law of the WWW - so you must fix that.  Perhaps the easiest way to fix it would be to install the script the way I posted it, without any modification.  I tested it before I posted it and it works correctly.

I looked at your online quiz page posted above.  Here is a sample of what I found:

<input type="radio" value="5" />

That kind of HTML statement is completely useless ;-)  It has no "name" attribute so there is no way to know whether or what the client checked!  Here is another little script that will show you what the relationship is between the HTML form and the PHP superglobal array \$_POST.  Try running it and you can see what comes through from the form into your script.

At this point I would recommend that you look for some classes in HTML, just to get a feel for what the language needs.  There are plenty of online learning resources too, but a classroom setting might get you up to speed faster.  Best regards, ~Ray

I think you have a lot of "moving parts" when you start trying to program an online quiz, but I am confident that the SitePoint book can be a help.

``````<?php // RAY_temp_post.php
error_reporting(E_ALL);
echo "<pre>" . PHP_EOL;

// SHOW THE POST ARRAY
ECHO "POSTED DATA FOLLOWS: ";
var_dump(\$_POST);

// END OF PHP - PUT UP THE FORM
?>
<form method="post">
TEXT INPUT (TYPE SOMETHING)
<input type="text" name="myText" />

RADIO INPUT (CLICK ONE)
<input type="radio" name="myRadio" value="FOO" />FOO
<input type="radio" name="myRadio" value="BAR" />BAR

NAMELESS RADIO INPUT (CLICK ONE OR BOTH - NOTHING WILL HAPPEN)
<input type="radio" value="BIG" />BIG
<input type="radio" value="DOG" />DOG

NAMELESS SUBMIT BUTTON
<input type="submit" />

A SUBMIT BUTTON NAMED FRED
<input type="submit" name="fred" value="Go!" />
</form>
``````
Top Expert 2015

Commented:
@Ray
The author is just experimenting with html and javascript. I say, better to complete something even if imperfect and move on to bigger challenges than to get bogged down in the details of a more advanced web technology and become overwhelmed. I don't know about you, but I did not attempt PHP until my fifth or sixth website design. First I tried Java, then Perl, then PHP. I abandoned all that for asp.net as of late.

>><input type="radio" value="5" />

That kind of HTML statement is completely useless ;-)  It has no "name" attribute so there is no way to know whether or what the client checked!<<

In this case, it's not necessary to know what radio button was checked, only that it was checked. We are looping through all of them. The value of the radio button is the only information the author needs to complete the calculation. That part works just fine.
Most Valuable Expert 2011
Top Expert 2016

Commented:
@tommyBoy: Agree about iterative learning, for sure.  I do not think PHP is very advanced or detailed (Rasmus Lerdorf once described it as a programming language his grandmother could use), certainly not when compared to JavaScript, but to each his own.  JavaScript is great for client-side activity, but it is inadequate for any kind of data validation or security -- that work has to come on the server after the form has been submitted.

As to the point about the nameless input tags, I am just guessing that our asker might one day want to store this information on the server (PHP is good for that), perhaps in a data base (maybe MySQL or PostGreSQL).  If that is EVER to be the case, we need to have name attributes on the input tags.  If that is never to be the case then I am missing the point of an online quiz.  In any case, I do not know of a "best practices" approach that would omit the names from HTML inputs so it seems best to begin coding on the right foot, so to speak.

Online contests, quizzes and rankings are fairly well documented in the technical literature, and the code necessary to produce anything meaningful, while simple in the broad concepts, has a lot of detailed advanced concepts related to sorting and summing, etc.  Your point about how to handle a "tie" for any place is one good example.  What if a client does not answer part of the question set?  Are the other answers valid?  Questions like these keep IT architects up at night ;-)  For someone learning HTML and server-side actions it might be simpler to start with a content management system.

Best to all, ~Ray

Commented:
I think I may have to make the questions odd to make sure there is not a tie.  Since I have an even amount right now that kind of ruins things.  lol

I dont know why I find javascript easier than php, since every where online people seem to think php is easier and better.  I like web design alot though, so I am going to go back to school to take classes this fall :)  But until then I am practicing.  I am only good at html and css so far.

Ok TommyBoy, well I added the extra javascript:  http://mydreamlayout.com/color_quiz.html
but when I hit submit it only returns the quiz itself.  I created a blue result, and hit all of the blue answers to try and get it to display the blue result page.  Do you know how to get it to return the webpage??

Ray, I put your code here: http://mydreamlayout.com/color_example.php
I see it works right, but as I'm not so good with php I dont know what else to do with it  :P

Top Expert 2015
Commented:
Easy. You are calling DisplayResult from the button click so the DisplayFormValues never gets called which means highestName is an empty string. Put DisplayFormValues back in the onClick for the button and modify the bottom part of the DisplayFormValues function as follows:

//for (i = 0; i < colors.length; i++) {
//str += colorNames[i] + " value = " + colors[i] + "<br />";
//}
//document.getElementById('lblValues').innerHTML = str;
DisplayResult();

I added a "DisplayResult()" call to the end and commented out the lines that display the results to the screen. They were just for the demo. You can remove those lines.
Top Expert 2015

Commented:
As for dealing with a tie, making the selections an odd number will not prevent a tie. Even if there is a tie, a final color will still be chosen. The DisplayResults function will simply assign "highest" to the first color it finds in the array with the highest value even if there are others with the same value. So, you really don't have to worry about it except it will likely always be colors at the beginning of the array that get assigned to "highest". If you want to get creative, you could have a tie breaker question pop up in the event of a tie. Or, just have the javascript pick a winner at random from all the colors with the same high value. That gives all the colors a fair chance at number one. To make that work you would collect all the tied values in a new array and have the script pick a random number from 0 to the newArray.length - 1 to determine the winner.
Top Expert 2015

Commented:
By the way: This URL failed, http://mydreamlayout.com/blue.htm.
I see you have a blue.html though, so you will need to add the "L" at the end of the window.location URL in the js file.

Commented:
Ok I replaced the javascript and added an L at the end of .htm  but it is still not working:
http://mydreamlayout.com/color_quiz.html

well everything works, except for it does not go to the blue result page.  I do not know what I will do in case of a tie.  I would like the question to be added which color does the person like best between the two colors, but I do not know how to do that.
Top Expert 2015

Commented:
A few of things to correct to get this working.
1. When you separated the task of finding the highest value into it's own function, variables that only the DisplayFormValues function was aware of were being used namely the colors and colorNames arrays. I moved those variables outside of the DisplayFormValues function so they became available to both functions.
2. At some point, the colors names in the colorNames array got shuffled. They need to be in the exact same order of the colors array or the wrong color name gets returned. That drove me nuts until I discovered the problem. Also missing a semi-colon at the end of that line.
3. This line of code:      var elem = document.getElementById('colors').elements;
was not working because the form tag had a name but not an id. Form tags also need an action. Change your form tag to <form id="colors" action="#">. The name tag is obsolete.

As for the tie problem, I think you are losing some of the mystical nature of the quiz if you ask the user what color they like between the two colors. Why not just short circuit the whole quiz and ask them what their favorite color is at the start and redirect to the page with that color. See what I'm saying? In fact, I think you should take the color names in parenthesis off the quiz. With the names displayed, it's easy to surmise what color will come out on top. It would be more fun if it looked like some mystical calculation was going on to determine the color based on the answers. To break a tie, my vote is for letting the script pick from the tieing colors at random. It's no less scientific than the rest of the quiz.
``````// JavaScript Document

var red=0, purple=0, blue=0, green=0, pink=0, orange=0, black=0, yellow=0, brown=0, grey=0;
var colors = new Array(red, purple, blue, green, pink, orange, black, yellow, brown, grey);
var colorNames = new Array("red","purple","blue","green","pink","orange","black","yellow","brown","grey");

function DisplayFormValues() {
var elem = document.getElementById('colors').elements;
for(var i = 0; i < elem.length; i++) {
if (elem[i].type == "radio") {
if (elem[i].checked) {
var radioValue = elem[i].value
if (radioValue.indexOf('~') != -1) {
var valueArray = radioValue.split('~');
for(var j = 0; j < valueArray.length; j++) {
colors[parseInt(valueArray[j])] ++;
}
} else {
colors[parseInt(radioValue)] ++;
}
}
}
}
DisplayResult();
}

function DisplayResult() {
var highest = 0;
var highestName = '';
for (x = 0; x < colors.length; x++) {
if (colors[x] > highest) {
highest = colors[x];
highestName = colorNames[x];
}
}
window.location = "http://www.mydreamlayout.com/" + highestName + ".html";
}
``````

Commented:
Oh, I changed everything but I still cant get it to work!  I am going to remove the colors right next to the answers, once I am finished! It was to remind me which ones belonged with which colors.
Top Expert 2015

Commented:
Works fine locally as is. The problems now are with the redirect. Since the blue.html file is in the same directory, try changing your window.location line to a relative path:

window.location.href = "./" + highestName + ".html";

This worked for me in Firefox but not in IE8. (Welcome to the web developer's nightmare--cross browser compatibility.) You are also up against the limits of javascript. As a result of abuse, newer browsers have features that prevent redirecting with javascript. Maybe it's time for a new question thread to get around the redirect problem?

Commented:
Ok, I will start a new thread for the redirect problem.  Make sure to look for it!  :)

Commented:
Thanks!