// kai me to katallhlo hidden pedio echo "<form method='GET' action='backFromExercise.php'><input type='hidden' name='course' value='$course_code'>" . "<input type='hidden' name='op' value='finish'>"; $i = $totalScore = $totalWeighting = 0; // for each question foreach ($_SESSION['questionList'][$exerciseId] as $questionId) { // gets the student choice for this question $choice = @$_SESSION['exerciseResult'][$exerciseId][$questionId]; // creates a temporary Question object $objQuestionTmp = new Question(); $objQuestionTmp->read($questionId); $questionName = $objQuestionTmp->selectTitle(); $questionDescription = $objQuestionTmp->selectDescription(); $questionDescription_temp = nl2br(make_clickable($questionDescription)); $questionDescription_temp = mathfilter($questionDescription_temp, 12, "$webDir/courses/mathimg/"); $questionWeighting = $objQuestionTmp->selectWeighting(); $answerType = $objQuestionTmp->selectType(); // destruction of the Question object unset($objQuestionTmp); if ($answerType == UNIQUE_ANSWER || $answerType == MULTIPLE_ANSWER || $answerType == TRUE_FALSE) { $colspan = 4; } elseif ($answerType == MATCHING) { $colspan = 2; } else { $colspan = 1;
/** * Shows a question * @param Question $objQuestionTmp * @param bool $only_questions if true only show the questions, no exercise title * @param bool $origin origin i.e = learnpath * @param string $current_item current item from the list of questions * @param bool $show_title * @param bool $freeze * @param array $user_choice * @param bool $show_comment * @param null $exercise_feedback * @param bool $show_answers * @param null $modelType * @param bool $categoryMinusOne * @return bool|null|string */ public function showQuestion(Question $objQuestionTmp, $only_questions = false, $origin = false, $current_item = '', $show_title = true, $freeze = false, $user_choice = array(), $show_comment = false, $exercise_feedback = null, $show_answers = false, $modelType = null, $categoryMinusOne = true) { // Text direction for the current language //$is_ltr_text_direction = api_get_text_direction() != 'rtl'; // Change false to true in the following line to enable answer hinting $debug_mark_answer = $show_answers; //api_is_allowed_to_edit() && false; // Reads question information if (!$objQuestionTmp) { // Question not found return false; } $html = null; $questionId = $objQuestionTmp->id; if ($exercise_feedback != EXERCISE_FEEDBACK_TYPE_END) { $show_comment = false; } $answerType = $objQuestionTmp->selectType(); $pictureName = $objQuestionTmp->selectPicture(); $s = null; $form = new FormValidator('question'); $renderer = $form->defaultRenderer(); $form_template = '{content}'; $renderer->setFormTemplate($form_template); if ($answerType != HOT_SPOT && $answerType != HOT_SPOT_DELINEATION) { // Question is not a hotspot if (!$only_questions) { $questionDescription = $objQuestionTmp->selectDescription(); if ($show_title) { $categoryName = TestCategory::getCategoryNamesForQuestion($objQuestionTmp->id, null, true, $categoryMinusOne); $html .= $categoryName; $html .= Display::div($current_item . '. ' . $objQuestionTmp->selectTitle(), array('class' => 'question_title')); if (!empty($questionDescription)) { $html .= Display::div($questionDescription, array('class' => 'question_description')); } } else { $html .= '<div class="media">'; $html .= '<div class="pull-left">'; $html .= '<div class="media-object">'; $html .= Display::div($current_item, array('class' => 'question_no_title')); $html .= '</div>'; $html .= '</div>'; $html .= '<div class="media-body">'; if (!empty($questionDescription)) { $html .= Display::div($questionDescription, array('class' => 'question_description')); } $html .= '</div>'; $html .= '</div>'; } } if (in_array($answerType, array(FREE_ANSWER, ORAL_EXPRESSION)) && $freeze) { return null; } $html .= '<div class="question_options">'; // construction of the Answer object (also gets all answers details) $objAnswerTmp = new Answer($questionId, null, $this); $nbrAnswers = $objAnswerTmp->selectNbrAnswers(); $course_id = api_get_course_int_id(); $quiz_question_options = Question::readQuestionOption($questionId, $course_id); // For "matching" type here, we need something a little bit special // because the match between the suggestions and the answers cannot be // done easily (suggestions and answers are in the same table), so we // have to go through answers first (elems with "correct" value to 0). $select_items = array(); //This will contain the number of answers on the left side. We call them // suggestions here, for the sake of comprehensions, while the ones // on the right side are called answers $num_suggestions = 0; if ($answerType == MATCHING || $answerType == DRAGGABLE) { if ($answerType == DRAGGABLE) { $s .= '<div class="ui-widget ui-helper-clearfix"> <ul class="drag_question ui-helper-reset ui-helper-clearfix">'; } else { $s .= '<div id="drag' . $questionId . '_question" class="drag_question">'; $s .= '<table class="data_table">'; } $j = 1; //iterate through answers $letter = 'A'; //mark letters for each answer $answer_matching = array(); $capital_letter = array(); //for ($answerId=1; $answerId <= $nbrAnswers; $answerId++) { foreach ($objAnswerTmp->answer as $answerId => $answer_item) { $answerCorrect = $objAnswerTmp->isCorrect($answerId); $answer = $objAnswerTmp->selectAnswer($answerId); if ($answerCorrect == 0) { // options (A, B, C, ...) that will be put into the list-box // have the "correct" field set to 0 because they are answer $capital_letter[$j] = $letter; //$answer_matching[$j]=$objAnswerTmp->selectAnswerByAutoId($numAnswer); $answer_matching[$j] = array('id' => $answerId, 'answer' => $answer); $j++; $letter++; } } $i = 1; $select_items[0]['id'] = 0; $select_items[0]['letter'] = '--'; $select_items[0]['answer'] = ''; foreach ($answer_matching as $id => $value) { $select_items[$i]['id'] = $value['id']; $select_items[$i]['letter'] = $capital_letter[$id]; $select_items[$i]['answer'] = $value['answer']; $i++; } $num_suggestions = $nbrAnswers - $j + 1; } elseif ($answerType == FREE_ANSWER) { $content = isset($user_choice[0]) && !empty($user_choice[0]['answer']) ? $user_choice[0]['answer'] : null; $toolBar = 'TestFreeAnswer'; if ($modelType == EXERCISE_MODEL_TYPE_COMMITTEE) { $toolBar = 'TestFreeAnswerStrict'; } $form->addElement('html_editor', "choice[" . $questionId . "]", null, array('id' => "choice[" . $questionId . "]"), array('ToolbarSet' => $toolBar)); $form->setDefaults(array("choice[" . $questionId . "]" => $content)); $s .= $form->return_form(); } elseif ($answerType == ORAL_EXPRESSION) { // Add nanogong if (api_get_setting('document.enable_nanogong') == 'true') { //@todo pass this as a parameter global $exercise_stat_info, $exerciseId; if (!empty($exercise_stat_info)) { $params = array('exercise_id' => $exercise_stat_info['exe_exo_id'], 'exe_id' => $exercise_stat_info['exe_id'], 'question_id' => $questionId); } else { $params = array('exercise_id' => $exerciseId, 'exe_id' => 'temp_exe', 'question_id' => $questionId); } $nano = new Nanogong($params); $s .= $nano->show_button(); } $form->addElement('html_editor', "choice[" . $questionId . "]", null, array('id' => "choice[" . $questionId . "]"), array('ToolbarSet' => 'TestFreeAnswer')); //$form->setDefaults(array("choice[".$questionId."]" => $content)); $s .= $form->return_form(); } // Now navigate through the possible answers, using the max number of // answers for the question as a limiter $lines_count = 1; // a counter for matching-type answers if ($answerType == MULTIPLE_ANSWER_TRUE_FALSE || $answerType == MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE) { $header = Display::tag('th', get_lang('Options')); foreach ($objQuestionTmp->options as $item) { $header .= Display::tag('th', $item); } if ($show_comment) { $header .= Display::tag('th', get_lang('Feedback')); } $s .= '<table class="data_table">'; $s .= Display::tag('tr', $header, array('style' => 'text-align:left;')); } if ($show_comment) { if (in_array($answerType, array(MULTIPLE_ANSWER, MULTIPLE_ANSWER_COMBINATION, UNIQUE_ANSWER, UNIQUE_ANSWER_NO_OPTION, GLOBAL_MULTIPLE_ANSWER))) { $header = Display::tag('th', get_lang('Options')); if ($exercise_feedback == EXERCISE_FEEDBACK_TYPE_END) { $header .= Display::tag('th', get_lang('Feedback')); } $s .= '<table class="data_table">'; $s .= Display::tag('tr', $header, array('style' => 'text-align:left;')); } } $matching_correct_answer = 0; $user_choice_array = array(); if (!empty($user_choice)) { foreach ($user_choice as $item) { $user_choice_array[] = $item['answer']; } } foreach ($objAnswerTmp->answer as $answerId => $answer_item) { $answer = $objAnswerTmp->selectAnswer($answerId); $answerCorrect = $objAnswerTmp->isCorrect($answerId); $comment = $objAnswerTmp->selectComment($answerId); //$numAnswer = $objAnswerTmp->selectAutoId($answerId); $numAnswer = $answerId; $attributes = array(); // Unique answer if (in_array($answerType, array(UNIQUE_ANSWER, UNIQUE_ANSWER_IMAGE, UNIQUE_ANSWER_NO_OPTION))) { $input_id = 'choice-' . $questionId . '-' . $answerId; if (isset($user_choice[0]['answer']) && $user_choice[0]['answer'] == $numAnswer) { $attributes = array('id' => $input_id, 'checked' => 1, 'selected' => 1); } else { $attributes = array('id' => $input_id); } if ($debug_mark_answer) { if ($answerCorrect) { $attributes['checked'] = 1; $attributes['selected'] = 1; } } $answer = Security::remove_XSS($answer); $s .= Display::input('hidden', 'choice2[' . $questionId . ']', '0'); $answer_input = null; if ($answerType == UNIQUE_ANSWER_IMAGE) { $attributes['style'] = 'display:none'; $answer_input .= '<div id="answer' . $questionId . $numAnswer . '" style="float:left" class="highlight_image_default highlight_image">'; } $answer_input .= '<label class="radio">'; $answer_input .= Display::input('radio', 'choice[' . $questionId . ']', $numAnswer, $attributes); $answer_input .= $answer; $answer_input .= '</label>'; if ($answerType == UNIQUE_ANSWER_IMAGE) { $answer_input .= "</div>"; } if ($show_comment) { $s .= '<tr><td>'; $s .= $answer_input; $s .= '</td>'; $s .= '<td>'; $s .= $comment; $s .= '</td>'; $s .= '</tr>'; } else { $s .= $answer_input; } } elseif (in_array($answerType, array(MULTIPLE_ANSWER, MULTIPLE_ANSWER_TRUE_FALSE, GLOBAL_MULTIPLE_ANSWER))) { $input_id = 'choice-' . $questionId . '-' . $answerId; $answer = Security::remove_XSS($answer); if (in_array($numAnswer, $user_choice_array)) { $attributes = array('id' => $input_id, 'checked' => 1, 'selected' => 1); } else { $attributes = array('id' => $input_id); } if ($debug_mark_answer) { if ($answerCorrect) { $attributes['checked'] = 1; $attributes['selected'] = 1; } } if ($answerType == MULTIPLE_ANSWER || $answerType == GLOBAL_MULTIPLE_ANSWER) { $s .= '<input type="hidden" name="choice2[' . $questionId . ']" value="0" />'; $answer_input = '<label class="checkbox">'; $answer_input .= Display::input('checkbox', 'choice[' . $questionId . '][' . $numAnswer . ']', $numAnswer, $attributes); $answer_input .= $answer; $answer_input .= '</label>'; if ($show_comment) { $s .= '<tr><td>'; $s .= $answer_input; $s .= '</td>'; $s .= '<td>'; $s .= $comment; $s .= '</td>'; $s .= '</tr>'; } else { $s .= $answer_input; } } elseif ($answerType == MULTIPLE_ANSWER_TRUE_FALSE) { $my_choice = array(); if (!empty($user_choice_array)) { foreach ($user_choice_array as $item) { $item = explode(':', $item); $my_choice[$item[0]] = $item[1]; } } $s .= '<tr>'; $s .= Display::tag('td', $answer); if (!empty($quiz_question_options)) { foreach ($quiz_question_options as $id => $item) { $id = $item['iid']; if (isset($my_choice[$numAnswer]) && $id == $my_choice[$numAnswer]) { $attributes = array('checked' => 1, 'selected' => 1); } else { $attributes = array(); } if ($debug_mark_answer) { if ($id == $answerCorrect) { $attributes['checked'] = 1; $attributes['selected'] = 1; } } $s .= Display::tag('td', Display::input('radio', 'choice[' . $questionId . '][' . $numAnswer . ']', $id, $attributes), array('style' => '')); } } if ($show_comment) { $s .= '<td>'; $s .= $comment; $s .= '</td>'; } $s .= '</tr>'; } } elseif ($answerType == MULTIPLE_ANSWER_COMBINATION) { // multiple answers $input_id = 'choice-' . $questionId . '-' . $answerId; if (in_array($numAnswer, $user_choice_array)) { $attributes = array('id' => $input_id, 'checked' => 1, 'selected' => 1); } else { $attributes = array('id' => $input_id); } if ($debug_mark_answer) { if ($answerCorrect) { $attributes['checked'] = 1; $attributes['selected'] = 1; } } $answer = Security::remove_XSS($answer); $answer_input = '<input type="hidden" name="choice2[' . $questionId . ']" value="0" />'; $answer_input .= '<label class="checkbox">'; $answer_input .= Display::input('checkbox', 'choice[' . $questionId . '][' . $numAnswer . ']', 1, $attributes); $answer_input .= $answer; $answer_input .= '</label>'; if ($show_comment) { $s .= '<tr>'; $s .= '<td>'; $s .= $answer_input; $s .= '</td>'; $s .= '<td>'; $s .= $comment; $s .= '</td>'; $s .= '</tr>'; } else { $s .= $answer_input; } } elseif ($answerType == MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE) { $s .= '<input type="hidden" name="choice2[' . $questionId . ']" value="0" />'; $my_choice = array(); if (!empty($user_choice_array)) { foreach ($user_choice_array as $item) { $item = explode(':', $item); $my_choice[$item[0]] = $item[1]; } } $answer = Security::remove_XSS($answer); $s .= '<tr>'; $s .= Display::tag('td', $answer); foreach ($objQuestionTmp->options as $key => $item) { if (isset($my_choice[$numAnswer]) && $key == $my_choice[$numAnswer]) { $attributes = array('checked' => 1, 'selected' => 1); } else { $attributes = array(); } if ($debug_mark_answer) { if ($key == $answerCorrect) { $attributes['checked'] = 1; $attributes['selected'] = 1; } } $s .= Display::tag('td', Display::input('radio', 'choice[' . $questionId . '][' . $numAnswer . ']', $key, $attributes)); } if ($show_comment) { $s .= '<td>'; $s .= $comment; $s .= '</td>'; } $s .= '</tr>'; } elseif ($answerType == FILL_IN_BLANKS) { list($answer) = explode('::', $answer); //Correct answer api_preg_match_all('/\\[[^]]+\\]/', $answer, $correct_answer_list); //Student's answezr if (isset($user_choice[0]['answer'])) { api_preg_match_all('/\\[[^]]+\\]/', $user_choice[0]['answer'], $student_answer_list); $student_answer_list = $student_answer_list[0]; } //If debug if ($debug_mark_answer) { $student_answer_list = $correct_answer_list[0]; } if (!empty($correct_answer_list) && !empty($student_answer_list)) { $correct_answer_list = $correct_answer_list[0]; $i = 0; foreach ($correct_answer_list as $correct_item) { $value = null; if (isset($student_answer_list[$i]) && !empty($student_answer_list[$i])) { //Cleaning student answer list $value = strip_tags($student_answer_list[$i]); $value = api_substr($value, 1, api_strlen($value) - 2); $value = explode('/', $value); if (!empty($value[0])) { $value = str_replace(' ', '', trim($value[0])); } $correct_item = preg_quote($correct_item); $correct_item = api_preg_replace('|/|', '\\/', $correct_item); // to prevent error if there is a / in the text to find $answer = api_preg_replace('/' . $correct_item . '/', Display::input('text', "choice[{$questionId}][]", $value), $answer, 1); } $i++; } } else { $answer = api_preg_replace('/\\[[^]]+\\]/', Display::input('text', "choice[{$questionId}][]", '', $attributes), $answer); } $s .= $answer; } elseif ($answerType == MATCHING) { // matching type, showing suggestions and answers // TODO: replace $answerId by $numAnswer if ($lines_count == 1) { $s .= $objAnswerTmp->getJs(); } if ($answerCorrect != 0) { // only show elements to be answered (not the contents of // the select boxes, who are correct = 0) $s .= '<tr><td width="45%">'; $parsed_answer = $answer; $windowId = $questionId . '_' . $lines_count; //left part questions $s .= ' <div id="window_' . $windowId . '" class="window window_left_question window' . $questionId . '_question"> <b>' . $lines_count . '</b>. ' . $parsed_answer . ' </div> </td>'; // middle part (matches selects) $s .= '<td width="10%" align="center"> '; $s .= '<div style="display:block">'; $s .= '<select id="window_' . $windowId . '_select" name="choice[' . $questionId . '][' . $numAnswer . ']">'; $selectedValue = 0; // fills the list-box $item = 0; foreach ($select_items as $val) { // set $debug_mark_answer to true at public static function start to // show the correct answer with a suffix '-x' $selected = ''; if ($debug_mark_answer) { if ($val['id'] == $answerCorrect) { $selected = 'selected="selected"'; $selectedValue = $val['id']; } } if (isset($user_choice[$matching_correct_answer]) && $val['id'] == $user_choice[$matching_correct_answer]['answer']) { $selected = 'selected="selected"'; $selectedValue = $val['id']; } //$s .= '<option value="'.$val['id'].'" '.$selected.'>'.$val['letter'].'</option>'; $s .= '<option value="' . $item . '" ' . $selected . '>' . $val['letter'] . '</option>'; $item++; } if (!empty($answerCorrect) && !empty($selectedValue)) { $s .= '<script> jsPlumb.ready(function() { jsPlumb.connect({ source: "window_' . $windowId . '", target: "window_' . $questionId . '_' . $selectedValue . '_answer", endpoint:["Blank", { radius:15 }], anchor:["RightMiddle","LeftMiddle"], paintStyle:{ strokeStyle:"#8a8888" , lineWidth:8 }, connector: [connectorType, { curviness: curvinessValue } ], }) }); </script>'; } $s .= '</select></div></td>'; $s .= '<td width="45%" valign="top" >'; if (isset($select_items[$lines_count])) { $s .= '<div id="window_' . $windowId . '_answer" class="window window_right_question"> <b>' . $select_items[$lines_count]['letter'] . '.</b> ' . $select_items[$lines_count]['answer'] . ' </div>'; } else { $s .= ' '; } $s .= '</td>'; $s .= '</tr>'; $lines_count++; //if the left side of the "matching" has been completely // shown but the right side still has values to show... if ($lines_count - 1 == $num_suggestions) { // if it remains answers to shown at the right side while (isset($select_items[$lines_count])) { $s .= '<tr> <td colspan="2"></td> <td valign="top">'; $s .= '<b>' . $select_items[$lines_count]['letter'] . '.</b>'; $s .= $select_items[$lines_count]['answer']; $s .= "</td>\n </tr>"; $lines_count++; } // end while() } // end if() $matching_correct_answer++; } } elseif ($answerType == DRAGGABLE) { // matching type, showing suggestions and answers // TODO: replace $answerId by $numAnswer if ($answerCorrect != 0) { // only show elements to be answered (not the contents of // the select boxes, who are correct = 0) $s .= '<td>'; $parsed_answer = $answer; $windowId = $questionId . '_' . $numAnswer; //67_293 - 67_294 //left part questions $s .= '<li class="ui-state-default" id="' . $windowId . '">'; $s .= ' <div id="window_' . $windowId . '" class="window' . $questionId . '_question_draggable question_draggable"> ' . $parsed_answer . ' </div>'; $s .= '<div style="display:none">'; $s .= '<select id="window_' . $windowId . '_select" name="choice[' . $questionId . '][' . $numAnswer . ']" class="select_option">'; $selectedValue = 0; // fills the list-box $item = 0; foreach ($select_items as $val) { // set $debug_mark_answer to true at function start to // show the correct answer with a suffix '-x' $selected = ''; if ($debug_mark_answer) { if ($val['id'] == $answerCorrect) { $selected = 'selected="selected"'; $selectedValue = $val['id']; } } if (isset($user_choice[$matching_correct_answer]) && $val['id'] == $user_choice[$matching_correct_answer]['answer']) { $selected = 'selected="selected"'; $selectedValue = $val['id']; } //$s .= '<option value="'.$val['id'].'" '.$selected.'>'.$val['letter'].'</option>'; $s .= '<option value="' . $item . '" ' . $selected . '>' . $val['letter'] . '</option>'; $item++; } $s .= '</select>'; if (!empty($answerCorrect) && !empty($selectedValue)) { $s .= '<script> $(function() { deleteItem($("#' . $questionId . '_' . $selectedValue . '"), $("#drop_' . $windowId . '")); }); </script>'; } if (isset($select_items[$lines_count])) { $s .= '<div id="window_' . $windowId . '_answer" class=""> <b>' . $select_items[$lines_count]['letter'] . '.</b> ' . $select_items[$lines_count]['answer'] . ' </div>'; } else { $s .= ' '; } $lines_count++; //if the left side of the "matching" has been completely // shown but the right side still has values to show... if ($lines_count - 1 == $num_suggestions) { // if it remains answers to shown at the right side while (isset($select_items[$lines_count])) { $s .= '<b>' . $select_items[$lines_count]['letter'] . '.</b>'; $s .= $select_items[$lines_count]['answer']; $lines_count++; } } $s .= '</div>'; $matching_correct_answer++; $s .= '</li>'; } } } // end for() if ($show_comment) { $s .= '</table>'; } else { if ($answerType == MATCHING || $answerType == UNIQUE_ANSWER_NO_OPTION || $answerType == MULTIPLE_ANSWER_TRUE_FALSE || $answerType == MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE) { $s .= '</table>'; } } if ($answerType == DRAGGABLE) { $s .= '</ul><div class="clear"></div>'; $counterAnswer = 1; foreach ($objAnswerTmp->answer as $answerId => $answer_item) { $answerCorrect = $objAnswerTmp->isCorrect($answerId); $windowId = $questionId . '_' . $counterAnswer; if ($answerCorrect == 0) { $s .= '<div id="drop_' . $windowId . '" class="droppable ui-state-default">' . $counterAnswer . '</div>'; $counterAnswer++; } } } if ($answerType == MATCHING) { $s .= '</div>'; } $s .= '</div>'; // destruction of the Answer object unset($objAnswerTmp); // destruction of the Question object unset($objQuestionTmp); $html .= $s; return $html; } elseif ($answerType == HOT_SPOT || $answerType == HOT_SPOT_DELINEATION) { // Question is a HOT_SPOT //checking document/images visibility if (api_is_platform_admin() || api_is_course_admin()) { $course = api_get_course_info(); $doc_id = DocumentManager::get_document_id($course, '/images/' . $pictureName); if (is_numeric($doc_id)) { $images_folder_visibility = api_get_item_visibility($course, 'document', $doc_id, api_get_session_id()); if (!$images_folder_visibility) { //This message is shown only to the course/platform admin if the image is set to visibility = false Display::display_warning_message(get_lang('ChangeTheVisibilityOfTheCurrentImage')); } } } $questionName = $objQuestionTmp->selectTitle(); $questionDescription = $objQuestionTmp->selectDescription(); if ($freeze) { $s .= Display::img($objQuestionTmp->selectPicturePath()); $html .= $s; return $html; } // Get the answers, make a list $objAnswerTmp = new Answer($questionId); // get answers of hotpost $answers_hotspot = array(); foreach ($objAnswerTmp->answer as $answerId => $answer_item) { //$answers = $objAnswerTmp->selectAnswerByAutoId($objAnswerTmp->selectAutoId($answerId)); $answers_hotspot[$answerId] = $objAnswerTmp->selectAnswer($answerId); } // display answers of hotpost order by id $answer_list = '<div style="padding: 10px; margin-left: 0px; border: 1px solid #A4A4A4; height: 408px; width: 200px;"><b>' . get_lang('HotspotZones') . '</b><dl>'; if (!empty($answers_hotspot)) { ksort($answers_hotspot); foreach ($answers_hotspot as $key => $value) { $answer_list .= '<dt>' . $key . '.- ' . $value . '</dt><br />'; } } $answer_list .= '</dl></div>'; if ($answerType == HOT_SPOT_DELINEATION) { $answer_list = ''; $swf_file = 'hotspot_delineation_user'; $swf_height = 405; } else { $swf_file = 'hotspot_user'; $swf_height = 436; } if (!$only_questions) { if ($show_title) { $html .= TestCategory::getCategoryNamesForQuestion($objQuestionTmp->id); $html .= '<div class="question_title">' . $current_item . '. ' . $questionName . '</div>'; $html .= $questionDescription; } else { $html .= '<div class="media">'; $html .= '<div class="pull-left">'; $html .= '<div class="media-object">'; $html .= Display::div($current_item . '. ', array('class' => 'question_no_title')); $html .= '</div>'; $html .= '</div>'; $html .= '<div class="media-body">'; if (!empty($questionDescription)) { $html .= Display::div($questionDescription, array('class' => 'question_description')); } $html .= '</div>'; $html .= '</div>'; } //@todo I need to the get the feedback type $html .= '<input type="hidden" name="hidden_hotspot_id" value="' . $questionId . '" />'; $html .= '<table class="exercise_questions"> <tr> <td valign="top" colspan="2">'; $html .= '</td></tr>'; } $canClick = isset($_GET['editQuestion']) ? '0' : (isset($_GET['modifyAnswers']) ? '0' : '1'); $s .= ' <script type="text/javascript" src="../plugin/hotspot/JavaScriptFlashGateway.js"></script> <script src="../plugin/hotspot/hotspot.js" type="text/javascript" ></script> <script type="text/javascript"> <!-- // Globals // Major version of Flash required var requiredMajorVersion = 7; // Minor version of Flash required var requiredMinorVersion = 0; // Minor version of Flash required var requiredRevision = 0; // the version of javascript supported var jsVersion = 1.0; // --> </script> <script language="VBScript" type="text/vbscript"> <!-- // Visual basic helper required to detect Flash Player ActiveX control version information Function VBGetSwfVer(i) on error resume next Dim swControl, swVersion swVersion = 0 set swControl = CreateObject("ShockwaveFlash.ShockwaveFlash." + CStr(i)) if (IsObject(swControl)) then swVersion = swControl.GetVariable("$version") end if VBGetSwfVer = swVersion End Function // --> </script> <script language="JavaScript1.1" type="text/javascript"> <!-- // Detect Client Browser type var isIE = (navigator.appVersion.indexOf("MSIE") != -1) ? true : false; var isWin = (navigator.appVersion.toLowerCase().indexOf("win") != -1) ? true : false; var isOpera = (navigator.userAgent.indexOf("Opera") != -1) ? true : false; jsVersion = 1.1; // JavaScript helper required to detect Flash Player PlugIn version information function JSGetSwfVer(i) { // NS/Opera version >= 3 check for Flash plugin in plugin array if (navigator.plugins != null && navigator.plugins.length > 0) { if (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]) { var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : ""; var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description; descArray = flashDescription.split(" "); tempArrayMajor = descArray[2].split("."); versionMajor = tempArrayMajor[0]; versionMinor = tempArrayMajor[1]; if ( descArray[3] != "" ) { tempArrayMinor = descArray[3].split("r"); } else { tempArrayMinor = descArray[4].split("r"); } versionRevision = tempArrayMinor[1] > 0 ? tempArrayMinor[1] : 0; flashVer = versionMajor + "." + versionMinor + "." + versionRevision; } else { flashVer = -1; } } // MSN/WebTV 2.6 supports Flash 4 else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.6") != -1) flashVer = 4; // WebTV 2.5 supports Flash 3 else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.5") != -1) flashVer = 3; // older WebTV supports Flash 2 else if (navigator.userAgent.toLowerCase().indexOf("webtv") != -1) flashVer = 2; // Can\'t detect in all other cases else { flashVer = -1; } return flashVer; } // When called with reqMajorVer, reqMinorVer, reqRevision returns true if that version or greater is available function DetectFlashVer(reqMajorVer, reqMinorVer, reqRevision) { reqVer = parseFloat(reqMajorVer + "." + reqRevision); // loop backwards through the versions until we find the newest version for (i=25;i>0;i--) { if (isIE && isWin && !isOpera) { versionStr = VBGetSwfVer(i); } else { versionStr = JSGetSwfVer(i); } if (versionStr == -1 ) { return false; } else if (versionStr != 0) { if(isIE && isWin && !isOpera) { tempArray = versionStr.split(" "); tempString = tempArray[1]; versionArray = tempString .split(","); } else { versionArray = versionStr.split("."); } versionMajor = versionArray[0]; versionMinor = versionArray[1]; versionRevision = versionArray[2]; versionString = versionMajor + "." + versionRevision; // 7.0r24 == 7.24 versionNum = parseFloat(versionString); // is the major.revision >= requested major.revision AND the minor version >= requested minor if ( (versionMajor > reqMajorVer) && (versionNum >= reqVer) ) { return true; } else { return ((versionNum >= reqVer && versionMinor >= reqMinorVer) ? true : false ); } } } } // --> </script>'; $s .= '<tr><td valign="top" colspan="2" width="520"><table><tr><td width="520"> <script> // Version check based upon the values entered above in "Globals" var hasReqestedVersion = DetectFlashVer(requiredMajorVersion, requiredMinorVersion, requiredRevision); // Check to see if the version meets the requirements for playback if (hasReqestedVersion) { // if we\'ve detected an acceptable version var oeTags = \'<object type="application/x-shockwave-flash" data="../plugin/hotspot/' . $swf_file . '.swf?modifyAnswers=' . $questionId . '&canClick:' . $canClick . '" width="600" height="' . $swf_height . '">\' + \'<param name="wmode" value="transparent">\' + \'<param name="movie" value="../plugin/hotspot/' . $swf_file . '.swf?modifyAnswers=' . $questionId . '&canClick:' . $canClick . '" />\' + \'<\\/object>\'; document.write(oeTags); // embed the Flash Content SWF when all tests are passed } else { // flash is too old or we can\'t detect the plugin var alternateContent = "Error<br \\/>" + "Hotspots requires Macromedia Flash 7.<br \\/>" + "<a href=\\"http://www.macromedia.com/go/getflash/\\">Get Flash<\\/a>"; document.write(alternateContent); // insert non-flash content } </script> </td> <td valign="top" align="left">' . $answer_list . '</td></tr> </table> </td></tr>'; $html .= $s; $html .= '</table>'; return $html; } return $nbrAnswers; }
/** * 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 Thanos Kyritsis <*****@*****.**> * @author Amand Tihon <*****@*****.**> */ function prepareQuiz($quizId, $raw_to_pass = 50) { global $langQuestion, $langOk, $langScore, $claro_stylesheet, $clarolineRepositorySys; global $charset, $langExerciseDone; // those two variables are needed by display_attached_file() global $attachedFilePathWeb; global $attachedFilePathSys; $attachedFilePathWeb = 'Exercises'; $attachedFilePathSys = $this->destDir . '/Exercises'; // Generate standard page header $pageHeader = '<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=' . $charset . '"> <meta http-equiv="expires" content="Tue, 05 DEC 2000 07:00:00 GMT"> <meta http-equiv="Pragma" content="no-cache"> <link rel="stylesheet" type="text/css" href="bootstrap-custom.css" /> <link rel="stylesheet" type="text/css" href="' . $claro_stylesheet . '" media="screen, projection, tv" /> <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 class="table-default"><tr><td>' . "\n"; // read the exercise $quiz = new Exercise(); if (!$quiz->read($quizId)) { $this->error[] = $GLOBALS['langErrorLoadingExercise']; return false; } // Get the question list $questionList = $quiz->selectQuestionList(); $questionCount = $quiz->selectNbrQuestions(); // Keep track of raw scores (ponderation) for each question $questionPonderationList = array(); // Keep track of correct texts for fill-in type questions $fillAnswerList = array(); // Counter used to generate the elements' id. Incremented after every <input> or <select> $idCounter = 0; // Display each question $questionCount = 0; foreach ($questionList as $questionId) { // Update question number $questionCount++; // read the question, abort on error $question = new Question(); if (!$question->read($questionId)) { $this->error[] = $GLOBALS['langErrorLoadingQuestion']; return false; } $qtype = $question->selectType(); $qtitle = $question->selectTitle(); $qdescription = $question->selectDescription(); $questionPonderationList[$questionId] = $question->selectWeighting(); // Generic display, valid for all kind of question $pageBody .= '<table class="table-default"> <tr><th valign="top" colspan="2">' . $langQuestion . ' ' . $questionCount . '</th></tr> <tfoot> <tr><td valign="top" colspan="2">' . $qtitle . '</td></tr> <tr><td valign="top" colspan="2"><i>' . parse_user_text($qdescription) . '</i></td></tr>' . "\n"; // Attached file, if it exists. //$attachedFile = $question->selectAttachedFile(); if (!empty($attachedFile)) { // copy the attached file if (!claro_copy_file($this->srcDirExercise . '/' . $attachedFile, $this->destDir . '/Exercises')) { $this->error[] = $GLOBALS['langErrorCopyAttachedFile'] . $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 */ $answer = new Answer($questionId); $answerCount = $answer->selectNbrAnswers(); // Used for matching: $letterCounter = 'A'; $choiceCounter = 1; $Select = array(); for ($answerId = 1; $answerId <= $answerCount; $answerId++) { $answerText = $answer->selectAnswer($answerId); $answerCorrect = $answer->isCorrect($answerId); // Unique answer if ($qtype == UNIQUE_ANSWER || $qtype == TRUE_FALSE) { // Construct the identifier $htmlQuestionId = 'unique_' . $questionCount . '_x'; $pageBody .= '<tr><td width="5%" align="center"> <input type="radio" name="' . $htmlQuestionId . '" id="scorm_' . $idCounter . '" value="' . $answer->selectWeighting($answerId) . '"></td> <td width="95%"><label for="scorm_' . $idCounter . '">' . $answerText . '</label> </td></tr>'; $idCounter++; } // Multiple answers elseif ($qtype == MULTIPLE_ANSWER) { // Construct the identifier $htmlQuestionId = 'multiple_' . $questionCount . '_' . $answerId; // Compute the score modifier if this answer is checked $raw = $answer->selectWeighting($answerId); $pageBody .= '<tr><td width="5%" align="center"> <input type="checkbox" name="' . $htmlQuestionId . '" id="scorm_' . $idCounter . '" value="' . $raw . '"></td> <td width="95%"><label for="scorm_' . $idCounter . '">' . $answerText . '</label> </td></tr>'; $idCounter++; } // Fill in blanks elseif ($qtype == FILL_IN_BLANKS || $qtype == FILL_IN_BLANKS_TOLERANT) { $pageBody .= '<tr><td colspan="2">'; // We must split the text, to be able to treat each input independently // separate the text and the scorings $explodedAnswer = explode('::', $answerText); $phrase = (isset($explodedAnswer[0])) ? $explodedAnswer[0] : ''; $weighting = (isset($explodedAnswer[1])) ? $explodedAnswer[1] : ''; $fillType = (!empty($explodedAnswer[2])) ? $explodedAnswer[2] : 1; // default value if value is invalid if ($fillType != TEXTFIELD_FILL && $fillType != LISTBOX_FILL) { $fillType = TEXTFIELD_FILL; } $wrongAnswers = (!empty($explodedAnswer[3])) ? explode('[', $explodedAnswer[3]) : array(); // get the scorings as a list $fillScoreList = explode(',', $weighting); $fillScoreCounter = 0; //listbox if ($fillType == LISTBOX_FILL) { // get the list of propositions (good and wrong) to display in lists // add wrongAnswers in the list $answerList = $wrongAnswers; // add good answers in the list // we save the answer because it will be modified $temp = $phrase; while (1) { // quits the loop if there are no more blanks if (($pos = strpos($temp, '[')) === false) { break; } // removes characters till '[' $temp = substr($temp, $pos + 1); // quits the loop if there are no more blanks if (($pos = strpos($temp, ']')) === false) { break; } // stores the found blank into the array $answerList[] = substr($temp, 0, $pos); // removes the character ']' $temp = substr($temp, $pos + 1); } // alphabetical sort of the array natcasesort($answerList); } // Split after each blank $responsePart = explode(']', $phrase); $acount = 0; foreach ($responsePart as $part) { // Split between text and (possible) blank if (strpos($part, '[') !== false) { list($rawtext, $blankText) = explode('[', $part); } else { $rawtext = $part; $blankText = ""; } $pageBody .= $rawtext; // If there's a blank to fill-in after the text (this is usually not the case at the end) if (!empty($blankText)) { // Build the element's name $name = 'fill_' . $questionCount . '_' . $acount; // Keep track of the correspondance between element's name and correct value + scoring $fillAnswerList[$name] = array($blankText, $fillScoreList[$fillScoreCounter]); if ($fillType == LISTBOX_FILL) {// listbox $pageBody .= '<select name="' . $name . '" id="scorm_' . $idCounter . '">' . "\n" . '<option value=""> </option>'; foreach ($answerList as $answer) { $pageBody .= '<option value="' . htmlspecialchars($answer) . '">' . $answer . '</option>' . "\n"; } $pageBody .= '</select>' . "\n"; } else { $pageBody .= '<input type="text" name="' . $name . '" size="10" id="scorm_' . $idCounter . '">'; } $fillScoreCounter++; $idCounter++; } $acount++; } $pageBody .= '</td></tr>' . "\n"; } // Matching elseif ($qtype == MATCHING) { if (!$answer->isCorrect($answerId)) { // Add the option as a possible answer. $Select[$answerId] = $answerText; } else { $pageBody .= '<tr><td colspan="2"> <table border="0" cellpadding="0" cellspacing="0" width="99%"> <tr> <td width="40%" valign="top"><b>' . $choiceCounter . '.</b> ' . $answerText . '</td> <td width="20%" valign="center"> <select name="matching_' . $questionCount . '_' . $answerId . '" id="scorm_' . $idCounter . '"> <option value="0">--</option>'; $idCounter++; // fills the list-box $letter = 'A'; foreach ($Select as $key => $val) { $scoreModifier = ( $key == $answer->isCorrect($answerId) ) ? $answer->selectWeighting($answerId) : 0; $pageBody .= '<option value="' . $scoreModifier . '">' . $letter++ . '</option>'; } $pageBody .= '</select></td><td width="40%" valign="top">'; if (isset($Select[$choiceCounter])) { $pageBody .= '<b>' . $letterCounter . '.</b> ' . $Select[$choiceCounter]; } $pageBody .= ' </td></tr></table></td></tr>' . "\n"; // Done with this one $letterCounter++; $choiceCounter++; // If the left side has been completely displayed : if ($answerId == $answerCount) { // Add all possibly remaining answers to the right while (isset($Select[$choiceCounter])) { $pageBody .= '<tr><td colspan="2"> <table border="0" cellpadding="0" cellspacing="0" width="99%"> <tr> <td width="40%"> </td> <td width="20%"> </td> <td width="40%"><b>' . $letterCounter . '.</b> ' . $Select[$choiceCounter] . '</td> </tr> </table> </td></tr>' . "\n"; $letterCounter++; $choiceCounter++; } // end while } // end if } // else } // end if (MATCHING) } // end for each answer // End of the question $pageBody .= '</tfoot></table>' . "\n\n"; } // foreach($questionList as $questionId) // No more questions, add the button. $pageEnd = '</td></tr> <tr> <td align="center"><br><input class="btn btn-primary" type="button" value="' . $langOk . '" 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"; // Add the data for fillAnswerList foreach ($fillAnswerList as $key => $val) { $pageHeader .= " fillAnswerList['" . $key . "'] = new Array('" . $val[0] . "', '" . $val[1] . "');\n"; } // This is the actual code present in every exported exercise. $pageHeader .= ' function calcScore() { if( !scoreCommited ) { rawScore = CalculateRawScore(document, ' . $idCounter . ', fillAnswerList); var score = Math.max(Math.round(rawScore * 100 / weighting), 0); var oldScore = doGetValue("cmi.score.raw"); doSetValue("cmi.score.max", weighting); doSetValue("cmi.score.min", 0); computeTime(); if (score > oldScore) // Update only if score is better than the previous time. { doSetValue("cmi.score.raw", rawScore); } var oldStatus = doGetValue( "cmi.success_status" ) if (score >= raw_to_pass) { doSetValue("cmi.success_status", "passed"); } else if (oldStatus != "passed" ) // If passed once, never mark it as failed. { doSetValue("cmi.success_status", "failed"); } doCommit(); doTerminate(); scoreCommited = true; if(showScore) alert(\'' . clean_str_for_javascript($langScore) . ' :\n\' + rawScore + \'/\' + weighting + \'\n\' + \'' . clean_str_for_javascript($langExerciseDone) . '\'); } } </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[] = $GLOBALS['langErrorCreatingFile'] . $filename; return false; } fwrite($f, $pageContent); fclose($f); // Went well. return True; }
/** * This function exports the given Chamilo test * @param integer Test ID * @return string The test itself as an HTML string */ function export_exercise($item_id) { global $expdir, $_course, $_configuration, $_SESSION, $_SERVER, $language_interface, $langExerciseNotFound, $langQuestion, $langOk, $origin, $questionNum; $exerciseId = $item_id; require_once '../exercice/exercise.class.php'; require_once '../exercice/question.class.php'; require_once '../exercice/answer.class.php'; $TBL_EXERCISES = Database::get_course_table(TABLE_QUIZ_TEST); /* Clears the exercise session */ if (isset($_SESSION['objExercise'])) { Session::erase('objExercise'); } if (isset($_SESSION['objQuestion'])) { Session::erase('objQuestion'); } if (isset($_SESSION['objAnswer'])) { Session::erase('objAnswer'); } if (isset($_SESSION['questionList'])) { Session::erase('questionList'); } if (isset($_SESSION['exerciseResult'])) { Session::erase('exerciseResult'); } // If the object is not in the session: if (!isset($_SESSION['objExercise'])) { // Construction of Exercise. $objExercise = new Exercise(); $sql = "SELECT title,description,sound,type,random,active FROM {$TBL_EXERCISES} WHERE iid='{$exerciseId}'"; // If the specified exercise doesn't exist or is disabled: if (!$objExercise->read($exerciseId) || !$objExercise->selectStatus() && !api_is_allowed_to_edit() && $origin != 'learnpath') { die($langExerciseNotFound); } // Saves the object into the session. Session::write('objExercise', $objExercise); } $exerciseTitle = $objExercise->selectTitle(); $exerciseDescription = $objExercise->selectDescription(); $exerciseSound = $objExercise->selectSound(); $randomQuestions = $objExercise->isRandom(); $exerciseType = $objExercise->selectType(); if (!isset($_SESSION['questionList'])) { // Selects the list of question ID. $questionList = $randomQuestions ? $objExercise->selectRandomList() : $objExercise->selectQuestionList(); // Saves the question list into the session. Session::write('questionList', $questionList); } $nbrQuestions = sizeof($questionList); // If questionNum comes from POST and not from GET: if (!$questionNum || $_POST['questionNum']) { // Only used for sequential exercises (see $exerciseType). if (!$questionNum) { $questionNum = 1; } else { $questionNum++; } } $test .= "<h3>" . $exerciseTitle . "</h3>"; if (!empty($exerciseSound)) { $test .= "<a href=\"../document/download.php?doc_url=%2Faudio%2F" . $exerciseSound . "\"&SQMSESSID=36812c2dea7d8d6e708d5e6a2f09b0b9 target=\"_blank\"><img src=\"../img/sound.gif\" border=\"0\" align=\"absmiddle\" alt=" . get_lang("Sound") . "\" /></a>"; } // Writing the .js file with to check the correct answers begin. $scriptfilename = "Exercice" . $item_id . ".js"; $s = "<script type=\"text/javascript\" src='../js/" . $scriptfilename . "'></script>"; $test .= $s; $content = "function evaluate() {\n alert('Test evaluated.');\n }\n "; if (!($handle = fopen($expdir . '/js/' . $scriptfilename, 'w'))) { echo "Cannot open file ({$scriptfilename})"; } if (fwrite($handle, $content) === false) { echo "Cannot write to file ({$filename})"; exit; } fclose($handle); // Writing the .js file with to check the correct answers end. $s = "\n <p>{$exerciseDescription}</p>\n <table width='100%' border='0' cellpadding='1' cellspacing='0'>\n <form method='post' action=''><input type=\"hidden\" name=\"SQMSESSID\" value=\"36812c2dea7d8d6e708d5e6a2f09b0b9\" />\n <input type='hidden' name='formSent' value='1' />\n <input type='hidden' name='exerciseType' value='" . $exerciseType . "' />\n <input type='hidden' name='questionNum' value='" . $questionNum . "' />\n <input type='hidden' name='nbrQuestions' value='" . $nbrQuestions . "' />\n <tr>\n <td>\n <table width='100%' cellpadding='4' cellspacing='2' border='0'>"; $exerciseType = 1; // So to list all questions in one page. $test .= $s; $i = 0; foreach ($questionList as $questionId) { $i++; // For sequential exercises. if ($exerciseType == 2) { // If it is not the right question, goes to the next loop iteration. if ($questionNum != $i) { continue; } else { // if the user has already answered this question: if (isset($exerciseResult[$questionId])) { // Construction of the Question object. $objQuestionTmp = new Question(); // Reads question informations. $objQuestionTmp->read($questionId); $questionName = $objQuestionTmp->selectTitle(); // Destruction of the Question object. unset($objQuestionTmp); $test .= '<tr><td>' . get_lang('AlreadyAnswered') . ' "' . $questionName . '"</td></tr>'; break; } } } echo $s = "<tr bgcolor='#e6e6e6'><td valign='top' colspan='2'>" . get_lang('Question') . " "; // Call the showQuestion(). This basically displays the question in a table. $question_obj = Question::read($questionId); $test .= $objExercise->showQuestion($question_obj, false, 'export', $i); } // end foreach() $s = "</table></td></tr><tr><td><br/><input type='button' value='" . $langOk . "' onclick=\"javascript: evaluate(); alert('Evaluated.');\">"; $s .= "</td></tr></form></table>"; $s .= "<script type='text/javascript'> loadPage(); </script>"; $b = 2; $test .= $s; return $test; }
function showQuestion($questionId, $onlyAnswers = false) { global $picturePath, $urlServer; global $langNoAnswer, $langColumnA, $langColumnB, $langMakeCorrespond; // construction of the Question object $objQuestionTmp = new Question(); // reads question informations if (!$objQuestionTmp->read($questionId)) { // question not found return false; } $answerType = $objQuestionTmp->selectType(); if (!$onlyAnswers) { $questionName = $objQuestionTmp->selectTitle(); $questionDescription = $objQuestionTmp->selectDescription(); $questionDescription_temp = standard_text_escape($questionDescription); echo "<tr class='even'>\n <td colspan='2'><b>" . q($questionName) . "</b><br />\n {$questionDescription_temp}\n </td>\n </tr>"; if (file_exists($picturePath . '/quiz-' . $questionId)) { echo "<tr class='even'>\n <td class='center' colspan='2'><img src='{$urlServer}/{$picturePath}/quiz-{$questionId}' /></td>\n </tr>"; } } // end if(!$onlyAnswers) // construction of the Answer object $objAnswerTmp = new Answer($questionId); $nbrAnswers = $objAnswerTmp->selectNbrAnswers(); // only used for the answer type "Matching" if ($answerType == MATCHING) { $cpt1 = 'A'; $cpt2 = 1; $select = array(); echo "\n <tr class='even'>\n <td colspan='2'>\n <table class='tbl_border' width='100%'>\n <tr>\n <th width='200'>{$langColumnA}</th>\n <th width='130'>{$langMakeCorrespond}</th>\n <th width='200'>{$langColumnB}</th>\n </tr>\n </table>\n </td>\n </tr>"; } for ($answerId = 1; $answerId <= $nbrAnswers; $answerId++) { $answer = $objAnswerTmp->selectAnswer($answerId); $answer = mathfilter($answer, 12, '../../courses/mathimg/'); $answerCorrect = $objAnswerTmp->isCorrect($answerId); if ($answerType == FILL_IN_BLANKS) { // splits text and weightings that are joined with the character '::' list($answer) = explode('::', $answer); // replaces [blank] by an input field $answer = preg_replace('/\\[[^]]+\\]/', '<input type="text" name="choice[' . $questionId . '][]" size="10" />', standard_text_escape($answer)); } // unique answer if ($answerType == UNIQUE_ANSWER) { echo "\n <tr class='even'>\n <td class='center' width='1'>\n <input type='radio' name='choice[{$questionId}]' value='{$answerId}' />\n </td>\n <td>" . standard_text_escape($answer) . "</td>\n </tr>"; } elseif ($answerType == MULTIPLE_ANSWER) { echo "\n <tr class='even'>\n <td width='1' align='center'>\n <input type='checkbox' name='choice[{$questionId}][{$answerId}]' value='1' />\n </td>\n <td>" . standard_text_escape($answer) . "</td>\n </tr>"; } elseif ($answerType == FILL_IN_BLANKS) { echo "\n <tr class='even'>\n <td colspan='2'>" . $answer . "</td>\n </tr>"; } elseif ($answerType == MATCHING) { if (!$answerCorrect) { // options (A, B, C, ...) that will be put into the list-box $select[$answerId]['Lettre'] = $cpt1++; // answers that will be shown at the right side $select[$answerId]['Reponse'] = standard_text_escape($answer); } else { echo "<tr class='even'>\n <td colspan='2'>\n <table class='tbl'>\n <tr>\n <td width='200'><b>{$cpt2}.</b> " . standard_text_escape($answer) . "</td>\n <td width='130'><div align='center'>\n <select name='choice[{$questionId}][{$answerId}]'>\n <option value='0'>--</option>"; // fills the list-box foreach ($select as $key => $val) { echo "<option value=\"{$key}\">{$val['Lettre']}</option>"; } echo "</select></div></td>\n <td width='200'>"; if (isset($select[$cpt2])) { echo '<b>' . $select[$cpt2]['Lettre'] . '.</b> ' . $select[$cpt2]['Reponse']; } else { echo ' '; } echo "</td></tr></table></td></tr>"; $cpt2++; // if the left side of the "matching" has been completely shown if ($answerId == $nbrAnswers) { // if it remains answers to shown at the right side while (isset($select[$cpt2])) { echo "<tr class='even'>\n <td colspan='2'>\n <table>\n <tr>\n <td width='60%' colspan='2'> </td>\n <td width='40%' align='right' valign='top'>" . "<b>" . $select[$cpt2]['Lettre'] . ".</b> " . $select[$cpt2]['Reponse'] . "</td>\n </tr>\n </table>\n </td>\n </tr>"; $cpt2++; } // end while() } // end if() } } elseif ($answerType == TRUE_FALSE) { echo "<tr class='even'>\n <td width='1' align='center'>\n <input type='radio' name='choice[{$questionId}]' value='{$answerId}' />\n </td><td>{$answer}</td>\n </tr>"; } } // end for() if (!$nbrAnswers) { echo "<tr><td colspan='2'><div class='alert alert-danger'>{$langNoAnswer}</div></td></tr>"; } // destruction of the Answer object unset($objAnswerTmp); // destruction of the Question object unset($objQuestionTmp); return $nbrAnswers; }
$deleteQuestion = $_GET['deleteQuestion']; // construction of the Question object $objQuestionTmp = new Question(); // if the question exists if ($objQuestionTmp->read($deleteQuestion)) { $objQuestionTmp->delete($exerciseId); // if the question has been removed from the exercise if ($objExercise->removeFromList($deleteQuestion)) { $nbrQuestions--; } } redirect_to_home_page("modules/exercise/admin.php?course={$course_code}&exerciseId={$exerciseId}"); } $tool_content .= action_bar(array(array('title' => $langNewQu, 'url' => "{$_SERVER['SCRIPT_NAME']}?course={$course_code}&exerciseId={$exerciseId}&newQuestion=yes", 'icon' => 'fa-plus-circle', 'level' => 'primary-label', 'button-class' => 'btn-success'), array('title' => $langSelection . ' ' . $langWithCriteria, 'class' => 'randomSelection', 'url' => "#", 'icon' => 'fa-random', 'level' => 'primary-label'), array('title' => $langSelection . ' ' . $langFrom2 . ' ' . $langQuestionPool, 'url' => "question_pool.php?course={$course_code}&fromExercise={$exerciseId}", 'icon' => 'fa-bank', 'level' => 'primary-label'))); if ($nbrQuestions) { $questionList = $objExercise->selectQuestionList(); $i = 1; $tool_content .= "\n <div class='table-responsive'>\n\t <table class='table-default'>\n\t <tr>\n\t <th colspan='2' class='text-left'>{$langQuestionList}</th>\n\t <th class='text-center'>" . icon('fa-gears', $langActions) . "</th>\n\t </tr>"; foreach ($questionList as $id) { $objQuestionTmp = new Question(); $objQuestionTmp->read($id); $tool_content .= "<tr>\n\t\t\t<td align='right' width='1'>" . $i . ".</td>\n\t\t\t<td> " . q($objQuestionTmp->selectTitle()) . "<br />\n\t\t\t" . $aType[$objQuestionTmp->selectType() - 1] . "</td>\n\t\t\t<td class='option-btn-cell'>" . action_button(array(array('title' => $langModify, 'url' => "{$_SERVER['SCRIPT_NAME']}?course={$course_code}&exerciseId={$exerciseId}&editQuestion={$id}", 'icon-class' => 'warnLink', 'icon-extra' => $objQuestionTmp->selectNbrExercises() > 1 ? "data-toggle='modal' data-target='#modalWarning' data-remote='false'" : "", 'icon' => 'fa-edit'), array('title' => $langDelete, 'url' => "?course={$course_code}&exerciseId={$exerciseId}&deleteQuestion={$id}", 'icon' => 'fa-times', 'class' => 'delete', 'confirm' => $langConfirmYourChoice, 'show' => !isset($fromExercise)), array('title' => $langUp, 'url' => "{$_SERVER['SCRIPT_NAME']}?course={$course_code}&exerciseId={$exerciseId}&moveUp={$id}", 'level' => 'primary', 'icon' => 'fa-arrow-up', 'disabled' => $i == 1), array('title' => $langDown, 'url' => "{$_SERVER['SCRIPT_NAME']}?course={$course_code}&exerciseId={$exerciseId}&moveDown={$id}", 'level' => 'primary', 'icon' => 'fa-arrow-down', 'disabled' => $i == $nbrQuestions))) . "</td></tr>"; $i++; unset($objQuestionTmp); } $tool_content .= "</table></div>"; } $tool_content .= "\n<!-- Modal -->\n<div class='modal fade' id='modalWarning' tabindex='-1' role='dialog' aria-labelledby='modalWarningLabel' aria-hidden='true'>\n <div class='modal-dialog'>\n <div class='modal-content'>\n <div class='modal-header'>\n <button type='button' class='close' data-dismiss='modal'><span aria-hidden='true'>×</span><span class='sr-only'>Close</span></button>\n </div>\n <div class='modal-body'>\n {$langUsedInSeveralExercises}\n </div>\n <div class='modal-footer'>\n <a href='#' id='modifyAll' class='btn btn-primary'>{$langModifyInAllExercises}</a>\n <a href='#' id='modifyOne' class='btn btn-success'>{$langModifyInThisExercise}</a>\n </div>\n </div>\n </div>\n</div> \n"; if ($nbrQuestions == 0) { $tool_content .= "<div class='alert alert-warning'>{$langNoQuestion}</div>"; }
include 'question.class.php'; $exerciseId = $_GET['exerciseId']; $objExercise = new Exercise(); $objExercise->read($exerciseId); $pageName = $langExerciseStats; $navigation[] = array("url" => "index.php?course={$course_code}", "name" => $langExercices); $tool_content .= action_bar(array(array('title' => $langBack, 'level' => 'primary-label', 'icon' => 'fa-reply', 'url' => "index.php?course={$course_code}"))); $completedAttempts = Database::get()->querySingle("SELECT count(*) AS count FROM exercise_user_record WHERE eid = ?d AND attempt_status = ?d", $exerciseId, ATTEMPT_COMPLETED)->count; $pausedAttempts = Database::get()->querySingle("SELECT count(*) AS count FROM exercise_user_record WHERE eid = ?d AND attempt_status = ?d", $exerciseId, ATTEMPT_PAUSED)->count; $pendingAttempts = Database::get()->querySingle("SELECT count(*) AS count FROM exercise_user_record WHERE eid = ?d AND attempt_status = ?d", $exerciseId, ATTEMPT_PENDING)->count; $cancelledAttempts = Database::get()->querySingle("SELECT count(*) AS count FROM exercise_user_record WHERE eid = ?d AND attempt_status = ?d", $exerciseId, ATTEMPT_CANCELED)->count; $total_attempts = $completedAttempts + $pausedAttempts + $pendingAttempts + $cancelledAttempts; $grade_stats = Database::get()->querySingle("SELECT COUNT(DISTINCT uid) AS unique_users, AVG(TIME_TO_SEC(TIMEDIFF(record_end_date, record_start_date))) AS avg_time, AVG(total_score) AS avg_grade, MIN(total_score) AS min_grade, MAX(total_score) AS max_grade FROM exercise_user_record WHERE eid = ?d AND attempt_status = ?d", $exerciseId, ATTEMPT_COMPLETED); $max_grade = $grade_stats->max_grade; $min_grade = $grade_stats->min_grade; $avg_grade = $grade_stats->avg_grade; $avg_time = $grade_stats->avg_time; $unique_users = $grade_stats->unique_users; //average number of attempts //avg completion time $tool_content .= "\n <div class='table-responsive'>\n <table class='table-default'>\n <thead>\n <tr>\n <th colspan='4' class='text-center'>{$langAttempts}</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td>{$langAttemptsCompleted}</th>\n <td>{$completedAttempts}</td>\n <td>{$langAttemptsPaused}</th>\n <td>{$pausedAttempts}</td> \n </tr>\n <tr>\n <td>{$langAttemptPending}</th>\n <td>{$pendingAttempts}</td>\n <td>{$langAttemptsCanceled}</th>\n <td>{$cancelledAttempts}</td> \n </tr>\n </tbody>\n <tfoot>\n <tr class='active'>\n <th colspan='3'>{$langTotal}:</th>\n <th colspan='1'>{$total_attempts}</th>\n </tr> \n </tfoot>\n </table>\n </div>\n <div class='table-responsive'>\n <table class='table-default'>\n <thead>\n <tr>\n <th colspan='2' class='text-center'>{$langScore}</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td>{$langHighestGrade}</th>\n <td>{$max_grade}</td>\n \n </tr>\n <tr>\n <td>{$langLowestGrade}</th>\n <td>{$min_grade}</td> \n </tr>\n <tr>\n <td>{$langRatingAverage}</th>\n <td>{$avg_grade}</td> \n </tr> \n </tbody>\n </table>\n </div>\n <div class='table-responsive'>\n <table class='table-default'>\n <thead>\n <tr>\n <th colspan='2' class='text-center'>{$langStudents}</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td>{$langStudentsExerciseCompleted}</th>\n <td>{$unique_users}</td> \n </tr> \n <tr>\n <td>{$langAverage} {$langExerciseDuration}</th>\n <td>" . format_time_duration($avg_time) . "</td> \n </tr> \n </tbody>\n </table>\n </div>"; //Questions Table $questionList = $objExercise->selectQuestionList(); $tool_content .= "\n <h3>{$langQuestions}</h3>\n <div class='table-responsive'>\n <table class='table-default'>\n <thead>\n <tr>\n <th>{$langTitle}</th>\n <th>Ποσοστό Επιτυχίας</th>\n </tr>\n </thead>\n <tbody>"; foreach ($questionList as $id) { $objQuestionTmp = new Question(); $objQuestionTmp->read($id); $tool_content .= "\n <tr>\n <td>" . $objQuestionTmp->selectTitle() . "</th>\n <td>\n <div class='progress'>\n <div class='progress-bar progress-bar-success progress-bar-striped' role='progressbar' aria-valuenow='" . $objQuestionTmp->successRate($exerciseId) . "' aria-valuemin='0' aria-valuemax='100' style='width: " . $objQuestionTmp->successRate($exerciseId) . "%;'>\n " . $objQuestionTmp->successRate($exerciseId) . "%\n </div>\n </div></td> \n </tr>"; } $tool_content .= "\n </tbody>\n </table>\n </div>"; draw($tool_content, 2, null, $head_content);
<h3>$langQuestions</h3> <div class='table-responsive'> <table class='table-default'> <thead> <tr> <th>$langTitle</th> <th>Ποσοστό Επιτυχίας</th> </tr> </thead> <tbody>"; foreach($questionList as $id){ $objQuestionTmp = new Question(); $objQuestionTmp->read($id); $tool_content .= " <tr> <td>".q_math($objQuestionTmp->selectTitle())."</th> <td> <div class='progress'> <div class='progress-bar progress-bar-success progress-bar-striped' role='progressbar' aria-valuenow='".$objQuestionTmp->successRate($exerciseId)."' aria-valuemin='0' aria-valuemax='100' style='width: ".$objQuestionTmp->successRate($exerciseId)."%;'> ".$objQuestionTmp->successRate($exerciseId)."% </div> </div></td> </tr>"; } $tool_content .= " </tbody> </table> </div>"; draw($tool_content, 2, null, $head_content);