• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

cms/modules/quiz/simplequiz.php

Go to the documentation of this file.
00001 <?php
00002 if(!defined('__PRAGYAN_CMS'))
00003 { 
00004         header($_SERVER['SERVER_PROTOCOL'].' 403 Forbidden');
00005         echo "<h1>403 Forbidden<h1><h4>You are not authorized to access the page.</h4>";
00006         echo '<hr/>'.$_SERVER['SERVER_SIGNATURE'];
00007         exit(1);
00008 }
00009 /*
00010  * Created on Jan 15, 2009
00011  */
00012 
00013 // SSO: optAnswer{SectionId}_{QuestionId} => value (OptionId)
00014 // MSO: chkAnswer{SectionId}_{QuestionId}_{OptionId}
00015 // Subj: txtAnswer{SectionId}_{QuestionId}
00016 
00017 
00018 define('QUIZ_COMPLETED', 1);
00019 define('QUIZ_SUBMISSIONFAILED', false);
00020 define('QUIZ_SUBMISSIONSUCCESSFUL', true);
00021 
00022 define('QUIZ_TIMEOUT_ERRORMSG', 'You have run out of time for this quiz. Your test will be evaluated only for the answers you have submitted previously.');
00023 define('QUIZ_SECTION_TIMEOUT_ERRORMSG', 'You have run out of time for this section. Only the answers that you have submitted previously will be evaluated. You can still view sections for which you have time left from the <a href="./+view">Quiz main page</a>.');
00024 
00025 class SimpleQuiz implements IQuiz {
00026         private $quizId;
00027         private $quizRow;
00028 
00029         public function __construct($quizId) {
00030                 $this->quizId = $quizId;
00031                 $this->quizRow = getQuizRow($quizId);
00032         }
00033         
00038         public function getPropertiesForm($dataSource) {
00039                 return 'No quiz specific properties.';
00040         }
00041 
00042         public function submitPropertiesForm() {
00043                 return true;
00044         }
00045         
00051         private function getSectionStartForm($sectionId) {
00052                 return <<<SECTIONSTARTFORM
00053                         <form name="sectionstartform" method="POST" action="./+view" style="padding:0;margin:0;display:inline">
00054                                 <input type="hidden" name="hdnSectionId" id="hdnSectionId" value="$sectionId" />
00055                                 <input type="submit" name="btnStartSection" id="btnStartSection" value="Start" />
00056                         </form>
00057 SECTIONSTARTFORM;
00058         }
00059         
00064         public function getFrontPage($userId) {
00065                 $frontPage = "<h2>{$this->quizRow['quiz_title']}</h2>\n";
00066                 $frontPage .= "<div class=\"quiz_headertext\">{$this->quizRow['quiz_headertext']}</div><br /><br />\n";
00067                 if ($this->quizRow['quiz_allowsectionrandomaccess']) {
00068                         $sectionList = getSectionList($this->quizId);
00069                         for ($i = 0; $i < count($sectionList); ++$i) {
00070                                 $frontPage .= '<strong>' . $sectionList[$i]['quiz_sectiontitle'] . '</strong> ';
00071                                 $attemptRow = getAttemptRow($this->quizId, $sectionList[$i]['quiz_sectionid'], $userId);
00072                                 if (!$attemptRow || is_null($attemptRow['quiz_attemptstarttime'])) {
00073                                         // User hasn't started this section yet.
00074                                         $frontPage .= $this->getSectionStartForm($sectionList[$i]['quiz_sectionid']);
00075                                 }
00076                                 elseif (is_null($attemptRow['quiz_submissiontime'])) {
00077                                         // User hasn't finished this section yet.
00078                                         $frontPage .= ' <a href="./+view&sectionid=' . $sectionList[$i]['quiz_sectionid'] . '">Go to questions</a>';
00079                                 }
00080                                 else {
00081                                         // User has finished the section already.
00082                                         $frontPage .= " Section Completed.";
00083                                 }
00084                                 $frontPage .= '<br /><br />';
00085                         }
00086                 }
00087                 else {
00088                         $frontPage .= <<<QUIZSTARTFORM
00089                         <form name="quizstartform" method="POST" action="./+view" style="padding:0;margin:0;display:inline">
00090                                 <input type="submit" name="btnStartQuiz" id="btnStartQuiz" value="Start" />
00091                         </form>
00092 QUIZSTARTFORM;
00093                 }
00094 
00095                 return $frontPage;
00096         }
00097 
00105         public function getQuizPage($userId) {
00106                 if ($this->checkQuizCompleted($userId)) {
00107                         displayinfo('You seem to have completed this quiz already. You can only take this quiz once.');
00108                         return '';
00109                 }
00110 
00111                 if ($this->quizRow['quiz_allowsectionrandomaccess']) {
00112                         // if btnStartSection and hdnSectionId are set
00113                         if (isset($_POST['btnStartSection']) && $this->isValidId($_POST['hdnSectionId']) && sectionBelongsToQuiz($this->quizId, $_POST['hdnSectionId']))
00114                                 $sectionId = intval($_POST['hdnSectionId']);
00115                         elseif (isset($_GET['sectionid']) && $this->isValidId($_GET['sectionid']))
00116                                 $sectionId = intval($_GET['sectionid']);
00117 
00118                         if (!isset($sectionId))
00119                                 return $this->getFrontPage($userId);
00120 
00121                         $attemptRow = getAttemptRow($this->quizId, $sectionId, $userId);
00122                         $sectionStarted = $attemptRow ? true : false;
00123                         $sectionCompleted = !is_null($attemptRow['quiz_submissiontime']);
00124 
00125                         if (!$sectionStarted) {
00126                                 if (!isset($_POST['btnStartSection'])) {
00127                                         displayerror('Error. You have not started this section yet. Please go to the quiz main page, and click on the Start Section button to view this section.');
00128                                         return '';
00129                                 }
00130                                 if (!startSection($this->quizId, $sectionId, $userId))
00131                                         return '';
00132                         }
00133                         elseif ($sectionCompleted) {
00134                                 displayinfo("You have completed this section.");
00135                                 return '';
00136                         }
00137 
00138                         if (isset($_POST['btnSubmit'])) {
00139                                 if ($this->submitQuizPage($userId) === true) {
00140                                         if ($this->markSectionCompleted($userId, $sectionId)) {
00141                                                 // This section has been completed. See if the quiz also got completed
00142                                                 if ($this->checkQuizCompleted($userId)) {
00143                                                         return $this->quizRow['quiz_submittext'];
00144                                                 }
00145                                                 else {
00146                                                         displayinfo('You have completed this section. You can move to another section.');
00147                                                         return $this->getFrontPage($userId);
00148                                                 }
00149                                         }
00150                                         else
00151                                                 displayinfo('Your previous page was submitted successfully.');
00152                                 }
00153                         }
00154 
00155                         // TODO: Put in time check here
00156                         if ($this->checkUserTimedOut($userId)) {
00157                                 displayerror(QUIZ_TIMEOUT_ERRORMSG);
00158                                 $this->forceQuizCompleted($userId);
00159                                 return '';
00160                         }
00161                         elseif ($this->checkUserTimedOut($userId, $sectionId)) {
00162                                 displayerror(QUIZ_SECTION_TIMEOUT_ERRORMSG);
00163                                 $this->forceQuizCompleted($userId, $sectionId);
00164                                 return '';
00165                         }
00166 
00167                         return $this->formatNextPage($userId, $sectionId);
00168                 }
00169                 else {
00170                         // if quiz is already started, show next page
00171                         // else, see if btnStartQuiz is set, if yes, mark quiz as started, and show next page
00172 
00173                         // to mark a user's quiz as started, we insert one entry for each section in the quiz into user_attempts
00174                         // to see if the user's quiz has been started, we see if there is a row in user_attempts with section id 1
00175                         $minSectionId = getFirstSectionId($this->quizId);
00176                         $attemptRow = getAttemptRow($this->quizId, $minSectionId, $userId);
00177 
00178                         if (!$attemptRow) {
00179                                 if (!isset($_POST['btnStartQuiz']))
00180                                         return $this->getFrontPage($userId);
00181 
00182                                 // ok, btnStartQuiz was set, and the quiz wasn't started already,
00183                                 // start it by inserting a row for each section in the quiz into quiz_userattempts.
00184                                 $attemptQuery = "INSERT INTO `quiz_userattempts`(`page_modulecomponentid`, `quiz_sectionid`, `user_id`, `quiz_attemptstarttime`) " .
00185                                                 "SELECT {$this->quizId}, `quiz_sectionid`, $userId, NOW() FROM `quiz_sections` WHERE `page_modulecomponentid` = {$this->quizId}";
00186                                 if (!mysql_query($attemptQuery)) {
00187                                         displayerror('Database Error. Could not update quiz information.');
00188                                         return '';
00189                                 }
00190                         }
00191 
00192                         if (isset($_POST['btnSubmit'])) {
00193                                 if ($this->submitQuizPage($userId) == true) {
00194                                         if ($this->markSectionCompleted($userId, -1)) {
00195                                                 if ($this->checkQuizCompleted($userId))
00196                                                         return $this->quizRow['quiz_submittext'];
00197                                         }
00198                                         else
00199                                                 displayinfo('Your previous page was submitted successfully.');
00200                                 }
00201                         }
00202 
00203                         // TODO: Put in time check here
00204                         if ($this->checkUserTimedOut($userId)) {
00205                                 displayerror(QUIZ_TIMEOUT_ERRORMSG);
00206                                 $this->forceQuizCompleted($userId);
00207                                 return '';
00208                         }
00209 
00210                         return $this->formatNextPage($userId);
00211                 }
00212         }
00213 
00220         public function submitQuizPage($userId) {
00221                 // get all the questions that have been shown to the user
00222                 // get the submitted answer for all of these questions, and insert them into the db
00223                 $questionQuery = "SELECT `quiz_questions`.`quiz_sectionid` AS `quiz_sectionid`, " .
00224                                 "`quiz_questions`.`quiz_questionid` AS `quiz_questionid`, " .
00225                                 "`quiz_questions`.`quiz_questiontype` AS `quiz_questiontype`, " .
00226                                 "`quiz_questions`.`quiz_answermaxlength` AS `quiz_answermaxlength` " .
00227                                 "FROM `quiz_answersubmissions`, `quiz_questions` WHERE " .
00228                                 "`quiz_questions`.`page_modulecomponentid` = `quiz_answersubmissions`.`page_modulecomponentid` AND " .
00229                                 "`quiz_questions`.`quiz_sectionid` = `quiz_answersubmissions`.`quiz_sectionid` AND " .
00230                                 "`quiz_questions`.`quiz_questionid` = `quiz_answersubmissions`.`quiz_questionid` AND " .
00231                                 "`quiz_questions`.`page_modulecomponentid` = {$this->quizId} AND `user_id` = $userId AND " .
00232                                 "`quiz_questionviewtime` IS NOT NULL AND `quiz_answersubmittime` IS NULL ";
00233                 if($this->quizRow['quiz_allowsectionrandomaccess'] == 1)
00234                         $questionQuery .= "AND `quiz_answersubmissions`.`quiz_sectionid` = {$_GET['sectionid']} ";
00235                 $questionQuery .= "ORDER BY `quiz_answersubmissions`.`quiz_questionrank` LIMIT {$this->quizRow['quiz_questionsperpage']}";
00236                 $questionResult = mysql_query($questionQuery);
00237                 if (!$questionResult) {
00238                         displayerror('Invalid query. ' . $questionQuery . ' ' . mysql_error());
00239                         return false;
00240                 }
00241 
00242                 // Put in check about user's time elapsed here
00243                 if ($this->checkUserTimedOut($userId, -1, '1 MINUTE')) {
00244                         displayerror('Sorry, you have exceeded your time limit for the quiz. Your latest submission cannot be evaluated.');
00245                         return false;
00246                 }
00247 
00248                 if ($this->quizRow['quiz_allowsectionrandomaccess']) {
00249                         $sectionId = intval($_GET['sectionid']);
00250                         if ($this->checkUserTimedOut($userId, $sectionId, '1 MINUTE')) {
00251                                 displayerror('Sorry, you have exceeded your time limit for this section. Your latest submission cannot be evaluated.');
00252                                 return false;
00253                         }
00254                 }
00255 
00256                 $submittedAnswers = array();
00257                 $rollbackQuery = array();
00258                 while ($questionRow = mysql_fetch_assoc($questionResult)) {
00259                         $rollbackQuery[] = "(`quiz_sectionid` = {$questionRow['quiz_sectionid']} AND `quiz_questionid` = {$questionRow['quiz_questionid']})";
00260                         $questionType = $questionRow['quiz_questiontype'];
00261 
00262                         if (!isset($_POST['hdnQuestion' . $questionRow['quiz_sectionid'] . '_' . $questionRow['quiz_questionid']])) {
00263                                 displayerror(
00264                                         'Error. The answers that you submitted do not match the list of questions you were shown. You may have refreshed the page, and resubmitted your previous page\'s answers. ' .
00265                                         'Please do not use the navigation buttons on your browser while taking the quiz.'
00266                                 );
00267                                 return false;
00268                         }
00269 
00270                         if ($questionType == 'sso' || $questionType == 'mso') {
00271                                 $options = getQuestionOptionList($this->quizId, $questionRow['quiz_sectionid'], $questionRow['quiz_questionid']);
00272                                 if ($questionType == 'sso') {
00273                                         $fieldName = 'optAnswer' . $questionRow['quiz_sectionid'] . '_' . $questionRow['quiz_questionid'];
00274                                         $submittedAnswer = isset($_POST[$fieldName]) && is_numeric($_POST[$fieldName]) ? intval($_POST[$fieldName]) : '';
00275                                         $optionFound = false;
00276                                         for ($i = 0; $i < count($options); ++$i) {
00277                                                 if ($options[$i]['quiz_optionid'] == $submittedAnswer) {
00278                                                         $submittedAnswers[] = array($questionRow['quiz_sectionid'], $questionRow['quiz_questionid'], $questionRow['quiz_questiontype'], $submittedAnswer);
00279                                                         $optionFound = true;
00280                                                         break;
00281                                                 }
00282                                         }
00283 
00284                                         if (!$optionFound)
00285                                                 $submittedAnswers[] = array($questionRow['quiz_sectionid'], $questionRow['quiz_questionid'], $questionRow['quiz_questiontype'], '');
00286                                 }
00287                                 else {
00288                                         $submittedAnswer = array();
00289                                         for ($i = 0; $i < count($options); ++$i) {
00290                                                 $fieldName = 'chkAnswer' . $questionRow['quiz_sectionid'] . '_' . $questionRow['quiz_questionid'] . '_' . $options[$i]['quiz_optionid'];
00291                                                 if (isset($_POST[$fieldName]) && is_numeric($_POST[$fieldName]))
00292                                                         $submittedAnswer[] = intval($options[$i]['quiz_optionid']);
00293                                         }
00294                                         sort($submittedAnswer);
00295                                         $submittedAnswers[] = array($questionRow['quiz_sectionid'], $questionRow['quiz_questionid'], $questionRow['quiz_questiontype'], implode('|', $submittedAnswer));
00296                                 }
00297                         }
00298                         elseif ($questionType == 'subjective') {
00299                                 $fieldName = 'txtAnswer' . $questionRow['quiz_sectionid'] . '_' . $questionRow['quiz_questionid'];
00300                                 $submittedAnswers[] = array($questionRow['quiz_sectionid'], $questionRow['quiz_questionid'], $questionRow['quiz_questiontype'], isset($_POST[$fieldName]) ? escape($_POST[$fieldName]) : '');
00301                         }
00302                 }
00303 
00304                 $rollbackQuery = "UPDATE `quiz_answersubmissions` SET `quiz_answersubmittime` = NULL WHERE `page_modulecomponentid` = {$this->quizId} AND `user_id` = $userId AND (" . implode(' OR ', $rollbackQuery) . ")";
00305                 for ($i = 0; $i < count($submittedAnswers); ++$i) {
00306                         $updateQuery = "UPDATE `quiz_answersubmissions` SET `quiz_submittedanswer` = '{$submittedAnswers[$i][3]}', `quiz_answersubmittime` = NOW() WHERE " .
00307                                         "`page_modulecomponentid` = {$this->quizId} AND `quiz_sectionid` = {$submittedAnswers[$i][0]} AND " .
00308                                         "`quiz_questionid` = {$submittedAnswers[$i][1]} AND `user_id` = $userId";
00309                         if (!mysql_query($updateQuery)) {
00310                                 displayerror('Invalid Query. Could not save answers.');
00311                                 mysql_query($rollbackQuery);
00312                                 return false;
00313                         }
00314                 }
00315 
00316                 return true;
00317         }
00318 
00325         private function checkQuizInitialized($userId) {
00326                 $countQuery = "SELECT COUNT(*) FROM `quiz_answersubmissions` WHERE `page_modulecomponentid` = {$this->quizId} AND `user_id` = $userId";
00327                 $countResult = mysql_query($countQuery);
00328                 
00329                 $countRow = mysql_fetch_row($countResult);
00330                 
00331                 return $countRow[0] == $this->quizRow['quiz_questionspertest'];
00332         }
00333 
00340         public function initQuiz($userId) {
00341                 // a user is about to start the quiz
00342                 // generate a list of questions, insert into quiz_answersubmissions, with answersubmittime = NULL
00343                 if ($this->checkQuizInitialized($userId))
00344                         return true;
00345 
00346                 $this->deleteEntries($userId);
00347                 $sectionList = getSectionList($this->quizId);
00348                 $questionList = array();
00349                 $sections = array();
00350                 for ($i = 0; $i < count($sectionList); ++$i) {
00351                         $questionList[$i] = $this->getSectionQuestions($sectionList[$i]);
00352                         for ($j = 0; $j < count($questionList[$i]); ++$j)
00353                                 $sections[] = $i;
00354                 }
00355 
00356                 if ($this->quizRow['quiz_allowsectionrandomaccess'] == 0 && $this->quizRow['quiz_mixsections']) 
00357                         shuffle($sections);
00358 
00359                 $offsets = array_fill(0, count($questionList), 0);
00360                 for ($i = 0; $i < count($sections); ++$i) {
00361                         $insertQuery = "INSERT INTO `quiz_answersubmissions`(`page_modulecomponentid`, `quiz_sectionid`, `quiz_questionid`, `user_id`, `quiz_questionrank`) VALUES" .
00362                                         "({$this->quizId}, {$sectionList[$sections[$i]]['quiz_sectionid']}, {$questionList[$sections[$i]][$offsets[$sections[$i]]]}, $userId, $i)";
00363                         if (!mysql_query($insertQuery)) {
00364                                 displayerror('Database Error. Could not initialize quiz.');
00365                                 return false;
00366                         }
00367                         $offsets[$sections[$i]]++;
00368                 }
00369                 return true;
00370         }
00371 
00376         public function deleteEntries($userId) {
00377                 $tableNames = array('quiz_userattempts', 'quiz_answersubmissions');
00378                 $affectedRows = array();
00379                 return deleteItem($tableNames, "`page_modulecomponentid` = {$this->quizId} AND `user_id` = $userId", $affectedRows);
00380         }
00381 
00386         private function getPageQuestions($userId, $sectionId = -1) {
00387                 $questionsPerPage = $this->quizRow['quiz_questionsperpage'];
00388                 $questionQuery = "SELECT `quiz_sectionid`, `quiz_questionid` FROM `quiz_answersubmissions` WHERE `user_id` = $userId AND `page_modulecomponentid` = {$this->quizId} AND `quiz_answersubmittime` IS NULL ";
00389                 if ($this->quizRow['quiz_allowsectionrandomaccess'] == 1)
00390                         $questionQuery .= " AND `quiz_sectionid` = $sectionId ";
00391                 $questionQuery .= " ORDER BY `quiz_questionrank` LIMIT $questionsPerPage";
00392                 $questionResult = mysql_query($questionQuery);
00393                 if (!$questionResult) {
00394                         displayerror('Database Error. Could not fetch questions.');
00395                         return null;
00396                 }
00397                 $questionIds = array();
00398                 while ($questionRow = mysql_fetch_row($questionResult))
00399                         $questionIds[] = $questionRow;
00400                 return $questionIds;
00401         }
00402         
00408         private function getTimerHtml($userId, $sectionId = -1) {
00409                 $testElapsedTime = $this->getElapsedTime($userId);
00410                 $testElapsedTime = explode(':', $testElapsedTime);
00411                 $testElapsedTime = implode(', ', $testElapsedTime);
00412                 $sectionElapsedTime = $this->getElapsedTime($userId,$sectionId);
00413                 $sectionElapsedTime = explode(':', $sectionElapsedTime);
00414                 $sectionElapsedTime = implode(', ', $sectionElapsedTime);
00415 
00416                 $testTime = $this->quizRow['quiz_testduration'];
00417                 $testTime = explode(':', $testTime);
00418                 $testTime = implode(', ', $testTime);
00419                 
00420                 if ($this->quizRow['quiz_allowsectionrandomaccess']) {
00421                     $sectionTime = mysql_fetch_array(mysql_query("SELECT `quiz_sectiontimelimit` FROM `quiz_sections` WHERE `page_modulecomponentid` = '{$this->quizId}' AND `quiz_sectionid` = '$sectionId'"));
00422                 
00423                     $sectionTime = $sectionTime[0];
00424                     $sectionTime = explode(':', $sectionTime);
00425                     $sectionTime = implode(', ', $sectionTime);             
00426                 $scripts[] = "var sectionTimer = new JSTimer('sectionTimerContainer', $sectionElapsedTime);\nsectionTimer.addTickHandler($sectionTime, forceQuizSubmit)";
00427                 }
00428 
00429 
00430                 $scripts[] = "var testTimer = new JSTimer('testTimerContainer', $testElapsedTime);\ntestTimer.addTickHandler($testTime, forceQuizSubmit)";
00431                 
00432                 $divs = array();
00433                 if ($this->quizRow['quiz_showquiztimer']) {
00434 
00435                         $divs[] = '<div id="testTimerContainer" class="quiz_testtimer">Total Quiz Time Elapsed: </div>';
00436 
00437                 }
00438 
00439                 if ($this->quizRow['quiz_showpagetimer']) {
00440                         $divs[] = '<div id="pageTimerContainer" class="quiz_pagetimer"></div>';
00441                         $scripts[] = "var pageTimer = new JSTimer('pageTimerContainer', 0, 0, 0);\n";
00442                 }
00443 
00444                 $sectionRow = getSectionRow($this->quizId, $sectionId);
00445                 if ($sectionRow['quiz_sectionshowlimit']) {
00446                         $sectionRow = getSectionRow($this->quizId,$sectionId);
00447                         $limit = $sectionRow['quiz_sectiontimelimit'];
00448                         $divs[] = '<div id="pageTimerlimit" class="quiz_limit">Section Limit: ' . $limit . '</div>';
00449                         $divs[] = '<div id="sectionTimerContainer" 
00450 class="quiz_testtimer">Section Time Elapsed: </div><br /><br />';
00451                 }
00452 
00453                 global $urlRequestRoot, $cmsFolder, $moduleFolder;
00454                 $timerScriptSrc = "$urlRequestRoot/$cmsFolder/$moduleFolder/quiz/timer.js";
00455 
00456                 if (count($divs)) {
00457                         $divs = implode("\n", $divs);
00458                         $scripts = implode("\n", $scripts);
00459 
00460                         $timerScript = <<<TIMERSCRIPT
00461                                 <script type="text/javascript" src="$timerScriptSrc"></script>
00462                                 $divs
00463                                 <script type="text/javascript">
00464                                         function forceQuizSubmit() {
00465                                                 alert("Your time is up. Please click Ok to submit the quiz. If you do not submit within 30 seconds, your quiz will expire, and your answers to this page will not be recorded.");
00466                                                 var quizForm = document.getElementById('quizForm');
00467                                                 var submitButton = document.getElementById('btnSubmit');
00468                                                 submitButton.type = 'hidden';
00469                                                 quizForm.submit();
00470                                         }
00471 
00472                                         $scripts
00473                                 </script>
00474 TIMERSCRIPT;
00475                 }
00476 
00477                 return $timerScript;
00478         }
00479 
00486         private function formatQuestion($questionRow, $questionNumber = -1) {
00487                 $questionType = $questionRow['quiz_questiontype'];
00488                 if ($questionType == 'subjective') {
00489                         $fieldName = 'txtAnswer' . $questionRow['quiz_sectionid'] . '_' . $questionRow['quiz_questionid'];
00490                         $answer = '<textarea 
00491 style="width:95%;height:100px;" name="' . 
00492 $fieldName . '" id="' . $fieldName . '"></textarea>';
00493                 }
00494                 else {
00495                         $optionList = getQuestionOptionList($this->quizId, $questionRow['quiz_sectionid'], $questionRow['quiz_questionid']);
00496 
00497                         $answer = '<table class="objectivecontainer" width="100%">';
00498                         for ($i = 0; $i < count($optionList); ++$i) {
00499                                 $fieldType = ($questionType == 'sso' ? 'radio' : 'checkbox');
00500                                 $fieldName = '';
00501                                 $fieldId = '';
00502                                 if ($questionType == 'sso') {
00503                                         $fieldName = 'optAnswer' . $questionRow['quiz_sectionid'] . '_' . $questionRow['quiz_questionid'];
00504                                         $fieldId = $fieldName . '_' . $optionList[$i]['quiz_optionid'];
00505                                 }
00506                                 elseif ($questionType == 'mso') {
00507                                         $fieldName = 'chkAnswer' . $questionRow['quiz_sectionid'] . '_' . $questionRow['quiz_questionid'] . '_' . $optionList[$i]['quiz_optionid'];
00508                                         $fieldId = $fieldName;
00509                                 }
00510                                 $answer .= "<tr><td width=\"24\"><input type=\"$fieldType\" name=\"$fieldName\" id=\"$fieldId\" value=\"{$optionList[$i]['quiz_optionid']}\" /> </td><td><label for=\"$fieldId\"> {$optionList[$i]['quiz_optiontext']}</label></td></tr>\n";
00511                         }
00512                         $answer .= '</table>';
00513                 }
00514 
00515                 $hiddenFieldName = "hdnQuestion{$questionRow['quiz_sectionid']}_{$questionRow['quiz_questionid']}";
00516 
00517                 $questionDesc = $questionRow['quiz_question'];
00518                 if ($questionNumber > 0) $questionDesc = $questionNumber . ') ' . $questionDesc;
00519 
00520                 global $sourceFolder, $moduleFolder;
00521                 require_once($sourceFolder."/latexRender.class.php");
00522                 $render = new latexrender();
00523                 $questionDesc = $render->transform($questionDesc);
00524                 $answer = $render->transform($answer);
00525 
00526                 return <<<QUESTIONFORM
00527                         <input type="hidden" name="$hiddenFieldName" id="$hiddenFieldName" value="" />
00528                         <div class="quiz_questioncontainer">
00529                                 <br /><b>{$questionDesc}</b><br /><br />
00530                         </div>
00531                         <div class="quiz_answercontainer">
00532                                 $answer
00533                         </div>
00534 QUESTIONFORM;
00535         }
00536 
00541         private function formatNextPage($userId, $sectionId = -1) {
00542                 $questionCount = $this->quizRow['quiz_questionsperpage'];
00543                 $questionQuery = "SELECT `quiz_questions`.`quiz_sectionid` AS `quiz_sectionid`, `quiz_questions`.`quiz_questionid` AS `quiz_questionid`, `quiz_question`, `quiz_questiontype`, `quiz_questionweight`, `quiz_answermaxlength`, `quiz_rightanswer`, `quiz_questionviewtime`, `quiz_answersubmittime` " .
00544                                 "FROM `quiz_questions`, `quiz_answersubmissions` WHERE " .
00545                                 "`quiz_questions`.`page_modulecomponentid` = {$this->quizId} AND " .
00546                                 "`quiz_answersubmissions`.`user_id` = $userId AND " .
00547                                 "`quiz_questions`.`page_modulecomponentid` = `quiz_answersubmissions`.`page_modulecomponentid` AND " .
00548                                 "`quiz_questions`.`quiz_sectionid` = `quiz_answersubmissions`.`quiz_sectionid` AND " .
00549                                 "`quiz_questions`.`quiz_questionid` = `quiz_answersubmissions`.`quiz_questionid` AND " .
00550                                 "`quiz_answersubmissions`.`quiz_answersubmittime` IS NULL ";
00551                 if ($this->quizRow['quiz_allowsectionrandomaccess'] == 1)
00552                         $questionQuery .= "AND `quiz_answersubmissions`.`quiz_sectionid` = $sectionId ";
00553                 $questionQuery .= "ORDER BY `quiz_answersubmissions`.`quiz_questionrank` " .
00554                                 "LIMIT $questionCount";
00555 
00556                 $questionResult = mysql_query($questionQuery);
00557 
00558                 $questionNumber = 1;
00559                 $questionPage = $this->getTimerHtml($userId, $sectionId);
00560                 $questionPage .= '<form name="quizquestions" id="quizForm" method="POST" action="./+view' . ($sectionId == -1 ? '' : '&sectionid=' . $sectionId) . '" onsubmit="return confirm(\'Are you sure you wish to submit this page?\')">';
00561                 while ($questionRow = mysql_fetch_assoc($questionResult)) {
00562                         if (is_null($questionRow['quiz_questionviewtime']))
00563                                 mysql_query("UPDATE `quiz_answersubmissions` SET `quiz_questionviewtime` = NOW() WHERE `page_modulecomponentid` = {$this->quizId} AND `quiz_sectionid` = {$questionRow['quiz_sectionid']} AND `quiz_questionid` = {$questionRow['quiz_questionid']}");
00564                         $questionPage .= $this->formatQuestion($questionRow, $questionNumber);
00565                         ++$questionNumber;
00566                 }
00567                 $questionPage .= '<input type="submit" name="btnSubmit" id="btnSubmit" value="Submit" />';
00568                 $questionPage .= '</form>';
00569 
00570                 $questionPage .= <<<QUESTIONPAGESCRIPT
00571                 <script type="text/javascript">
00572                         // make opt buttons uncheckable
00573                         var inputFields = document.getElementById('quizForm').getElementsByTagName('input');
00574                         for (var i = 0; i < inputFields.length; ++i) {
00575                                 if (inputFields[i].type == 'radio')
00576                                         inputFields[i].onclick = function(e) {
00577                                                 if (this.rel == 'checked') {
00578                                                         this.checked = false;
00579                                                         this.rel = '';
00580                                                 }
00581                                                 else {
00582                                                         var elements = document.getElementsByName(this.name);
00583                                                         for (var i = 0; i < elements.length; ++i) {
00584                                                                 elements[i].rel = '';
00585                                                                 elements[i].checked = false;
00586                                                         }
00587                                                         this.checked = true;
00588                                                         this.rel = 'checked';
00589                                                 }
00590                                         };
00591                         }
00592                 </script>
00593 QUESTIONPAGESCRIPT;
00594                 return $questionPage;
00595         }
00596 
00604         private function countAttemptedQuestions($userId, $sectionId = -1) {
00605                 $countQuery = "SELECT COUNT(*) FROM `quiz_submittedanswers` WHERE `page_modulecomponentid` = {$this->quizId}";
00606                 if ($sectionId != -1)
00607                         $countQuery .= " AND `quiz_sectionid` = $sectionId";
00608                 $countQuery .= " `user_id` = $userId AND `quiz_answersubmittime` IS NOT NULL";
00609                 $countResult = mysql_query($countQuery);
00610                 if (!$countResult) {
00611                         displayerror('Database Error. Could not retrieve user attempt information.');
00612                         return false;
00613                 }
00614                 $countRow = mysql_fetch_row($countResult);
00615                 return $countRow[0];
00616         }
00617         
00622         private function getSectionQuestions($sectionRow) {
00623                 $questionTypes = array_keys(getQuestionTypes());
00624                 $sectionId = $sectionRow['quiz_sectionid'];
00625 
00626                 if ($sectionRow['quiz_sectionquestionshuffled'] == 0) {
00627                         $limit = 0;
00628                         for ($i = 0; $i < count($questionTypes); ++$i)
00629                                 $limit += $sectionRow["quiz_section{$questionTypes[$i]}count"];
00630                         $questionQuery = "SELECT `quiz_questionid` FROM `quiz_questions` WHERE `page_modulecomponentid` = {$this->quizId} AND `quiz_sectionid` = $sectionId ORDER BY `quiz_questionrank` LIMIT $limit";
00631                 }
00632                 else {
00633                         $questionIdQueries = array();
00634                         for ($i = 0; $i < count($questionTypes); ++$i) {
00635                                 $limit = $sectionRow["quiz_section{$questionTypes[$i]}count"];
00636                                 if ($limit) {
00637                                         $questionIdQueries[] = 
00638                                                 "(SELECT `quiz_questionid` FROM `quiz_questions` WHERE `page_modulecomponentid` = {$this->quizId} AND `quiz_sectionid` = $sectionId AND `quiz_questiontype` = '{$questionTypes[$i]}' ORDER BY RAND() LIMIT $limit)";
00639                                 }
00640                         }
00641 
00642                         $questionQuery = "SELECT `quiz_questionid` FROM (" . implode(' UNION ', $questionIdQueries) . ") AS `questions` ORDER BY RAND()";
00643                 }
00644 
00645                 $questionIds = array();
00646                 $questionResult = mysql_query($questionQuery) or die(mysql_error());
00647                 while ($questionRow = mysql_fetch_row($questionResult))
00648                         $questionIds[] = $questionRow[0];
00649                 return $questionIds;
00650         }
00651 
00659         private function checkQuizCompleted($userId) {
00660                 $countQuery = "SELECT COUNT(*) FROM `quiz_userattempts`, `quiz_sections` WHERE " .
00661                                 "`quiz_sections`.`page_modulecomponentid` = `quiz_userattempts`.`page_modulecomponentid` AND " .
00662                                 "`quiz_sections`.`quiz_sectionid` = `quiz_userattempts`.`quiz_sectionid` AND " .
00663                                 "`quiz_sections`.`page_modulecomponentid` = {$this->quizId} AND " .
00664                                 "`quiz_userattempts`.`user_id` = $userId AND " .
00665                                 "`quiz_submissiontime` IS NOT NULL";
00666                 $countResult = mysql_query($countQuery);
00667                 if (!$countResult) {
00668                         displayerror('Database Error. Could not fetch section information.');
00669                         return false;
00670                 }
00671                 $countRow = mysql_fetch_row($countResult);
00672                 $completedCount = $countRow[0];
00673                 $countQuery = "SELECT COUNT(*) FROM `quiz_sections` WHERE `page_modulecomponentid` = {$this->quizId}";
00674                 $countResult = mysql_query($countQuery);
00675                 $countRow = mysql_fetch_row($countResult);
00676                 return $countRow[0] == $completedCount;
00677         }
00678 
00685         private function isValidId($id) {
00686                 return isset($id) && is_numeric($id) && $id > 0;
00687         }
00688 
00694         private function markSectionCompleted($userId, $sectionId = -1) {
00695                 if ($sectionId == -1) {
00696                         $sections = getSectionList($this->quizId);
00697                         $allOk = true;
00698                         for ($i = 0; $i < count($sections); ++$i)
00699                                 $allOk = $this->markSectionCompleted($userId, $sections[$i]['quiz_sectionid']) && $allOk;
00700                         return $allOk;
00701                 }
00702 
00703                 $attemptRow = getAttemptRow($this->quizId, $sectionId, $userId);
00704                 if (is_null($attemptRow['quiz_submissiontime'])) {
00705                         // Check if all questions for this section have been completed, if yes, set quiz_submissiontime and return true
00706                         $questionQuery = "SELECT COUNT(*) FROM `quiz_answersubmissions` WHERE " .
00707                                         "`page_modulecomponentid` = {$this->quizId} AND `quiz_sectionid` = $sectionId AND `user_id` = $userId AND `quiz_answersubmittime` IS NULL";
00708                         $questionResult = mysql_query($questionQuery);
00709                         $questionRow = mysql_fetch_row($questionResult);
00710 
00711                         if ($questionRow[0] != 0)
00712                                 return false;
00713 
00714                         $updateQuery = "UPDATE `quiz_userattempts` SET `quiz_submissiontime` = NOW() WHERE `page_modulecomponentid` = $this->quizId AND `quiz_sectionid` = $sectionId AND `user_id` = $userId";
00715                         if (mysql_query($updateQuery))
00716                                 return true;
00717                         else {
00718                                 displayerror('Database Error. Could not mark section as completed.');
00719                                 return -1;
00720                         }
00721                 }
00722                 else
00723                         return true;
00724         }
00725 
00732         private function markQuizCompleted($userId) {
00733                 $updateQueries = array(
00734                         "UPDATE `quiz_answersubmissions` SET `quiz_submittedanswer` = '', `quiz_answersubmittime` = NOW() WHERE `page_modulecomponentid` = {$this->quizId} AND `user_id` = $userId AND `quiz_answersubmittime` IS NULL",
00735                         "UPDATE `quiz_userattempts` SET `quiz_submissiontime` = NOW() WHERE `page_modulecomponentid` = {$this->quizId} AND `user_id` = $userId AND `quiz_submissiontime` IS NULL"
00736                 );
00737 
00738                 if (!mysql_query($updateQueries[0]) || !mysql_query($updateQueries[1])) {
00739                         displayerror('Error. Could not mark quiz as completed.');
00740                         return false;
00741                 }
00742 
00743                 return true;
00744         }
00745 
00752         private function getElapsedTime($userId, $sectionId = -1) {
00753                 if ($sectionId < 0)
00754                         $elapsedQuery = "SELECT TIMEDIFF(NOW(), MIN(`quiz_attemptstarttime`)) FROM `quiz_userattempts` WHERE " .
00755                                         "`page_modulecomponentid` = {$this->quizId} AND `user_id` = $userId";
00756                 else
00757                         $elapsedQuery = "SELECT TIMEDIFF(NOW(), `quiz_attemptstarttime`) FROM `quiz_userattempts` WHERE " .
00758                                         "`page_modulecomponentid` = {$this->quizId} AND `quiz_sectionid` = $sectionId AND `user_id` = $userId";
00759 
00760                 $elapsedResult = mysql_query($elapsedQuery);
00761                 if (!$elapsedResult)
00762                         displayerror('Error. ' . $elapsedQuery . '<br />' . mysql_error());
00763                 $elapsedRow = mysql_fetch_row($elapsedResult);
00764                 return $elapsedRow[0];
00765         }
00766 
00767         private function getRemainingTime($userId, $sectionId = -1) {
00768                 if ($sectionId < 0) {
00769                         $remainingQuery = "SELECT TIMEDIFF(NOW(), ADDTIME(MIN(`quiz_attemptstarttime`), '{$this->quizRow['quiz_testduration']}')) FROM `quiz_userattempts` WHERE " .
00770                                         "`page_modulecomponentid` = {$this->quizId} AND `user_id` = $userId";
00771                 }
00772                 else {
00773                         $remainingQuery = "SELECT TIMEDIFF(NOW(), ADDTIME(`quiz_attemptstarttime`, '{$this->quizRow['quiz_testduration']}')) FROM `quiz_userattempts` WHERE " .
00774                                         "`page_modulecomponentid` = {$this->quizId} AND `user_id` = $userId";
00775                 }
00776 
00777                 $remainingResult = mysql_query($remainingQuery);
00778                 $remainingRow = mysql_fetch_row($remainingResult);
00779                 return $remainingRow[0];
00780         }
00781 
00790         private function checkUserTimedOut($userId, $sectionId = -1, $offset = '0 SECOND') {
00791                 if ($sectionId < 0) {
00792                         // Check if the quiz has timed out:
00793                         //  Find the earliest attempt start time, add quiz duration to it
00794                         //      add offset to now, and compare
00795                         $timeoutQuery = "SELECT IF(DATE_SUB(NOW(), INTERVAL $offset) > ADDTIME(MIN(`quiz_attemptstarttime`), '{$this->quizRow['quiz_testduration']}'), 1, 0) AS `quiz_expired` FROM " .
00796                                         "`quiz_userattempts` WHERE `page_modulecomponentid` = {$this->quizId} AND `user_id` = $userId";
00797                 }
00798                 else {
00799                         $sectionRow = getSectionRow($this->quizId, $sectionId);
00800 
00801                         if ($sectionRow['quiz_sectiontimelimit'] == '00:00:00')
00802                                 return false;
00803 
00804                         $timeoutQuery = "SELECT IF(DATE_SUB(NOW(), INTERVAL $offset) > ADDTIME(`quiz_attemptstarttime`, '{$sectionRow['quiz_sectiontimelimit']}'), 1, 0) AS `quiz_expired` FROM " .
00805                                         "`quiz_userattempts` WHERE `page_modulecomponentid` = {$this->quizId} AND `quiz_sectionid` = $sectionId AND `user_id` = $userId";
00806                 }
00807 
00808                 $timeoutResult = mysql_query($timeoutQuery);
00809                 if (!$timeoutResult) {
00810                         displayerror('Database Error. Could not retrieve time information.');
00811                         return -1;
00812                 }
00813 
00814                 $timeoutRow = mysql_fetch_row($timeoutResult);
00815                 if (is_null($timeoutRow[0])) {
00816                         // An invalid Section ID was passed => we could not find a row for the user for that
00817                         // Section ID. assume he timed out
00818                         return true;
00819                 }
00820 
00821                 return $timeoutRow[0];
00822         }
00823 
00831         private function forceQuizCompleted($userId, $sectionId = -1) {
00832                 $updateQuery = "UPDATE `quiz_userattempts` SET `quiz_submissiontime` = NOW() WHERE `quiz_submissiontime` IS NULL AND `page_modulecomponentid` = {$this->quizId} AND `user_id` = $userId";
00833                 if ($sectionId >= 0)
00834                         $updateQuery .= " AND `quiz_sectionid` = $sectionId";
00835                 if (!mysql_query($updateQuery)) {
00836                         displayerror('Database Error. Could not mark quiz as completed.');
00837                         return false;
00838                 }
00839                 return true;
00840         }
00841 };

Generated on Mon Mar 14 2011 05:35:30 for Pragyan CMS by  doxygen 1.7.1