Link to home
Start Free TrialLog in
Avatar of kate2001
kate2001

asked on

Online question and grading using php and mysql

I have a randomly generated question from 4 different question tables. Here is want I want:

1.  I want to make the generated question available for the users so that they can answer the question.
2. As they work on each questions, I want to compair the users answer with the stored correct answer
3. According to the user answer, for each question I want to calculate the mark/weight of each question, add the total grade and store the total in the Grade Table according to their ID/Name.

E.g User 1: Total grade 89  out of 100
      user 2: Total grade 100 out of 100

4. Also, I want to make all the above activity applied for every randomly generated question.
Information: At a time, a minimum of 10 question can be generated. So that means, for a one time generated question, the user will be asked to work on 10 questions.

Is it possible to implement the above with out storing the generated questions back in another table and retrive them back and allow user to work on the question? If yes how? If not how do you think it will be possible?

I greatly appreciate your help
Thank you in advance.
Avatar of amrish80
amrish80
Flag of India image

yes store ur grading system in SESSIONS and user Details as well. this will help u out.
Avatar of kate2001
kate2001

ASKER

Oh, Thank you. But how? Would you pls give me one example?
ASKER CERTIFIED SOLUTION
Avatar of Member_2_248744
Member_2_248744
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Just curious - have you tried anything yet?  If so, please post the code that you tried so we can see what progress has been made so far.  Also, can you please tell us if this is a school assignment?  It sounds extremely "academic" in its current description, so if you can give us some more concrete information about the application requirements, we might be able to help more, or point you toward a quiz generator.

Thanks and regards, ~Ray
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thank you all for your comment,

I have been asked to randomly generate a number of questions from diffrent question type database which I successfully did. But now I want to continue so that I can grade different users responds.  Once the question is generated and posted I want to track users respond and grade them by compairing their answer with the correct answer which is stored in my question table.

Here is what I have till now.

//Generate true false questions randomly

 $sql1 = "SELECT * FROM truefalsequestions where Course_ID = $courseID AND Chapter_No = $chapter_No ORDER BY RAND() LIMIT $truefalse";
      $result1 = mysql_query($sql1);

// Count and compare the number of questions in the database
       
        $res1 = mysql_query("SELECT * FROM truefalsequestions where Course_ID = $courseID AND Chapter_No = $chapter_No");
        $num_rows1 = mysql_num_rows($res1);
       
        if ($truefalse != 0)
        {
        if ($truefalse > $num_rows1 )
        {
           echo "<p> Number of requested True/False questions are greater than the number of quesion in the database for the selected Course.</p>";
           echo " <p>Please create enough pool of True/False quesion first.</p>";
        }
        else if ($num_rows1 >= $truefalse)
        {
        echo "<br><b>INSTRUCTION: Select True or False Option Buttons For the Following True/False Questions.</b><br>";
        $tfquestnumber = 1;        
        while($row = mysql_fetch_object($result1))
      {
            $Quest_No = $row->Quest_No;
            $Course_ID = $row->Course_ID;
            $TF_Answer1 = $row->TF_Answer1;
            $TF_Answer2 = $row->TF_Answer2;
            $TF_Correct_Answer = $row->TF_Correct_Answer;
            $Question_Description = $row->Quest_Description;
           
            //calculate question Number
               
            echo "$tfquestnumber" . ". ";
            echo"$Question_Description";
          echo "<br>";
          echo "<input type='radio' value='false' name='truefalse'>False<br />";
          echo "<input type='radio' value='true' name='truefalse'>True<br />";
            $tfquestnumber = $tfquestnumber + 1;
          }
   }
}
      // Generate question button goes here
I get crossed Eyed, , I started to do some code to try and get some results that might do for an online true false test. The more I tried to get a fairly correct set up and display for a student test, things got more and more complex. I did this code below, not so much from your guidelines, but just from my opinion of how a 10 answer quiz should be displayed as the graded result. For this I need a database table that has the Course ID and all of the students in all of the Courses, I named the table 'studentScores' as

 TABLE.`studentScores`
