• 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 
00034         public function getPropertiesForm($dataSource) {
00035                 return 'No quiz specific properties.';
00036         }
00037 
00038         public function submitPropertiesForm() {
00039                 return true;
00040         }
00041 
00042         private function getSectionStartForm($sectionId) {
00043                 return <<<SECTIONSTARTFORM
00044                         <form name="sectionstartform" method="POST" action="./+view" style="padding:0;margin:0;display:inline">
00045                                 <input type="hidden" name="hdnSectionId" id="hdnSectionId" value="$sectionId" />
00046                                 <input type="submit" name="btnStartSection" id="btnStartSection" value="Start" />
00047                         </form>
00048 SECTIONSTARTFORM;
00049         }
00050 
00051         public function getFrontPage($userId) {
00052                 $frontPage = "<h2>{$this->quizRow['quiz_title']}</h2>\n";
00053                 $frontPage .= "<div class=\"quiz_headertext\">{$this->quizRow['quiz_headertext']}</div><br /><br />\n";
00054                 if ($this->quizRow['quiz_allowsectionrandomaccess']) {
00055                         $sectionList = getSectionList($this->quizId);
00056                         for ($i = 0; $i < count($sectionList); ++$i) {
00057                                 $frontPage .= '<strong>' . $sectionList[$i]['quiz_sectiontitle'] . '</strong> ';
00058                                 $attemptRow = getAttemptRow($this->quizId, $sectionList[$i]['quiz_sectionid'], $userId);
00059                                 if (!$attemptRow || is_null($attemptRow['quiz_attemptstarttime'])) {
00060                                         // User hasn't started this section yet.
00061                                         $frontPage .= $this->getSectionStartForm($sectionList[$i]['quiz_sectionid']);
00062                                 }
00063                                 elseif (is_null($attemptRow['quiz_submissiontime'])) {
00064                                         // User hasn't finished this section yet.
00065                                         $frontPage .= ' <a href="./+view&sectionid=' . $sectionList[$i]['quiz_sectionid'] . '">Go to questions</a>';
00066                                 }
00067                                 else {
00068                                         // User has finished the section already.
00069                                         $frontPage .= " Section Completed.";
00070                                 }
00071                                 $frontPage .= '<br /><br />';
00072                         }
00073                 }
00074                 else {
00075                         $frontPage .= <<<QUIZSTARTFORM
00076                         <form name="quizstartform" method="POST" action="./+view" style="padding:0;margin:0;display:inline">
00077                                 <input type="submit" name="btnStartQuiz" id="btnStartQuiz" value="Start" />
00078                         </form>
00079 QUIZSTARTFORM;
00080                 }
00081 
00082                 return $frontPage;
00083         }
00084 
00091         public function getQuizPage($userId) {
00092                 if ($this->checkQuizCompleted($userId)) {
00093                         displayinfo('You seem to have completed this quiz already. You can only take this quiz once.');
00094                         return '';
00095                 }
00096 
00097                 if ($this->quizRow['quiz_allowsectionrandomaccess']) {
00098                         // if btnStartSection and hdnSectionId are set
00099                         if (isset($_POST['btnStartSection']) && $this->isValidId($_POST['hdnSectionId']) && sectionBelongsToQuiz($this->quizId, $_POST['hdnSectionId']))
00100                                 $sectionId = intval($_POST['hdnSectionId']);
00101                         elseif (isset($_GET['sectionid']) && $this->isValidId($_GET['sectionid']))
00102                                 $sectionId = intval($_GET['sectionid']);
00103 
00104                         if (!isset($sectionId))
00105                                 return $this->getFrontPage($userId);
00106 
00107                         $attemptRow = getAttemptRow($this->quizId, $sectionId, $userId);
00108                         $sectionStarted = $attemptRow ? true : false;
00109                         $sectionCompleted = !is_null($attemptRow['quiz_submissiontime']);
00110 
00111                         if (!$sectionStarted) {
00112                                 if (!isset($_POST['btnStartSection'])) {
00113                                         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.');
00114                                         return '';
00115                                 }
00116                                 if (!startSection($this->quizId, $sectionId, $userId))
00117                                         return '';
00118                         }
00119                         elseif ($sectionCompleted) {
00120                                 displayinfo("You have completed this section.");
00121                                 return '';
00122                         }
00123 
00124                         if (isset($_POST['btnSubmit'])) {
00125                                 if ($this->submitQuizPage($userId) === true) {
00126                                         if ($this->markSectionCompleted($userId, $sectionId)) {
00127                                                 // This section has been completed. See if the quiz also got completed
00128                                                 if ($this->checkQuizCompleted($userId)) {
00129                                                         return $this->quizRow['quiz_submittext'];
00130                                                 }
00131                                                 else {
00132                                                         displayinfo('You have completed this section. You can move to another section.');
00133                                                         return $this->getFrontPage($userId);
00134                                                 }
00135                                         }
00136                                         else
00137                                                 displayinfo('Your previous page was submitted successfully.');
00138                                 }
00139                         }
00140 
00141                         // TODO: Put in time check here
00142                         if ($this->checkUserTimedOut($userId)) {
00143                                 displayerror(QUIZ_TIMEOUT_ERRORMSG);
00144                                 $this->forceQuizCompleted($userId);
00145                                 return '';
00146                         }
00147                         elseif ($this->checkUserTimedOut($userId, $sectionId)) {
00148                                 displayerror(QUIZ_SECTION_TIMEOUT_ERRORMSG);
00149                                 $this->forceQuizCompleted($userId, $sectionId);
00150                                 return '';
00151                         }
00152 
00153                         return $this->formatNextPage($userId, $sectionId);
00154                 }
00155                 else {
00156                         // if quiz is already started, show next page
00157                         // else, see if btnStartQuiz is set, if yes, mark quiz as started, and show next page
00158 
00159                         // to mark a user's quiz as started, we insert one entry for each section in the quiz into user_attempts
00160                         // to see if the user's quiz has been started, we see if there is a row in user_attempts with section id 1
00161                         $minSectionId = getFirstSectionId($this->quizId);
00162                         $attemptRow = getAttemptRow($this->quizId, $minSectionId, $userId);
00163 
00164                         if (!$attemptRow) {
00165                                 if (!isset($_POST['btnStartQuiz']))
00166                                         return $this->getFrontPage($userId);
00167 
00168                                 // ok, btnStartQuiz was set, and the quiz wasn't started already,
00169                                 // start it by inserting a row for each section in the quiz into quiz_userattempts.
00170                                 $attemptQuery = "INSERT INTO `quiz_userattempts`(`page_modulecomponentid`, `quiz_sectionid`, `user_id`, `quiz_attemptstarttime`) " .
00171                                                 "SELECT {$this->quizId}, `quiz_sectionid`, $userId, NOW() FROM `quiz_sections` WHERE `page_modulecomponentid` = {$this->quizId}";
00172                                 if (!mysql_query($attemptQuery)) {
00173                                         displayerror('Database Error. Could not update quiz information.');
00174                                         return '';
00175                                 }
00176                         }
00177 
00178                         if (isset($_POST['btnSubmit'])) {
00179                                 if ($this->submitQuizPage($userId) == true) {
00180                                         if ($this->markSectionCompleted($userId, -1)) {
00181                                                 if ($this->checkQuizCompleted($userId))
00182                                                         return $this->quizRow['quiz_submittext'];
00183                                         }
00184                                         else
00185                                                 displayinfo('Your previous page was submitted successfully.');
00186                                 }
00187                         }
00188 
00189                         // TODO: Put in time check here
00190                         if ($this->checkUserTimedOut($userId)) {
00191                                 displayerror(QUIZ_TIMEOUT_ERRORMSG);
00192                                 $this->forceQuizCompleted($userId);
00193                                 return '';
00194                         }
00195 
00196                         return $this->formatNextPage($userId);
00197                 }
00198         }
00199 
00205         public function submitQuizPage($userId) {
00206                 // get all the questions that have been shown to the user
00207                 // get the submitted answer for all of these questions, and insert them into the db
00208                 $questionQuery = "SELECT `quiz_questions`.`quiz_sectionid` AS `quiz_sectionid`, " .
00209                                 "`quiz_questions`.`quiz_questionid` AS `quiz_questionid`, " .
00210                                 "`quiz_questions`.`quiz_questiontype` AS `quiz_questiontype`, " .
00211                                 "`quiz_questions`.`quiz_answermaxlength` AS `quiz_answermaxlength` " .
00212                                 "FROM `quiz_answersubmissions`, `quiz_questions` WHERE " .
00213                                 "`quiz_questions`.`page_modulecomponentid` = `quiz_answersubmissions`.`page_modulecomponentid` AND " .
00214                                 "`quiz_questions`.`quiz_sectionid` = `quiz_answersubmissions`.`quiz_sectionid` AND " .
00215                                 "`quiz_questions`.`quiz_questionid` = `quiz_answersubmissions`.`quiz_questionid` AND " .
00216                                 "`quiz_questions`.`page_modulecomponentid` = {$this->quizId} AND `user_id` = $userId AND " .
00217                                 "`quiz_questionviewtime` IS NOT NULL AND `quiz_answersubmittime` IS NULL ";
00218                 if($this->quizRow['quiz_allowsectionrandomaccess'] == 1)
00219                         $questionQuery .= "AND `quiz_answersubmissions`.`quiz_sectionid` = {$_GET['sectionid']} ";
00220                 $questionQuery .= "ORDER BY `quiz_answersubmissions`.`quiz_questionrank` LIMIT {$this->quizRow['quiz_questionsperpage']}";
00221                 $questionResult = mysql_query($questionQuery);
00222                 if (!$questionResult) {
00223                         displayerror('Invalid query. ' . $questionQuery . ' ' . mysql_error());
00224                         return false;
00225                 }
00226 
00227                 // Put in check about user's time elapsed here
00228                 if ($this->checkUserTimedOut($userId, -1, '1 MINUTE')) {
00229                         displayerror('Sorry, you have exceeded your time limit for the quiz. Your latest submission cannot be evaluated.');
00230                         return false;
00231                 }
00232 
00233                 if ($this->quizRow['quiz_allowsectionrandomaccess']) {
00234                         $sectionId = intval($_GET['sectionid']);
00235                         if ($this->checkUserTimedOut($userId, $sectionId, '1 MINUTE')) {
00236                                 displayerror('Sorry, you have exceeded your time limit for this section. Your latest submission cannot be evaluated.');
00237                                 return false;
00238                         }
00239                 }
00240 
00241                 $submittedAnswers = array();
00242                 $rollbackQuery = array();
00243                 while ($questionRow = mysql_fetch_assoc($questionResult)) {
00244                         $rollbackQuery[] = "(`quiz_sectionid` = {$questionRow['quiz_sectionid']} AND `quiz_questionid` = {$questionRow['quiz_questionid']})";
00245                         $questionType = $questionRow['quiz_questiontype'];
00246 
00247                         if (!isset($_POST['hdnQuestion' . $questionRow['quiz_sectionid'] . '_' . $questionRow['quiz_questionid']])) {
00248                                 displayerror(
00249                                         '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. ' .
00250                                         'Please do not use the navigation buttons on your browser while taking the quiz.'
00251                                 );
00252                                 return false;
00253                         }
00254 
00255                         if ($questionType == 'sso' || $questionType == 'mso') {
00256                                 $options = getQuestionOptionList($this->quizId, $questionRow['quiz_sectionid'], $questionRow['quiz_questionid']);
00257                                 if ($questionType == 'sso') {
00258                                         $fieldName = 'optAnswer' . $questionRow['quiz_sectionid'] . '_' . $questionRow['quiz_questionid'];
00259                                         $submittedAnswer = isset($_POST[$fieldName]) && is_numeric($_POST[$fieldName]) ? intval($_POST[$fieldName]) : '';
00260                                         $optionFound = false;
00261                                         for ($i = 0; $i < count($options); ++$i) {
00262                                                 if ($options[$i]['quiz_optionid'] == $submittedAnswer) {
00263                                                         $submittedAnswers[] = array($questionRow['quiz_sectionid'], $questionRow['quiz_questionid'], $questionRow['quiz_questiontype'], $submittedAnswer);
00264                                                         $optionFound = true;
00265                                                         break;
00266                                                 }
00267                                         }
00268 
00269                                         if (!$optionFound)
00270                                                 $submittedAnswers[] = array($questionRow['quiz_sectionid'], $questionRow['quiz_questionid'], $questionRow['quiz_questiontype'], '');
00271                                 }
00272                                 else {
00273                                         $submittedAnswer = array();
00274                                         for ($i = 0; $i < count($options); ++$i) {
00275                                                 $fieldName = 'chkAnswer' . $questionRow['quiz_sectionid'] . '_' . $questionRow['quiz_questionid'] . '_' . $options[$i]['quiz_optionid'];
00276                                                 if (isset($_POST[$fieldName]) && is_numeric($_POST[$fieldName]))
00277                                                         $submittedAnswer[] = intval($options[$i]['quiz_optionid']);
00278                                         }
00279                                         sort($submittedAnswer);
00280                                         $submittedAnswers[] = array($questionRow['quiz_sectionid'], $questionRow['quiz_questionid'], $questionRow['quiz_questiontype'], implode('|', $submittedAnswer));
00281                                 }
00282                         }
00283                         elseif ($questionType == 'subjective') {
00284                                 $fieldName = 'txtAnswer' . $questionRow['quiz_sectionid'] . '_' . $questionRow['quiz_questionid'];
00285                                 $submittedAnswers[] = array($questionRow['quiz_sectionid'], $questionRow['quiz_questionid'], $questionRow['quiz_questiontype'], isset($_POST[$fieldName]) ? escape($_POST[$fieldName]) : '');
00286                         }
00287                 }
00288 
00289                 $rollbackQuery = "UPDATE `quiz_answersubmissions` SET `quiz_answersubmittime` = NULL WHERE `page_modulecomponentid` = {$this->quizId} AND `user_id` = $userId AND (" . implode(' OR ', $rollbackQuery) . ")";
00290                 for ($i = 0; $i < count($submittedAnswers); ++$i) {
00291                         $updateQuery = "UPDATE `quiz_answersubmissions` SET `quiz_submittedanswer` = '{$submittedAnswers[$i][3]}', `quiz_answersubmittime` = NOW() WHERE " .
00292                                         "`page_modulecomponentid` = {$this->quizId} AND `quiz_sectionid` = {$submittedAnswers[$i][0]} AND " .
00293                                         "`quiz_questionid` = {$submittedAnswers[$i][1]} AND `user_id` = $userId";
00294                         if (!mysql_query($updateQuery)) {
00295                                 displayerror('Invalid Query. Could not save answers.');
00296                                 mysql_query($rollbackQuery);
00297                                 return false;
00298                         }
00299                 }
00300 
00301                 return true;
00302         }
00303 
00309         private function checkQuizInitialized($userId) {
00310                 $countQuery = "SELECT COUNT(*) FROM `quiz_answersubmissions` WHERE `page_modulecomponentid` = {$this->quizId} AND `user_id` = $userId";
00311                 $countResult = mysql_query($countQuery);
00312                 
00313                 $countRow = mysql_fetch_row($countResult);
00314                 
00315                 return $countRow[0] == $this->quizRow['quiz_questionspertest'];
00316         }
00317 
00323         public function initQuiz($userId) {
00324                 // a user is about to start the quiz
00325                 // generate a list of questions, insert into quiz_answersubmissions, with answersubmittime = NULL
00326                 if ($this->checkQuizInitialized($userId))
00327                         return true;
00328 
00329                 $this->deleteEntries($userId);
00330                 $sectionList = getSectionList($this->quizId);
00331                 $questionList = array();
00332                 $sections = array();
00333                 for ($i = 0; $i < count($sectionList); ++$i) {
00334                         $questionList[$i] = $this->getSectionQuestions($sectionList[$i]);
00335                         for ($j = 0; $j < count($questionList[$i]); ++$j)
00336                                 $sections[] = $i;
00337                 }
00338 
00339                 if ($this->quizRow['quiz_allowsectionrandomaccess'] == 0 && $this->quizRow['quiz_mixsections']) 
00340                         shuffle($sections);
00341 
00342                 $offsets = array_fill(0, count($questionList), 0);
00343                 for ($i = 0; $i < count($sections); ++$i) {
00344                         $insertQuery = "INSERT INTO `quiz_answersubmissions`(`page_modulecomponentid`, `quiz_sectionid`, `quiz_questionid`, `user_id`, `quiz_questionrank`) VALUES" .
00345                                         "({$this->quizId}, {$sectionList[$sections[$i]]['quiz_sectionid']}, {$questionList[$sections[$i]][$offsets[$sections[$i]]]}, $userId, $i)";
00346                         if (!mysql_query($insertQuery)) {
00347                                 displayerror('Database Error. Could not initialize quiz.');
00348                                 return false;
00349                         }
00350                         $offsets[$sections[$i]]++;
00351                 }
00352                 return true;
00353         }
00354 
00358         public function deleteEntries($userId) {
00359                 $tableNames = array('quiz_userattempts', 'quiz_answersubmissions');
00360                 $affectedRows = array();
00361                 return deleteItem($tableNames, "`page_modulecomponentid` = {$this->quizId} AND `user_id` = $userId", $affectedRows);
00362         }
00363 
00364         // Utility Functions
00365         private function getPageQuestions($userId, $sectionId = -1) {
00366                 $questionsPerPage = $this->quizRow['quiz_questionsperpage'];
00367                 $questionQuery = "SELECT `quiz_sectionid`, `quiz_questionid` FROM `quiz_answersubmissions` WHERE `user_id` = $userId AND `page_modulecomponentid` = {$this->quizId} AND `quiz_answersubmittime` IS NULL ";
00368                 if ($this->quizRow['quiz_allowsectionrandomaccess'] == 1)
00369                         $questionQuery .= " AND `quiz_sectionid` = $sectionId ";
00370                 $questionQuery .= " ORDER BY `quiz_questionrank` LIMIT $questionsPerPage";
00371                 $questionResult = mysql_query($questionQuery);
00372                 if (!$questionResult) {
00373                         displayerror('Database Error. Could not fetch questions.');
00374                         return null;
00375                 }
00376                 $questionIds = array();
00377                 while ($questionRow = mysql_fetch_row($questionResult))
00378                         $questionIds[] = $questionRow;
00379                 return $questionIds;
00380         }
00381 
00382         private function getTimerHtml($userId, $sectionId = -1) {
00383                 $testElapsedTime = $this->getElapsedTime($userId);
00384                 $testElapsedTime = explode(':', $testElapsedTime);
00385                 $testElapsedTime = implode(', ', $testElapsedTime);
00386                 $sectionElapsedTime = $this->getElapsedTime($userId,$sectionId);
00387                 $sectionElapsedTime = explode(':', $sectionElapsedTime);
00388                 $sectionElapsedTime = implode(', ', $sectionElapsedTime);
00389 
00390                 $testTime = $this->quizRow['quiz_testduration'];
00391                 $testTime = explode(':', $testTime);
00392                 $testTime = implode(', ', $testTime);
00393                 
00394                 if ($this->quizRow['quiz_allowsectionrandomaccess']) {
00395                     $sectionTime = mysql_fetch_array(mysql_query("SELECT `quiz_sectiontimelimit` FROM `quiz_sections` WHERE `page_modulecomponentid` = '{$this->quizId}' AND `quiz_sectionid` = '$sectionId'"));
00396                 
00397                     $sectionTime = $sectionTime[0];
00398                     $sectionTime = explode(':', $sectionTime);
00399                     $sectionTime = implode(', ', $sectionTime);             
00400                 $scripts[] = "var sectionTimer = new JSTimer('sectionTimerContainer', $sectionElapsedTime);\nsectionTimer.addTickHandler($sectionTime, forceQuizSubmit)";
00401                 }
00402 
00403 
00404                 $scripts[] = "var testTimer = new JSTimer('testTimerContainer', $testElapsedTime);\ntestTimer.addTickHandler($testTime, forceQuizSubmit)";
00405                 
00406                 $divs = array();
00407                 if ($this->quizRow['quiz_showquiztimer']) {
00408 
00409                         $divs[] = '<div id="testTimerContainer" class="quiz_testtimer">Total Quiz Time Elapsed: </div>';
00410 
00411                 }
00412 
00413                 if ($this->quizRow['quiz_showpagetimer']) {
00414                         $divs[] = '<div id="pageTimerContainer" class="quiz_pagetimer"></div>';
00415                         $scripts[] = "var pageTimer = new JSTimer('pageTimerContainer', 0, 0, 0);\n";
00416                 }
00417 
00418                 $sectionRow = getSectionRow($this->quizId, $sectionId);
00419                 if ($sectionRow['quiz_sectionshowlimit']) {
00420                         $sectionRow = getSectionRow($this->quizId,$sectionId);
00421                         $limit = $sectionRow['quiz_sectiontimelimit'];
00422                         $divs[] = '<div id="pageTimerlimit" class="quiz_limit">Section Limit: ' . $limit . '</div>';
00423                         $divs[] = '<div id="sectionTimerContainer" class="quiz_testtimer">Section Time Elapsed: </div>';
00424                 }
00425 
00426                 global $urlRequestRoot, $cmsFolder, $moduleFolder;
00427                 $timerScriptSrc = "$urlRequestRoot/$cmsFolder/$moduleFolder/quiz/timer.js";
00428 
00429                 if (count($divs)) {
00430                         $divs = implode("\n", $divs);
00431                         $scripts = implode("\n", $scripts);
00432 
00433                         $timerScript = <<<TIMERSCRIPT
00434                                 <script type="text/javascript" src="$timerScriptSrc"></script>
00435                                 $divs
00436                                 <script type="text/javascript">
00437                                         function forceQuizSubmit() {
00438                                                 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.");
00439                                                 var quizForm = document.getElementById('quizForm');
00440                                                 var submitButton = document.getElementById('btnSubmit');
00441                                                 submitButton.type = 'hidden';
00442                                                 quizForm.submit();
00443                                         }
00444 
00445                                         $scripts
00446                                 </script>
00447 TIMERSCRIPT;
00448                 }
00449 
00450                 return $timerScript;
00451         }
00452 
00458         private function formatQuestion($questionRow, $questionNumber = -1) {
00459                 $questionType = $questionRow['quiz_questiontype'];
00460                 if ($questionType == 'subjective') {
00461                         $fieldName = 'txtAnswer' . $questionRow['quiz_sectionid'] . '_' . $questionRow['quiz_questionid'];
00462                         $answer = '<textarea rows="6" cols="36" name="' . $fieldName . '" id="' . $fieldName . '"></textarea>';
00463                 }
00464                 else {
00465                         $optionList = getQuestionOptionList($this->quizId, $questionRow['quiz_sectionid'], $questionRow['quiz_questionid']);
00466 
00467                         $answer = '<table class="objectivecontainer" width="100%">';
00468                         for ($i = 0; $i < count($optionList); ++$i) {
00469                                 $fieldType = ($questionType == 'sso' ? 'radio' : 'checkbox');
00470                                 $fieldName = '';
00471                                 $fieldId = '';
00472                                 if ($questionType == 'sso') {
00473                                         $fieldName = 'optAnswer' . $questionRow['quiz_sectionid'] . '_' . $questionRow['quiz_questionid'];
00474                                         $fieldId = $fieldName . '_' . $optionList[$i]['quiz_optionid'];
00475                                 }
00476                                 elseif ($questionType == 'mso') {
00477                                         $fieldName = 'chkAnswer' . $questionRow['quiz_sectionid'] . '_' . $questionRow['quiz_questionid'] . '_' . $optionList[$i]['quiz_optionid'];
00478                                         $fieldId = $fieldName;
00479                                 }
00480                                 $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";
00481                         }
00482                         $answer .= '</table>';
00483                 }
00484 
00485                 $hiddenFieldName = "hdnQuestion{$questionRow['quiz_sectionid']}_{$questionRow['quiz_questionid']}";
00486 
00487                 $questionDesc = $questionRow['quiz_question'];
00488                 if ($questionNumber > 0) $questionDesc = $questionNumber . ') ' . $questionDesc;
00489 
00490                 global $sourceFolder, $moduleFolder;
00491                 require_once($sourceFolder."/latexRender.class.php");
00492                 $render = new latexrender();
00493                 $questionDesc = $render->transform($questionDesc);
00494                 $answer = $render->transform($answer);
00495 
00496                 return <<<QUESTIONFORM
00497                         <input type="hidden" name="$hiddenFieldName" id="$hiddenFieldName" value="" />
00498                         <div class="quiz_questioncontainer">
00499                                 {$questionDesc}
00500                         </div>
00501                         <div class="quiz_answercontainer">
00502                                 $answer
00503                         </div>
00504 QUESTIONFORM;
00505         }
00506 
00510         private function formatNextPage($userId, $sectionId = -1) {
00511                 $questionCount = $this->quizRow['quiz_questionsperpage'];
00512                 $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` " .
00513                                 "FROM `quiz_questions`, `quiz_answersubmissions` WHERE " .
00514                                 "`quiz_questions`.`page_modulecomponentid` = {$this->quizId} AND " .
00515                                 "`quiz_answersubmissions`.`user_id` = $userId AND " .
00516                                 "`quiz_questions`.`page_modulecomponentid` = `quiz_answersubmissions`.`page_modulecomponentid` AND " .
00517                                 "`quiz_questions`.`quiz_sectionid` = `quiz_answersubmissions`.`quiz_sectionid` AND " .
00518                                 "`quiz_questions`.`quiz_questionid` = `quiz_answersubmissions`.`quiz_questionid` AND " .
00519                                 "`quiz_answersubmissions`.`quiz_answersubmittime` IS NULL ";
00520                 if ($this->quizRow['quiz_allowsectionrandomaccess'] == 1)
00521                         $questionQuery .= "AND `quiz_answersubmissions`.`quiz_sectionid` = $sectionId ";
00522                 $questionQuery .= "ORDER BY `quiz_answersubmissions`.`quiz_questionrank` " .
00523                                 "LIMIT $questionCount";
00524 
00525                 $questionResult = mysql_query($questionQuery);
00526 
00527                 $questionNumber = 1;
00528                 $questionPage = $this->getTimerHtml($userId, $sectionId);
00529                 $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?\')">';
00530                 while ($questionRow = mysql_fetch_assoc($questionResult)) {
00531                         if (is_null($questionRow['quiz_questionviewtime']))
00532                                 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']}");
00533                         $questionPage .= $this->formatQuestion($questionRow, $questionNumber);
00534                         ++$questionNumber;
00535                 }
00536                 $questionPage .= '<input type="submit" name="btnSubmit" id="btnSubmit" value="Submit" />';
00537                 $questionPage .= '</form>';
00538 
00539                 $questionPage .= <<<QUESTIONPAGESCRIPT
00540                 <script type="text/javascript">
00541                         // make opt buttons uncheckable
00542                         var inputFields = document.getElementById('quizForm').getElementsByTagName('input');
00543                         for (var i = 0; i < inputFields.length; ++i) {
00544                                 if (inputFields[i].type == 'radio')
00545                                         inputFields[i].onclick = function(e) {
00546                                                 if (this.rel == 'checked') {
00547                                                         this.checked = false;
00548                                                         this.rel = '';
00549                                                 }
00550                                                 else {
00551                                                         var elements = document.getElementsByName(this.name);
00552                                                         for (var i = 0; i < elements.length; ++i) {
00553                                                                 elements[i].rel = '';
00554                                                                 elements[i].checked = false;
00555                                                         }
00556                                                         this.checked = true;
00557                                                         this.rel = 'checked';
00558                                                 }
00559                                         };
00560                         }
00561                 </script>
00562 QUESTIONPAGESCRIPT;
00563                 return $questionPage;
00564         }
00565 
00572         private function countAttemptedQuestions($userId, $sectionId = -1) {
00573                 $countQuery = "SELECT COUNT(*) FROM `quiz_submittedanswers` WHERE `page_modulecomponentid` = {$this->quizId}";
00574                 if ($sectionId != -1)
00575                         $countQuery .= " AND `quiz_sectionid` = $sectionId";
00576                 $countQuery .= " `user_id` = $userId AND `quiz_answersubmittime` IS NOT NULL";
00577                 $countResult = mysql_query($countQuery);
00578                 if (!$countResult) {
00579                         displayerror('Database Error. Could not retrieve user attempt information.');
00580                         return false;
00581                 }
00582                 $countRow = mysql_fetch_row($countResult);
00583                 return $countRow[0];
00584         }
00585 
00586         private function getSectionQuestions($sectionRow) {
00587                 $questionTypes = array_keys(getQuestionTypes());
00588                 $sectionId = $sectionRow['quiz_sectionid'];
00589 
00590                 if ($sectionRow['quiz_sectionquestionshuffled'] == 0) {
00591                         $limit = 0;
00592                         for ($i = 0; $i < count($questionTypes); ++$i)
00593                                 $limit += $sectionRow["quiz_section{$questionTypes[$i]}count"];
00594                         $questionQuery = "SELECT `quiz_questionid` FROM `quiz_questions` WHERE `page_modulecomponentid` = {$this->quizId} AND `quiz_sectionid` = $sectionId ORDER BY `quiz_questionrank` LIMIT $limit";
00595                 }
00596                 else {
00597                         $questionIdQueries = array();
00598                         for ($i = 0; $i < count($questionTypes); ++$i) {
00599                                 $limit = $sectionRow["quiz_section{$questionTypes[$i]}count"];
00600                                 if ($limit) {
00601                                         $questionIdQueries[] = 
00602                                                 "(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)";
00603                                 }
00604                         }
00605 
00606                         $questionQuery = "SELECT `quiz_questionid` FROM (" . implode(' UNION ', $questionIdQueries) . ") AS `questions` ORDER BY RAND()";
00607                 }
00608 
00609                 $questionIds = array();
00610                 $questionResult = mysql_query($questionQuery) or die(mysql_error());
00611                 while ($questionRow = mysql_fetch_row($questionResult))
00612                         $questionIds[] = $questionRow[0];
00613                 return $questionIds;
00614         }
00615 
00622         private function checkQuizCompleted($userId) {
00623                 $countQuery = "SELECT COUNT(*) FROM `quiz_userattempts`, `quiz_sections` WHERE " .
00624                                 "`quiz_sections`.`page_modulecomponentid` = `quiz_userattempts`.`page_modulecomponentid` AND " .
00625                                 "`quiz_sections`.`quiz_sectionid` = `quiz_userattempts`.`quiz_sectionid` AND " .
00626                                 "`quiz_sections`.`page_modulecomponentid` = {$this->quizId} AND " .
00627                                 "`quiz_userattempts`.`user_id` = $userId AND " .
00628                                 "`quiz_submissiontime` IS NOT NULL";
00629                 $countResult = mysql_query($countQuery);
00630                 if (!$countResult) {
00631                         displayerror('Database Error. Could not fetch section information.');
00632                         return false;
00633                 }
00634                 $countRow = mysql_fetch_row($countResult);
00635                 $completedCount = $countRow[0];
00636                 $countQuery = "SELECT COUNT(*) FROM `quiz_sections` WHERE `page_modulecomponentid` = {$this->quizId}";
00637                 $countResult = mysql_query($countQuery);
00638                 $countRow = mysql_fetch_row($countResult);
00639                 return $countRow[0] == $completedCount;
00640         }
00641 
00647         private function isValidId($id) {
00648                 return isset($id) && is_numeric($id) && $id > 0;
00649         }
00650 
00655         private function markSectionCompleted($userId, $sectionId = -1) {
00656                 if ($sectionId == -1) {
00657                         $sections = getSectionList($this->quizId);
00658                         $allOk = true;
00659                         for ($i = 0; $i < count($sections); ++$i)
00660                                 $allOk = $this->markSectionCompleted($userId, $sections[$i]['quiz_sectionid']) && $allOk;
00661                         return $allOk;
00662                 }
00663 
00664                 $attemptRow = getAttemptRow($this->quizId, $sectionId, $userId);
00665                 if (is_null($attemptRow['quiz_submissiontime'])) {
00666                         // Check if all questions for this section have been completed, if yes, set quiz_submissiontime and return true
00667                         $questionQuery = "SELECT COUNT(*) FROM `quiz_answersubmissions` WHERE " .
00668                                         "`page_modulecomponentid` = {$this->quizId} AND `quiz_sectionid` = $sectionId AND `user_id` = $userId AND `quiz_answersubmittime` IS NULL";
00669                         $questionResult = mysql_query($questionQuery);
00670                         $questionRow = mysql_fetch_row($questionResult);
00671 
00672                         if ($questionRow[0] != 0)
00673                                 return false;
00674 
00675                         $updateQuery = "UPDATE `quiz_userattempts` SET `quiz_submissiontime` = NOW() WHERE `page_modulecomponentid` = $this->quizId AND `quiz_sectionid` = $sectionId AND `user_id` = $userId";
00676                         if (mysql_query($updateQuery))
00677                                 return true;
00678                         else {
00679                                 displayerror('Database Error. Could not mark section as completed.');
00680                                 return -1;
00681                         }
00682                 }
00683                 else
00684                         return true;
00685         }
00686 
00692         private function markQuizCompleted($userId) {
00693                 $updateQueries = array(
00694                         "UPDATE `quiz_answersubmissions` SET `quiz_submittedanswer` = '', `quiz_answersubmittime` = NOW() WHERE `page_modulecomponentid` = {$this->quizId} AND `user_id` = $userId AND `quiz_answersubmittime` IS NULL",
00695                         "UPDATE `quiz_userattempts` SET `quiz_submissiontime` = NOW() WHERE `page_modulecomponentid` = {$this->quizId} AND `user_id` = $userId AND `quiz_submissiontime` IS NULL"
00696                 );
00697 
00698                 if (!mysql_query($updateQueries[0]) || !mysql_query($updateQueries[1])) {
00699                         displayerror('Error. Could not mark quiz as completed.');
00700                         return false;
00701                 }
00702 
00703                 return true;
00704         }
00705 
00711         private function getElapsedTime($userId, $sectionId = -1) {
00712                 if ($sectionId < 0)
00713                         $elapsedQuery = "SELECT TIMEDIFF(NOW(), MIN(`quiz_attemptstarttime`)) FROM `quiz_userattempts` WHERE " .
00714                                         "`page_modulecomponentid` = {$this->quizId} AND `user_id` = $userId";
00715                 else
00716                         $elapsedQuery = "SELECT TIMEDIFF(NOW(), `quiz_attemptstarttime`) FROM `quiz_userattempts` WHERE " .
00717                                         "`page_modulecomponentid` = {$this->quizId} AND `quiz_sectionid` = $sectionId AND `user_id` = $userId";
00718 
00719                 $elapsedResult = mysql_query($elapsedQuery);
00720                 if (!$elapsedResult)
00721                         displayerror('Error. ' . $elapsedQuery . '<br />' . mysql_error());
00722                 $elapsedRow = mysql_fetch_row($elapsedResult);
00723                 return $elapsedRow[0];
00724         }
00725 
00726         private function getRemainingTime($userId, $sectionId = -1) {
00727                 if ($sectionId < 0) {
00728                         $remainingQuery = "SELECT TIMEDIFF(NOW(), ADDTIME(MIN(`quiz_attemptstarttime`), '{$this->quizRow['quiz_testduration']}')) FROM `quiz_userattempts` WHERE " .
00729                                         "`page_modulecomponentid` = {$this->quizId} AND `user_id` = $userId";
00730                 }
00731                 else {
00732                         $remainingQuery = "SELECT TIMEDIFF(NOW(), ADDTIME(`quiz_attemptstarttime`, '{$this->quizRow['quiz_testduration']}')) FROM `quiz_userattempts` WHERE " .
00733                                         "`page_modulecomponentid` = {$this->quizId} AND `user_id` = $userId";
00734                 }
00735 
00736                 $remainingResult = mysql_query($remainingQuery);
00737                 $remainingRow = mysql_fetch_row($remainingResult);
00738                 return $remainingRow[0];
00739         }
00740 
00748         private function checkUserTimedOut($userId, $sectionId = -1, $offset = '0 SECOND') {
00749                 if ($sectionId < 0) {
00750                         // Check if the quiz has timed out:
00751                         //  Find the earliest attempt start time, add quiz duration to it
00752                         //      add offset to now, and compare
00753                         $timeoutQuery = "SELECT IF(DATE_SUB(NOW(), INTERVAL $offset) > ADDTIME(MIN(`quiz_attemptstarttime`), '{$this->quizRow['quiz_testduration']}'), 1, 0) AS `quiz_expired` FROM " .
00754                                         "`quiz_userattempts` WHERE `page_modulecomponentid` = {$this->quizId} AND `user_id` = $userId";
00755                 }
00756                 else {
00757                         $sectionRow = getSectionRow($this->quizId, $sectionId);
00758 
00759                         if ($sectionRow['quiz_sectiontimelimit'] == '00:00:00')
00760                                 return false;
00761 
00762                         $timeoutQuery = "SELECT IF(DATE_SUB(NOW(), INTERVAL $offset) > ADDTIME(`quiz_attemptstarttime`, '{$sectionRow['quiz_sectiontimelimit']}'), 1, 0) AS `quiz_expired` FROM " .
00763                                         "`quiz_userattempts` WHERE `page_modulecomponentid` = {$this->quizId} AND `quiz_sectionid` = $sectionId AND `user_id` = $userId";
00764                 }
00765 
00766                 $timeoutResult = mysql_query($timeoutQuery);
00767                 if (!$timeoutResult) {
00768                         displayerror('Database Error. Could not retrieve time information.');
00769                         return -1;
00770                 }
00771 
00772                 $timeoutRow = mysql_fetch_row($timeoutResult);
00773                 if (is_null($timeoutRow[0])) {
00774                         // An invalid Section ID was passed => we could not find a row for the user for that
00775                         // Section ID. assume he timed out
00776                         return true;
00777                 }
00778 
00779                 return $timeoutRow[0];
00780         }
00781 
00788         private function forceQuizCompleted($userId, $sectionId = -1) {
00789                 $updateQuery = "UPDATE `quiz_userattempts` SET `quiz_submissiontime` = NOW() WHERE `quiz_submissiontime` IS NULL AND `page_modulecomponentid` = {$this->quizId} AND `user_id` = $userId";
00790                 if ($sectionId >= 0)
00791                         $updateQuery .= " AND `quiz_sectionid` = $sectionId";
00792                 if (!mysql_query($updateQuery)) {
00793                         displayerror('Database Error. Could not mark quiz as completed.');
00794                         return false;
00795                 }
00796                 return true;
00797         }
00798 };

Generated on Sun Jan 2 2011 04:55:32 for Pragyan CMS by  doxygen 1.7.1