Revamping old quiz code - looking for suggestions (Javascript/HTML)

This is a discussion on Revamping old quiz code - looking for suggestions (Javascript/HTML) within the Tech Board forums, part of the Community Boards category; I've been having some fun revamping some old code for a quiz I made some years ago. Essentially, it's just ...

  1. #1
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,171

    Revamping old quiz code - looking for suggestions (Javascript/HTML)

    I've been having some fun revamping some old code for a quiz I made some years ago. Essentially, it's just HTML and Javascript.
    The thing is that the code is quite the mess (hey, it was a lot of years ago I wrote that). To understand this, let's review what the code needs and how it works, and finally get to how to improve this.

    Essentially, the quiz works by having 40 questions, and randomly selecting a question each time the user answers one.

    Now, here is the tricky part. Some questions depend on others being answered correctly. So this added some extra complexity because a) we have to know when it is possible to randomly select a question that depends on another question (being answered correctly) and b) we must know when the user has answered all available questions (if the user incorrectly answers a question which have dependent questions, they should be marked as failed).
    This was very messy implemented (and I don't really know if it actually works reliably).
    I used an array that kept track of which questions had been answered. Questions that were off-limit were marked as "answered," so that the quiz wouldn't randomly select them when the prerequisite questions had not yet been answered.
    When a question was answered, a hard-coded check was made to see if answering that question opened up other questions, and if so, it marked those questions as not answered.

    But this approach is horrible since is requires modification in at least two places when adding new questions to the quiz or modifying questions.
    Furthermore, it doesn't actually take into consideration one of the requirements.

    I want to fix this. I am revamping the code in preparation for changing questions and adding new questions. The problem is how the new code should be structured to meet the requirements.

    So on to the requirements I have in mind:
    - I want to be able to add and modify questions in one place easily, without having to modify several places.
    - It should be easy, so that I don't forget to add valuable information.
    - The code must be able to handle that some questions require that other questions have been answered correctly before. That is to say, the code must not randomly pick such questions until all prerequisite questions have been answered correctly.
    - If all prerequisite questions for a specific question have been answered, but at least one prerequisite question incorrectly answered, then all the questions that depend on that prerequisite question being answered correctly must be marked as answered incorrect.
    - It must know when all accessible questions have been answered so it knows when the quiz has ended.

    I have experimented with a small approach, which is not good enough yet. But what I have in mind so far is something like one big array containing all necessary questions and information regarding those at the beginning, like so:

    Code:
    var Questions =
    [
    	{	// 34
    		title: "Varför gick Aleria med i klan 3?",
    		requirements: [ 33 ],
    		answered: false,
    		correct_answer: false,
    		answer: 12,
    		answers:
    		[
    			"Gillar att spionera",
    			"Gillar att lönnmörda",
    			"Blev tvingad",
    			"Gillar att spionera och lönnmörda",
    			"Blev tillbedd av Svarta Blomman",
    			"Blev tillbedd av någon annan",
    			"För att söka rätt på hot mot sig själv",
    			"För att söka rätt på och utrota hot mot sig själv",
    			"För att söka rätt på hot mot andra",
    			"För att söka rätt på och utrota hot mot andra",
    			"För att söka rätt på hot mot Svarta Blomman",
    			"För att söka rätt på och utrota hot mot Svarta Blomman"
    		]
    	},
    	...
    ];
    Information so far would be the title of the question, what prerequisite questions there are, if it has been answered (and correctly answered), the correct answer and the answer options.

    As for picking a question to show, I use this:
    Code:
    for (;;)
    {
    	var rnd = Math.floor(Math.random() * max_q);
    	if (rnd >= max_q)
    		continue;
    	var _q = Questions[rnd];
    	if (_q.answered)
    		continue;
    
    	var cont = true;
    	for (var i = 0; i < _q.requirements.length; i++)
    	{
    		if (!Questions[_q.requirements[i]].correct_answer)
    		{
    			cont = false;
    			break;
    		}
    	}
    
    	if (!cont)
    		continue;
    
    	q = rnd;
    	var html = "<h1>Fråga nr " + num_q + "!</h1>" + _q.title + "<hr/><br/>";
    	for (var i = 0; i < _q.answers.length; i++)
    		html += (i + 1) + ")  <a href='javascript:Answer(" + (i + 1) + ");'>" + _q.answers[i] + "</a><br/>";
    
    	document.getElementById("main").innerHTML = html;
    	break;
    }
    This is fine. This works, and it's clean.
    These code snippets take care of requirements 1, 2 and 3. Whether it could be done better is arguable, and I'm open to suggestions.
    But I need a good way to implement requirements 4 & 5. So that's where I'm looking for suggestions.

    So, thanks for not getting bored reading through this long post, and I hope someone can offer any good ideas.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.
    For information on how to enable C++11 on your compiler, look here.
    よく聞くがいい!私は天才だからね! ^_^

  2. #2
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,171
    No interest, eh? Or is it too early in the morning?
    After having slept a little on it, the best design I could come up with was the following:

    When searching for the next question, I maintain an array of possible new questions:

    Code:
    for (;;)
    {
    	var rnd = Math.floor(Math.random() * g_PossibleQuestions.length);
    	if (rnd >= g_PossibleQuestions.length)
    		continue;
    						
    	var CurrentQ = g_PossibleQuestions[rnd];
    	if (CurrentQ.answered)
    		continue;
    	if (!PrerequisitesOK(CurrentQ))
    		continue;
    
    	g_CurrentQ = rnd;
    	var html = "<h1>Fråga nr " + num_q + "!</h1>" + CurrentQ.title + "<hr/><br/>";
    	for (var i = 0; i < CurrentQ.answers.length; i++)
    		html += (i + 1) + ")  <a href='javascript:Answer(" + (i + 1) + ");'>" + CurrentQ.answers[i] + "</a><br/>";
    	break;
    }
    To maintain this list, I iterate the questions and build new data, and pick questions that have no prerequisites and put them into the the g_PossibleQuestions array:

    Code:
    for (var i = 0; i < g_Questions.length; i++)
    {
    	var SourceQ = g_Questions[i];
    	SourceQ.answered = false;
    	SourceQ.correct_answer = false;
    	if (SourceQ.requirements == undefined)
    	{
    		g_PossibleQuestions.push(SourceQ);
    		continue;
    	}
    
    	for (var j = 0; j < g_Questions[i].requirements.length; j++)
    	{
    		var TargetQ = g_Questions[SourceQ.requirements[j] - 1];
    		SourceQ.requirements[j] = TargetQ;
    		if (TargetQ.possible_paths == undefined)
    			TargetQ.possible_paths = [];
    		TargetQ.possible_paths.push(SourceQ);
    	}
    }
    And if they do have requirements, I put a reference from the prerequisite to the question it could possibly unlock (possible_paths).

    And finally, when answering a question, I check possible_paths to see if a new questions can be unlocked. If so, we add them to the array of possible questions. The answered question is removed.

    Code:
    var ThisQ = g_PossibleQuestions[g_CurrentQ];
    ThisQ.answered = true;
    var CorrectAnswer = (uanswer == ThisQ.answer);
    
    if (CorrectAnswer)
    {
    	score++;
    	ThisQ.correct_answer = true;
    }
    else
    	ThisQ.correct_answer = false;
    
    if (ThisQ.possible_paths)
    {
    	for (var i = 0; i < ThisQ.possible_paths.length; i++)
    	{
    		var FutureQ = ThisQ.possible_paths[i];
    		if (CorrectAnswer)
    		{
    			if (PrerequisitesOK(FutureQ))
    				g_PossibleQuestions.push(FutureQ);
    		}
    		else
    		{
    			if (FutureQ.processed == undefined)
    			{
    				g_FailedQs++;
    				FutureQ.processed = true;
    			}
    		}
    	}
    }
    
    g_PossibleQuestions.splice(g_CurrentQ, 1);
    I also keep track of how many right questions have been answered so far (score). To make it more interesting, I keep track of how many failed questions there are due to incorrectly answering prerequisite questions (g_FailedQs). I tag questions processed by adding processed = true since a question may have multiple prerequisites and we should only count it once.

    Is it optimal? I don't know.
    Does it work? Yes.
    It is easy to maintain and work with? Yes.
    It is a clean and nice solution? Yes, I would think so.

    Oh, and the PrerequisitesOK function:
    Code:
    function PrerequisitesOK(Question)
    {
    	if (Question.requirements == undefined)
    		return true;
    	for (var i = 0; i < Question.requirements.length; i++)
    	{
    		if (!Question.requirements[i].correct_answer)
    			return false;
    	}
    	return true;
    }
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.
    For information on how to enable C++11 on your compiler, look here.
    よく聞くがいい!私は天才だからね! ^_^

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Javascript and HTML forum
    By xniinja in forum General Discussions
    Replies: 4
    Last Post: 01-12-2011, 08:48 PM
  2. Simple JavaScript Code Issue
    By clegs in forum Tech Board
    Replies: 8
    Last Post: 07-14-2008, 03:11 AM
  3. HTML/Javascript Getting by certain code?
    By two31d in forum Tech Board
    Replies: 4
    Last Post: 11-08-2005, 07:10 AM
  4. help with this short code on my quiz..
    By vtlo99 in forum C++ Programming
    Replies: 2
    Last Post: 03-01-2002, 07:17 AM
  5. one more code on quiz....
    By vtlo99 in forum C++ Programming
    Replies: 1
    Last Post: 02-28-2002, 10:51 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21