$cmd = null; } if (isset($item_list['1']) && is_numeric($item_list['1'])) { $quId = (int) $item_list['1']; } else { $quId = null; } if (isset($item_list['2']) && is_numeric($item_list['2'])) { $exId = (int) $item_list['2']; } else { $exId = null; } if ($cmd == 'download') { // find exercise informations $exercise = new Exercise(); if ($exercise->load($exId) || $is_allowedToEdit) { if ($exercise->getVisibility() == 'VISIBLE' || $is_allowedToEdit) { $question = new Question(); if ($question->load($quId)) { $attachmentFile = $question->getQuestionDirSys() . $question->getAttachment(); if (claro_send_file($attachmentFile)) { die; } else { $dialogBox->error(get_lang('Not found')); } } else { $dialogBox->error(get_lang('Not found')); } } else { $dialogBox->error(get_lang('Not allowed')); }
$quId = (int) $_REQUEST['quId']; } else { $quId = null; } if (isset($_REQUEST['filter'])) { $filter = $_REQUEST['filter']; } else { $filter = 'all'; } $categoryId = substr($filter, 0, 10) == 'categoryId' && is_numeric(substr($filter, 10)) ? substr($filter, 10) : null; /* * Init other vars */ $exercise = new Exercise(); if (!is_null($exId)) { $exercise->load($exId); } $dialogBox = new DialogBox(); /* * Execute commands */ // use question in exercise if ($cmd == 'rqUse' && !is_null($quId) && !is_null($exId)) { if ($exercise->addQuestion($quId)) { // TODO show confirmation and back link header('Location: ' . Url::Contextualize('edit_exercise.php?exId=' . $exId)); } } // delete question if ($cmd == 'delQu' && !is_null($quId)) { $question = new Question();
} if (isset($_REQUEST['exId']) && is_numeric($_REQUEST['exId'])) { $exId = (int) $_REQUEST['exId']; } else { $exId = null; } if (isset($_REQUEST['quId']) && is_numeric($_REQUEST['quId'])) { $quId = (int) $_REQUEST['quId']; } else { $quId = null; } /* * Init other vars */ $exercise = new Exercise(); if (!is_null($exId) && !$exercise->load($exId)) { $cmd = 'rqEdit'; } $dialogBox = new DialogBox(); $displayForm = false; $displaySettings = true; /* * Execute commands */ if ($cmd == 'rmQu' && !is_null($quId)) { $exercise->removeQuestion($quId); } if ($cmd == 'mvUp' && !is_null($quId)) { $exercise->moveQuestionUp($quId); } if ($cmd == 'mvDown' && !is_null($quId)) {
/** * Send a complete exercise in IMS/QTI format, from its ID * * @param int $exerciseId The exercise to exporte * @param boolean $standalone Wether it should include XML tag and DTD line. * @return The XML as a string, or an empty string if there's no exercise with given ID. * @author Amand Tihon <*****@*****.**> */ function export_exercise($exerciseId, $standalone = True) { $exercise = new Exercise(); if (!$exercise->load($exerciseId)) { return ''; } $ims = new ImsSection($exercise); $xml = $ims->export($standalone); return $xml; }
$quId = (int) $_REQUEST['quId']; } else { $quId = null; } /* * Init other vars */ $question = new Question(); if (is_null($quId) || !$question->load($quId)) { header('Location: ' . Url::Contextualize('../exercise.php')); exit; } if (!is_null($exId)) { $exercise = new Exercise(); // if exercise cannot be load set exId to null , it probably don't exist if (!$exercise->load($exId)) { $exId = null; } } $askDuplicate = false; // do not duplicate when there is no $exId, it means that we modify the question from pool // do not duplicate when there is no $quId, it means that question is a new one // check that question is used in several exercises if (count_exercise_using_question($quId) > 1 && !is_null($quId) && !is_null($exId)) { $askDuplicate = true; } $dialogBox = new DialogBox(); /* * Execute commands */ if ($cmd == 'exEdit') {
function export_exercise_tracking($exId) { $exercise = new Exercise(); if (!$exercise->load($exId)) { return ""; } $questionList = $exercise->getQuestionList(); $exerciseCsv = ''; foreach ($questionList as $question) { $exerciseCsv .= export_question_tracking($question['id'], $exId); } return $exerciseCsv; }
/** * Create files (quiz) needed in the export of this module * * @copyright (c) 2001-2011, Universite catholique de Louvain (UCL) * @param int $quizId id of the Quiz * @param object $item item of the path * @param string $destDir path when the files need to be copied * @param int $deepness deepness of the destinationd directory * @return boolean */ public function prepareFiles($quizId, &$item, $destDir, $deepness) { $completionThresold = $item->getCompletionThreshold(); if (empty($completionThresold)) { $completionThresold = 50; } $quizId = (int) $quizId; $quiz = new Exercise(); if (!$quiz->load($quizId)) { $this->error[] = get_lang('Unable to load the exercise'); return false; } $deep = ''; if ($deepness) { for ($i = $deepness; $i > 0; $i--) { $deep .= ' ../'; } } // Generate standard page header $pageHeader = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>' . $quiz->getTitle() . '</title> <meta http-equiv="expires" content="Tue, 05 DEC 2000 07:00:00 GMT"> <meta http-equiv="Pragma" content="no-cache"> <meta http-equiv="Content-Type" content="text/HTML; charset=' . get_locale('charset') . '" /> <link rel="stylesheet" type="text/css" href="' . $deep . get_conf('claro_stylesheet') . '/main.css" media="screen, projection, tv" /> <script language="javascript" type="text/javascript" src="' . $deep . 'js/jquery.js"></script> <script language="javascript" type="text/javascript" src="' . $deep . 'js/claroline.js"></script> <script language="javascript" type="text/javascript" src="' . $deep . 'js/claroline.ui.js"></script> <script language="javascript" type="text/javascript" src="' . $deep . 'js/APIWrapper.js"></script> <script language="javascript" type="text/javascript" src="' . $deep . 'js/connector13.js"></script> <script language="javascript" type="text/javascript" src="' . $deep . 'js/scores.js"></script> </head> ' . "\n"; $pageBody = '<body onload="loadPage()"> <div id="claroBody"><form id="quiz"> <table width="100%" border="0" cellpadding="1" cellspacing="0" class="claroTable">' . "\n"; // Get the question list $questionList = $quiz->getQuestionList(); $questionCount = count($questionList); // Keep track of raw scores (ponderation) for each question $questionPonderationList = array(); // Keep track of correct texts for fill-in type questions // TODO La variable $fillAnswerList n'apparaît qu'une fois $fillAnswerList = array(); // Display each question $questionCount = 0; foreach ($questionList as $question) { // Update question number $questionCount++; // read the question, abort on error $scormQuestion = new ScormQuestion(); if (!$scormQuestion->load($question['id'])) { $this->error[] = get_lang('Unable to load exercise\'s question'); return false; } $questionPonderationList[] = $scormQuestion->getGrade(); $pageBody .= '<thead>' . "\n" . '<tr>' . "\n" . '<th>' . get_lang('Question') . ' ' . $questionCount . '</th>' . "\n" . '</tr>' . "\n" . '</thead>' . "\n"; $pageBody .= '<tr>' . "\n" . '<td>' . "\n" . $scormQuestion->export() . "\n" . '</td>' . "\n" . '</tr>' . "\n"; } $pageEnd = ' <tr> <td align="center"><br /><input type="button" value="' . get_lang('Ok') . '" onclick="calcScore()" /></td> </tr> </table> </form> </div></body></html>' . "\n"; /* Generate the javascript that'll calculate the score * We have the following variables to help us : * $idCounter : number of elements to check. their id are "scorm_XY" * $raw_to_pass : score (on 100) needed to pass the quiz * $fillAnswerList : a list of arrays (text, score) indexed on <input>'s names * */ $pageHeader .= ' <script type="text/javascript" language="javascript"> var raw_to_pass = '******'; var weighting = ' . array_sum($questionPonderationList) . '; var rawScore; var scoreCommited = false; var showScore = true; var fillAnswerList = new Array();' . "\n"; // This is the actual code present in every exported exercise. // use claro_html_entity_decode in output to prevent double encoding errors with some languages... $pageHeader .= ' function calcScore() { if( !scoreCommited ) { rawScore = CalculateRawScore(document, ' . getIdCounter() . ', fillAnswerList); var score = Math.max(Math.round(rawScore * 100 / weighting), 0); var oldScore = doLMSGetValue("cmi.score.raw"); doLMSSetValue("cmi.score.max", weighting); doLMSSetValue("cmi.score.min", 0); computeTime(); if (score > oldScore) // Update only if score is better than the previous time. { doLMSSetValue("cmi.raw", rawScore); } var oldStatus = doLMSGetValue( "cmi.completion_status" ) if (score >= raw_to_pass) { doLMSSetValue("cmi.completion_status", "completed"); } else if (oldStatus != "completed" ) // If passed once, never mark it as failed. { doLMSSetValue("cmi.completion_status", "failed"); } doLMSCommit(); doLMSFinish(); scoreCommited = true; if(showScore) alert(\'' . clean_str_for_javascript(claro_html_entity_decode(get_lang('Score'))) . ' :\\n\' + rawScore + \'/\' + weighting ); } } </script> '; // Construct the HTML file and save it. $filename = "quiz_" . $quizId . ".html"; $pageContent = $pageHeader . $pageBody . $pageEnd; if (!($f = fopen($destDir . '/' . $filename, 'w'))) { $this->error = get_lang('Unable to create file : ') . $filename; return false; } fwrite($f, $pageContent); fclose($f); return true; }
} $dialogBox = new DialogBox(); /** * Handle SESSION * - refresh data in session if required * - copy session content locally to use local var in script * - */ $resetQuestionList = false; // if exercise is not in session try to load it. // if exId has been defined in request force refresh of exercise in session if (!isset($_SESSION['serializedExercise']) || !is_null($exId)) { // clean previous exercise if any unset($_SESSION['serializedExercise']); $exercise = new Exercise(); if (is_null($exId) || !$exercise->load($exId)) { // exercise is required header("Location: " . Url::Contextualize('./exercise.php')); exit; } else { // load successfull // exercise must be visible or in learning path to be displayed to a student if ($exercise->getVisibility() != 'VISIBLE' && !$is_allowedToEdit && !($inOldLP || $inLP)) { $dialogBox->error(get_lang('The exercise is not available')); $content = $dialogBox->render(); $claroline->display->body->appendContent($content); echo $claroline->display->render(); //header("Location: ./exercise.php"); exit; } else { $_SESSION['serializedExercise'] = serialize($exercise);
/** * Exports an exercise as a SCO. * This method is intended to be called from the prepare method. * *@note There's a lot of nearly cut-and-paste from exercise.lib.php here * because of some little differences... * Perhaps something that could be refactorised ? * * @see prepare * @param $quizId The quiz * @param $raw_to_pass The needed score to attain * @return False on error, True if everything went well. * @author Amand Tihon <*****@*****.**> */ public function prepareQuiz($quizId, $raw_to_pass = 50) { global $claro_stylesheet; // those two variables are needed by display_attached_file() global $attachedFilePathWeb; global $attachedFilePathSys; $attachedFilePathWeb = 'Exercises'; $attachedFilePathSys = $this->destDir . '/Exercises'; // read the exercise $quiz = new Exercise(); if (!$quiz->load($quizId)) { $this->error[] = get_lang('Unable to load the exercise'); return false; } // Generate standard page header $pageHeader = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>' . $quiz->getTitle() . '</title> <meta http-equiv="expires" content="Tue, 05 DEC 2000 07:00:00 GMT"> <meta http-equiv="Pragma" content="no-cache"> <meta http-equiv="Content-Type" content="text/HTML; charset=' . get_locale('charset') . '" /> <link rel="stylesheet" type="text/css" href="' . get_conf('claro_stylesheet') . '/main.css" media="screen, projection, tv" /> <script language="javascript" type="text/javascript" src="jquery.js"></script> <script language="javascript" type="text/javascript" src="claroline.js"></script> <script language="javascript" type="text/javascript" src="claroline.ui.js"></script> <script language="javascript" type="text/javascript" src="APIWrapper.js"></script> <script language="javascript" type="text/javascript" src="scores.js"></script> ' . "\n"; $pageBody = '<body onload="loadPage()"> <div id="claroBody"><form id="quiz"> <table width="100%" border="0" cellpadding="1" cellspacing="0" class="claroTable">' . "\n"; // Get the question list $questionList = $quiz->getQuestionList(); $questionCount = count($questionList); // Keep track of raw scores (ponderation) for each question $questionPonderationList = array(); // Keep track of correct texts for fill-in type questions // TODO La variable $fillAnswerList n'appara�t qu'une fois $fillAnswerList = array(); // Display each question $questionCount = 0; foreach ($questionList as $question) { // Update question number $questionCount++; // read the question, abort on error $scormQuestion = new ScormQuestion(); if (!$scormQuestion->load($question['id'])) { $this->error[] = get_lang('Unable to load exercise\'s question'); return false; } $questionPonderationList[] = $scormQuestion->getGrade(); $pageBody .= '<tr class="headerX">' . "\n" . '<th>' . get_lang('Question') . ' ' . $questionCount . '</th>' . "\n" . '</tr>' . "\n"; $pageBody .= '<tr>' . "\n" . '<td>' . "\n" . $scormQuestion->export() . "\n" . '</td>' . "\n" . '</tr>' . "\n"; /* if( !empty($scormQuestion->getAttachment()) ) { // copy the attached file if ( !claro_copy_file($this->srcDirExercise . '/' . $attachedFile, $this->destDir . '/Exercises') ) { $this->error[] = get_lang('Unable to copy file : %filename', array ( '%filename' => $attachedFile )); return false; } // Ok, if it was an mp3, we need to copy the flash mp3-player too. $extension=substr(strrchr($attachedFile, '.'), 1); if ( $extension == 'mp3') $this->mp3Found = true; $pageBody .= '<tr><td colspan="2">' . display_attached_file($attachedFile) . '</td></tr>' . "\n"; } */ /* * Display the possible answers */ // End of the question } // foreach($questionList as $questionId) // No more questions, add the button. $pageEnd = ' <tr> <td align="center"><br /><input type="button" value="' . get_lang('Ok') . '" onclick="calcScore()" /></td> </tr> </table> </form> </div></body></html>' . "\n"; /* Generate the javascript that'll calculate the score * We have the following variables to help us : * $idCounter : number of elements to check. their id are "scorm_XY" * $raw_to_pass : score (on 100) needed to pass the quiz * $fillAnswerList : a list of arrays (text, score) indexed on <input>'s names * */ $pageHeader .= ' <script type="text/javascript" language="javascript"> var raw_to_pass = '******'; var weighting = ' . array_sum($questionPonderationList) . '; var rawScore; var scoreCommited = false; var showScore = true; var fillAnswerList = new Array();' . "\n"; // This is the actual code present in every exported exercise. // use claro_html_entity_decode in output to prevent double encoding errors with some languages... $pageHeader .= ' function calcScore() { if( !scoreCommited ) { rawScore = CalculateRawScore(document, ' . getIdCounter() . ', fillAnswerList); var score = Math.max(Math.round(rawScore * 100 / weighting), 0); var oldScore = doLMSGetValue("cmi.core.score.raw"); doLMSSetValue("cmi.core.score.max", weighting); doLMSSetValue("cmi.core.score.min", 0); computeTime(); if (score > oldScore) // Update only if score is better than the previous time. { doLMSSetValue("cmi.core.score.raw", rawScore); } var mode = doLMSGetValue( "cmi.core.lesson_mode" ); if ( mode != "review" && mode != "browse" ) { var oldStatus = doLMSGetValue( "cmi.core.lesson_status" ) if (score >= raw_to_pass) { doLMSSetValue("cmi.core.lesson_status", "passed"); } else if (oldStatus != "passed" ) // If passed once, never mark it as failed. { doLMSSetValue("cmi.core.lesson_status", "failed"); } } doLMSCommit(); doLMSFinish(); scoreCommited = true; if(showScore) alert(\'' . clean_str_for_javascript(claro_html_entity_decode(get_lang('Score'))) . ' :\\n\' + rawScore + \'/\' + weighting ); } } </script> '; // Construct the HTML file and save it. $filename = "quiz_" . $quizId . ".html"; $pageContent = $pageHeader . $pageBody . $pageEnd; if (!($f = fopen($this->destDir . '/' . $filename, 'w'))) { $this->error[] = get_lang('Unable to create file : ') . $filename; return false; } fwrite($f, $pageContent); fclose($f); // Went well. return True; }