`id` INT AUTO_INCREMENT PRIMARY KEY
`Course_ID` INT
`StudentID` VARCHAR(32)
`Name` VARCHAR(48)
`total` MEDIUMINT
`AnswerID` MEDIUMINT
`answerList` VARCHAR(255)
`answers` INT
INDEX (`Course_ID`,`AnswerID`,`StudentID`)

I am afraid that you may not be able follow all of the stuff I did to get this to work, and have a display for the quiz result.
I did not use a session store for the data, I do not like and do not trust the session storage very much, although It works mostly.
I store ALL of the Data I need to compare the answers in the studentScores table.

Take a look at the code, and try it, if you are able to set up your data base for the fields I use.
This is NOT a finished version, but It does a passing grade to test the answers and display an informative result.
<html><head><title>Student Quiz</title><style type="text/css">.rd{color:#b00;}</style></head><body BGCOLOR="#E3F7FF"><h2>Student Quiz for 10 True-False Questions</h2>
<p>
<?php
$host = 'localhost'; $user = 'lost'; $pass = 'password'; $dbname = 'testing1';

//get all of the radios into an array
$tf= array();
$tf[] = (isset($_POST['truefalse0'])) ? (int)$_POST['truefalse0'] : -2;
$tf[] = (isset($_POST['truefalse1'])) ? (int)$_POST['truefalse1'] : -2;
$tf[] = (isset($_POST['truefalse2'])) ? (int)$_POST['truefalse2'] : -2;
$tf[] = (isset($_POST['truefalse3'])) ? (int)$_POST['truefalse3'] : -2;
$tf[] = (isset($_POST['truefalse4'])) ? (int)$_POST['truefalse4'] : -2;
$tf[] = (isset($_POST['truefalse5'])) ? (int)$_POST['truefalse5'] : -2;
$tf[] = (isset($_POST['truefalse6'])) ? (int)$_POST['truefalse6'] : -2;
$tf[] = (isset($_POST['truefalse7'])) ? (int)$_POST['truefalse7'] : -2;
$tf[] = (isset($_POST['truefalse8'])) ? (int)$_POST['truefalse8'] : -2;
$tf[] = (isset($_POST['truefalse9'])) ? (int)$_POST['truefalse9'] : -2;
$answID = (empty($_POST['AnswerID'])) ? 0 : (int)$_POST['AnswerID'];
// WARNING, I use my own selectors here with AnswerID StudentID courseID and chapterNum
$StudentID = (empty($_POST['StudentID'])) ? '|' : $_POST['StudentID'];
$courseID = (empty($_POST['courseID'])) ? 0 : (int)$_POST['courseID'];
$chapter_No = (empty($_POST['chapterNum'])) ? 0 : (int)$_POST['chapterNum'];

// test to see if there were answers Posted
if (($tf[0] > -1) && ($courseID > 0)) { //echo 'tf0 '.$tf[0].' tf1 '.$tf[1].' tf2 '.$tf[2].' tf3 '.$tf[3].' tf4 '.$tf[4].'<br />';
	$dbr = mysql_connect($host, $user, $pass);
	if (mysql_select_db($dbname,$dbr)) {
		$StudentID = mysql_real_escape_string($StudentID);
	// get the data you need to test the answers - answerList,AnswerID,answers
		$query = "SELECT answerList,AnswerID,answers FROM studentScores WHERE StudentID='$StudentID' AND Course_ID=$courseID AND AnswerID=$answID";
		$result = mysql_query($query);
		if ($result) {
			$row = mysql_fetch_object($result);// there should be ONLY one row, only ONE StudentID per Course_ID
			echo 'answers '.$row->answers.' AnswerID '.$row->AnswerID.' answerList '.$row->answerList.'<br />';
			$aryList = explode(',',$row->answerList);//implode($aryQues,',')
			$Correct = 0;//$answerBits += ($row->CorrectAnswer << $tfquestnumber);
	// do a bit wize test for the answers given and the correct answers
		for ($i = 0; $i < 10; $i++) {if (((($row->answers & (1 << $i)) > 0)) == $tf[$i])
			{$tf[$i] = 'Correct'; ++$Correct;} else $tf[$i] = '<span class="rd">Wrong</span>';}
		//for ($i = 0; $i < 10; $i++) echo $i.' '.$tf[$i].'<br />';
		$Correct *= 10;
		echo 'Quize Grade = '.$Correct.'%<br />';//' list len '.count($aryList).
		$courseID = 5432;
		// get the List of Descriptions to display to tell student their results
		$query = "SELECT NumID,CorrectAnswer,Description FROM questions_tf WHERE courseID = $courseID AND NumChapter=$chapter_No AND NumID IN ($row->answerList)";
		$result = mysql_query($query);
		if ($result) {
			while($row = mysql_fetch_object($result))
				{
				//echo $row->NumID.'. '.$row->Description.'<br />';
				for ($i = 0; $i < 10; $i++) { // get the correct Description in the array by testing for ID
					$right = ($row->CorrectAnswer) ? 'True' : 'False';
					if ($aryList[$i] == $row->NumID) $aryList[$i]=$i.'. '.$row->Description.' - '.$right.', you were '.$tf[$i].'<br />';
					}//($row->CorrectAnswer) ? 'True' : 'False';
				}
			for ($i = 0; $i < 10; $i++) {
				echo $aryList[$i]; // display the students results
				}
			} else echo 'ERROR2 QUERY 3 SELECT '.mysql_error().'<br />';
			} else echo 'ERROR2 QUERY 2 SELECT '.mysql_error().'<br />';
		} else echo 'ERROR2 QUERY 1 SELECT '.mysql_error().'<br />';
echo '</body></html>';
exit;
}

$StudentID = 'jklmnopqr';
$dbr = mysql_connect($host, $user, $pass);
if (mysql_select_db($dbname,$dbr)) {
$truefalse = 10;
$courseID = 5432;
$chapter_No = 1;


$count = 0;
$result = mysql_query('SELECT COUNT(NumID) FROM questions_tf');
if ($result) {
	$row = mysql_fetch_row($result);
	$count = $row[0];
	echo 'Row count '.$count.'<br />';
	} else die('Incorrect Database access error 1234');
if ($truefalse > $count)// Count and compare the number of questions in the database
	{
	echo "<p> Number of requested True/False questions are greater than the number of quesion in the database for the selected Course.</p>";
	echo " <p>Please create enough pool of True/False quesion first.</p>";
	} else {
	$query = "SELECT * FROM questions_tf WHERE courseID = $courseID AND NumChapter = $chapter_No ORDER BY RAND() LIMIT $truefalse";
	$result = mysql_query($query);
	if ($result) {
		$aryQues = array();
		$answerBits = 0;// a bit container, has - 1,2,4,8,16,32,64,128,512,1024 as question IDs
        echo '<form name="cform" action="quiz1.php" method="post">Course ID '.$courseID;
		echo ' - <b>INSTRUCTION: Select True or False Option Buttons For the Following True/False Questions.</b><br />';
        $tfquestnumber = 0;        
        while($row = mysql_fetch_object($result))
		{
		$aryQues[] = $row->NumID;
		$answerBits += ($row->CorrectAnswer << $tfquestnumber);// add unique BIT values to your BIT container
//calculate question Number 
		echo ($tfquestnumber+1) . ". ";
		echo $row->Description.'<br />';
		// you MUST have a different name for each radio pair
		echo '<input type="radio" value="0" name="truefalse'.$tfquestnumber.'" />False<br />';
		echo '<input type="radio" value="1" name="truefalse'.$tfquestnumber.'" />True<br />';
		++$tfquestnumber;
		}
		$answerList = mysql_real_escape_string(implode($aryQues,','));
		//$answerList is stored to retrive the question for the studen to see their results
		
	$courseID=54321;
	// You MUST have some hidden inputs for the student and course information
	echo '<input type="hidden" name="StudentID" value="'.$StudentID.'" />';
	echo '<input type="hidden" name="courseID" value="'.$courseID.'" />';
	echo '<input type="hidden" name="chapterNum" value="'.$chapter_No.'" />';
// IMPORTANT, you will need to store the data nessary for answer comparison and display, UPDATE studentScores
	$query = "UPDATE studentScores SET answerList='$answerList',AnswerID=AnswerID+1,answers=$answerBits WHERE StudentID='$StudentID' AND Course_ID=$courseID";
	if (mysql_query($query)) {//echo 'GOOD UPDATE <br />'; 
	$query = "SELECT answerList,AnswerID,answers FROM studentScores WHERE StudentID='$StudentID' AND Course_ID=$courseID";
	$result = mysql_query($query);
	if ($result) {
	$row = mysql_fetch_object($result);
	//echo 'answers '.$row->answers.' AnswerID '.$row->AnswerID.' answerList '.$row->answerList; 
	echo '<input type="hidden" name="AnswerID" value="'.$row->AnswerID.'" /><br /><input type="submit" value="Score This Quiz" \></form>Num Questions '.$tfquestnumber.' answerBits '.$answerBits.'<br />'.$answerList;
	} else echo 'ERROR QUERY 3 SELECT '.mysql_error().'<br />';
	} else echo 'ERROR QUERY 2 SELECT '.mysql_error().'<br />';
	} else echo 'ERROR QUERY 1 SELECT '.mysql_error().'<br />';

}
}
?>
</body></html>

Open in new window

It seems like this pattern shown in the code snippet at ID: 31209509 would be easy enough to adapt so that it used a data base.  Lines 10 through 30 are the quiz definition.  The quiz has only three elements: the question, the right answer and the choices of the answers.  In a T/F quiz, the choices are not even needed, but leaving them in place makes the programming logically consistent for multiple choice quizzes.

What you would want to do with the quiz definition is create three tables in your data base.  You would load the tables with the three elements, and you would associate the tables with a common key in each of the tables.  So, for example, the "question" table row #3 matches the "answer" table row #3 and the "choices" table row #3.

If you wanted to do a random selection of some questions from the table, you might use an algorithm like this:

1. SELECT all of the keys in one of the tables (they have the same number of rows).
2. Create an array using the selected keys.
3. Use shuffle() to randomly order the array.
4. Use array_slice() to grab as many elements as you want questions on the quiz.
5. Iterate over the sliced array, choosing the questions based on the keys.

If you wanted to be able to delete and add questions, choices and answers, the table maintenance would be pretty simple - a form with three fields.  

It's a little work to code this, but it's a pretty straightforward design pattern.
Thank you all for your comment and my apprec

My code above (ID: 31228874) will automatically generate a number of random questions of type true/fales.And its out put looks like the following.

INSTRUCTION: Select True or False Option Buttons For the Following True/False Questions.
1. The symbol Sn represent  strontium.
False (with option button)
True (with option button)
2. Gallons  cannot be used to express the volume of gas that is delivered into a gas tank.
False (with option button)
True (with option button)
_________
 [my other part of the code also generate a question of type multiple choice and short answer.]

So now I have a number of true false question. After generating the questions I want to calculate the users grade and store  it to grade table.

Here is my question,

Should I have to create a table and  store the generated question? So that I can create a page with in which I can populate the generated question back again with additional " score it" button, "exam taker name and exam taker ID text boxes"?  And finally, accourding to the user response i.e respondant name and id, and answer for each question, I want to calculate their total grade and  store each respondant total grade in a grade table.

Or do you think part of the code which calculate the users grade  should be done with the same page (a page where I am generating random question(ID: 31228874) ). If that is the case, how do I know who is taking the exam.

What would you do to keep track of users answer once you generate random questions?

I am lost in here. I greatly appreciate if you could help me with this.

Thank you all

This is not really a question any more, so much as a need for application design and development help and for that you might want to hire a developer, since it looks like there are a lot of moving parts.  Here are some ideas that may be helpful.

If you are going to need to keep track of the students who take the quiz, you will need a secure login.  That part alone is a significant effort, unless you are already using a framework.  You can learn more about it here: https://www.experts-exchange.com/articles/Web_Development/Web_Languages-Standards/PHP/PHP-login-logout-and-easy-access-control.html

If you're going to allow students to retake the test, or parts of it, you need more tables that record the progress, the questions they already answered, etc.  It could become quite a large application!

Computing the grade is really very simple, whether the scores come from the online activity of a single page or from a data base table.  See line 60 - 63 at ID: 31209509.  Once you know the score, all you need to do is determine the cutoff for grades.  So if a 90% is the lowest 'A', you can compare the student score to 90 and if equal or greater, they got 'A', etc.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
@Slick812: When I was talking about secure login, I was thinking of this: "how do you keep track of users and their answers?"  Without too much of a leap, you get to the questions, "How do I ensure the integrity of the tests?  How do I avoid accidentally losing user data?  How do I know that the person taking the test is really who they say they are?  Etc."

Certainly a session-only solution could "work," but it would be only an academic exercise to do it this way.  Without record-keeping and reporting, there is little chance that the application could have any real-world usefulness.

Best to all, ~Ray
Ray, Thanks for your view, and I do not disagree with your "Without record-keeping and reporting, there is little chance that the application could have any real-world usefulness." and I also think that web site security is VERY important.

but I am losing interest here, not being able to see much results in trying to help get some sort of advancement to solution here, or better idea of suggestion for code or education.

kate2001 : I an effort to have you get something from this, I took my last posted code and reworked it, hopefully to simplify the methods. I use SESSION data transfer in this one, and some hidden form input data also. This did NOT have any consideration for security, only simple methods (simple to me). You did not seem to follow any of the last code I posted, sorry about that. This may not address all of your goals, but you may need to start some where, for a workable test quiz page. I do NOT use any database access to test and grade the answers to the true-false questions, only the data in the $_SESSION['aList']
<?php
ini_set('session.name', 'hit_count'); session_start();
if (isset($_SESSION['userID'])) $userID = $_SESSION['userID']; else $userID = 222222;
// YOU will need to get a $userID from a secure LOG IN page, but I do NOT deal with that here

$truefalse = 10;
?>
<html><head><title>Student Quiz</title><style type="text/css">.rd{color:#b00;}</style></head><body BGCOLOR="#E3F7FF"><h2>Student Quiz for 10 True-False Questions</h2>
<p>
<?php
if (isset($_SESSION['userID'])) echo 'userID '.$_SESSION['userID'].'<br />';
if (isset($_SESSION['aList'])) echo 'aList '.$_SESSION['aList'].'<br />';
if (isset($_SESSION['qList'])) echo 'qList '.$_SESSION['qList'].'<br />';
$host = 'localhost';$user = 'xxxxx';$pass = 'xxxxx';$dbname = 'xxxxxx';

// GET Form Post Data here
$tf= array();
for ($i = 0; $i < $truefalse; $i++)
	{
	$tf[] = (isset($_POST['truefalse'.$i])) ? (int)$_POST['truefalse'.$i] : -2;
	}
$courseID = (empty($_POST['courseID'])) ? 0 : (int)$_POST['courseID'];
$chapter_No = (empty($_POST['chapterNum'])) ? 0 : (int)$_POST['chapterNum'];
// END of Form Post data


// I Deal with ALL of the Quiz on just One Page, Both Qustions and answer test
//BEGIN of code for answer evaluation to see which are correct
if (($tf[0] > -1) && ($courseID > 0)) {
// I DO NOT GET ANT DATABASE INFO TO TEST ANSWERS
// all data comes from the sesion 'aList' and the Post truefalse0 info
	$aryList = explode(',',$_SESSION['aList']);
	if (count($aryList) != $truefalse) die ('List Count is an ERROR');
	$Correct = 0;// number of correct answers
	for ($i = 0; $i < $truefalse; ++$i) {
		if ($aryList[$i] == $tf[$i]) {// test answer comparing the two arrays
			++$Correct;
			$tf[$i] = ($i+1).'. Correct<br />';
			} else $tf[$i] = ($i+1).'. Wrong<br />';
		}
	$Correct *= 100/$truefalse;
	echo 'Quiz Grade = '.$Correct.'%<br />';
	for ($i = 0; $i < $truefalse; ++$i) echo $tf[$i];
	// this is a SIMPLE display of results, the actual question text is not included
	
// here is where you access the database table for student test scores 
// and use the $_SESSION['userID'] and $courseID to record the result in the database
	echo '</body></html>';
	exit; // EXIT PHP so the quiz question code below will not happen
	}
//END of answer evaluation

$dbr = mysql_connect($host, $user, $pass);
mysql_select_db($dbname,$dbr) or die('Unable to select database');

$courseID = 5432;
$chapter_No = 1;

$count = 0;
$result = mysql_query('SELECT COUNT(NumID) FROM questions_tf WHERE courseID='.$courseID.' AND NumChapter='.$chapter_No);
if ($result) {
	$row = mysql_fetch_row($result);
	$count = $row[0];
	echo 'Row count '.$count.'<br />';
	} else die('Incorrect Database access error 1234');
if ($truefalse > $count)// Count and compare the number of questions in the database
	{
	echo '<p>ERROR- Number of requested True/False questions are greater than the number of quesion in the database for the selected Course.</p>';
	} else {
	$query = "SELECT NumID,CorrectAnswer,Description FROM questions_tf WHERE courseID = $courseID AND NumChapter = $chapter_No ORDER BY RAND() LIMIT $truefalse";
	// the ORDER BY RAND() can be REAL SLOW on large row count tables, but this was not in your question, just a hint
	$result = mysql_query($query);
	if ($result) {
		$QuesList = '';// a Comma delimited text list for the ID numbers of Questions
		$AnswerList = '';// a Comma delimited text list for the CorrectAnswer
        echo '<form name="tform" action="quiz2.php" method="post">Course ID '.$courseID;
		echo ' - <b>INSTRUCTION: Select True or False Option Buttons For the Following True/False Questions.</b><br />';
		
// transfer the courseID and chapterNum in POST data in the hidden inputs below
		echo '<input type="hidden" name="courseID" value="'.$courseID.'" />';
		echo '<input type="hidden" name="chapterNum" value="'.$chapter_No.'" />';
		echo '<table cellpadding="6" border="1">';
		$count = 0;// advances the "truefalse'.$count radio
		while($row = mysql_fetch_object($result))
		{
		if ($count == 0) {
		$QuesList .= $row->NumID;
		$AnswerList .= $row->CorrectAnswer;
		} 
		else 
		{
		$QuesList .= ','.$row->NumID;
		$AnswerList .= ','.$row->CorrectAnswer;
		}

		echo '<tr><td>'.($count+1) . ". ";
		echo $row->Description.$row->NumID.'<br />';
		// you MUST have a different name for each radio pair
		echo ' &nbsp; &nbsp;<input type="radio" value="0" name="truefalse'.$count.'" />False<br />';
		echo ' &nbsp; &nbsp;<input type="radio" value="1" name="truefalse'.$count.'" />True</td></tr>';
		++$count;
		}
		echo '</table><input type="submit" value="Score This Quiz" \></form><br />QuesList '.$QuesList.' AnswerList '.$AnswerList;
// IMPORTANT, below you MUST save your $AnswerList and $QuesList to session variables
		$_SESSION['aList'] = $AnswerList;
		$_SESSION['qList'] = $QuesList;
// I do NOT use the $_SESSION['qList'] in this, but it has the ID for question used here
		} else echo 'ERROR QUERY 2 SELECT '.mysql_error().'<br />';
	}

mysql_close();
?>
</body></html>

Open in new window

ID: 31209509 shows some of the moving parts of an online quiz.   ID: 31389693 addresses the idea of choosing the questions at random.  ID: 31397008 talks about grading.  HTH, ~Ray