function fixDocumentNameCallback($p_event, &$p_header) { global $remove_dir; $files = Session::read('doc_files_to_download'); $storedFile = $remove_dir . $p_header['stored_filename']; if (!isset($files[$storedFile])) { return 0; } $documentData = $files[$storedFile]; $documentNameFixed = DocumentManager::undoFixDocumentName($documentData['path'], $documentData['c_id'], $documentData['session_id'], $documentData['to_group_id']); // Changes file.phps to file.php $basename = basename($documentNameFixed); $basenamePHPFixed = str_replace('.phps', '.php', $basename); $documentNameFixed = str_replace($basename, $basenamePHPFixed, $documentNameFixed); if ($remove_dir != '/') { $documentNameFixed = str_replace($remove_dir, '/', $documentNameFixed); if (substr($documentNameFixed, 0, 1) == '/') { $documentNameFixed = substr($documentNameFixed, 1, api_strlen($documentNameFixed)); } } else { $documentNameFixed = ltrim($documentNameFixed, '/'); } $p_header['stored_filename'] = $documentNameFixed; return 1; }
/** * @param int $userId */ function preventMultipleLogin($userId) { $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE); $userId = intval($userId); if (api_get_settings('prevent_multiple_simultaneous_login') === 'true') { if (!empty($userId) && !api_is_anonymous()) { $isFirstLogin = Session::read('first_user_login'); if (empty($isFirstLogin)) { $sql = "SELECT login_id FROM {$table}\n WHERE login_user_id = " . $userId . " LIMIT 1"; $result = Database::query($sql); $loginData = array(); if (Database::num_rows($result)) { $loginData = Database::fetch_array($result); } $userIsReallyOnline = user_is_online($userId); // Trying double login. if (!empty($loginData) && $userIsReallyOnline == true) { session_regenerate_id(); Session::destroy(); header('Location: ' . api_get_path(WEB_PATH) . 'index.php?loginFailed=1&error=multiple_connection_not_allowed'); exit; } else { // First time Session::write('first_user_login', 1); } } } } }
/** * Starts a chat session and returns JSON array of status and chat history * @return void (prints output in JSON format) */ public function startSession() { $items = Session::read('chatHistory', []); $return = array('user_status' => $this->get_user_status(), 'me' => get_lang('Me'), 'items' => $items); echo json_encode($return); exit; }
/** * Displays info stating that the message is sent successfully. * @deprecated */ public static function display_success_message($uid) { $socialExist = Session::read('social_exist'); $userInfo = api_get_user_info($uid); if (isset($socialExist) && $socialExist === true) { if (api_get_setting('social.allow_social_tool') == 'true' && api_get_setting('message.allow_message_tool') == 'true') { $success = get_lang('MessageSentTo') . " <b>" . $userInfo['complete_name'] . "</b>"; } else { $success = get_lang('MessageSentTo') . " <b>" . $userInfo['complete_name'] . "</b>"; } } else { $success = get_lang('MessageSentTo') . " <b>" . $userInfo['complete_name'] . "</b>"; } return Display::return_message(api_xml_http_response_encode($success), 'confirmation', false); }
/** * Erase temp nanogong audio. */ public static function removeGeneratedAudioTempFile() { $tempAudio = Session::read('temp_audio_nanogong'); if (isset($tempAudio) && !empty($tempAudio) && is_file($tempAudio)) { unlink($tempAudio); Session::erase('temp_audio_nanogong'); } }
function api_is_student_view_active() { $studentView = Session::read('studentview'); return $studentView == "studentview"; }
/** * Get all the data of a glossary * * @param integer From which item * @param integer Number of items to collect * @param string Name of column on which to order * @param string Whether to sort in ascending (ASC) or descending (DESC) * @return unknown * * @author Patrick Cool <*****@*****.**> * @author Julio Montoya fixing this function, adding intvals * @version januari 2009, dokeos 1.8.6 */ public static function get_glossary_data($from, $number_of_items, $column, $direction) { $_user = api_get_user_info(); // Database table definition $t_glossary = Database::get_course_table(TABLE_GLOSSARY); $t_item_propery = Database::get_course_table(TABLE_ITEM_PROPERTY); $glossaryView = Session::read('glossary_view'); if (api_is_allowed_to_edit(null, true)) { $col2 = " glossary.glossary_id\tas col2, "; } else { $col2 = " "; } //condition for the session $session_id = api_get_session_id(); $condition_session = api_get_session_condition($session_id, true, true, 'glossary.session_id'); $column = intval($column); if (!in_array($direction, array('DESC', 'ASC'))) { $direction = 'ASC'; } $from = intval($from); $number_of_items = intval($number_of_items); $sql = "SELECT\n glossary.name \t\t\tas col0,\n\t\t\t\t\tglossary.description \tas col1,\n\t\t\t\t\t{$col2}\n\t\t\t\t\tglossary.session_id\n\t\t\t\tFROM {$t_glossary} glossary, {$t_item_propery} ip\n\t\t\t\tWHERE\n\t\t\t\t glossary.glossary_id = ip.ref AND\n\t\t\t\t\ttool = '" . TOOL_GLOSSARY . "' {$condition_session} AND\n\t\t\t\t\tglossary.c_id = " . api_get_course_int_id() . " AND\n\t\t\t\t\tip.c_id = " . api_get_course_int_id() . "\n\t\t ORDER BY col{$column} {$direction}\n\t\t LIMIT {$from},{$number_of_items}"; $res = Database::query($sql); $return = array(); $array = array(); while ($data = Database::fetch_array($res)) { // Validation when belongs to a session $session_img = api_get_session_image($data['session_id'], $_user['status']); $array[0] = $data[0] . $session_img; if (!$glossaryView || $glossaryView == 'table') { $array[1] = str_replace(array('<p>', '</p>'), array('', '<br />'), $data[1]); } else { $array[1] = $data[1]; } if (api_is_allowed_to_edit(null, true)) { $array[2] = $data[2]; } $return[] = $array; } return $return; }
$form_count = 0; if (api_is_allowed_to_edit(false, true)) { //if is called from a learning path lp_id $lp_id = isset($_REQUEST['lp_id']) ? intval($_REQUEST['lp_id']) : null; handle_forum_and_forumcategories($lp_id); } // Notification if ($actions == 'notify' && isset($_GET['content']) && isset($_GET['id'])) { if (api_get_session_id() != 0 && api_is_allowed_to_session_edit(false, true) == false) { api_not_allowed(); } $return_message = set_notification($_GET['content'], $_GET['id']); Display::display_confirmation_message($return_message, false); } get_whats_new(); $whatsnew_post_info = Session::read('whatsnew_post_info'); /* TRACKING */ Event::event_access_tool(TOOL_FORUM); /* RETRIEVING ALL THE FORUM CATEGORIES AND FORUMS note: we do this here just after het handling of the actions to be sure that we already incorporate the latest changes */ // Step 1: We store all the forum categories in an array $forum_categories. $forumCategories = get_forum_categories(); // Step 2: We find all the forums (only the visible ones if it is a student). // display group forum in general forum tool depending to configuration option $setting = api_get_setting('display_groups_forum_in_general_tool'); $forum_list = get_forums('', '', $setting == 'true'); $user_id = api_get_user_id(); /* RETRIEVING ALL GROUPS AND THOSE OF THE USER */
/** * Get the thematic advances to display on the current page (fill the sortable-table) * @param int offset of first user to recover * @param int Number of users to get * @param int Column to sort on * @param string Order (ASC,DESC) * @see SortableTable#get_table_data($from) */ public static function get_thematic_advance_data($from, $number_of_items, $column, $direction) { $thematic_id = Session::read('thematic_id'); $tbl_thematic_advance = Database::get_course_table(TABLE_THEMATIC_ADVANCE); $column = intval($column); $from = intval($from); $number_of_items = intval($number_of_items); if (!in_array($direction, array('ASC', 'DESC'))) { $direction = 'ASC'; } $data = array(); $course_id = api_get_course_int_id(); if (api_is_allowed_to_edit(null, true)) { $sql = "SELECT id AS col0, start_date AS col1, duration AS col2, content AS col3\n FROM {$tbl_thematic_advance}\n \t\t\t\tWHERE c_id = {$course_id} AND thematic_id = {$thematic_id}\n \t\t\t\tORDER BY col{$column} {$direction}\n \t\t\t\tLIMIT {$from},{$number_of_items} "; $list = api_get_item_property_by_tool('thematic_advance', api_get_course_id(), api_get_session_id()); $elements = array(); foreach ($list as $value) { $elements[] = $value['ref']; } $res = Database::query($sql); $i = 1; while ($thematic_advance = Database::fetch_row($res)) { if (in_array($thematic_advance[0], $elements)) { $thematic_advance[1] = api_get_local_time($thematic_advance[1]); $thematic_advance[1] = api_format_date($thematic_advance[1], DATE_TIME_FORMAT_LONG); $actions = ''; $actions .= '<a href="index.php?' . api_get_cidreq() . '&action=thematic_advance_edit&thematic_id=' . $thematic_id . '&thematic_advance_id=' . $thematic_advance[0] . '">' . Display::return_icon('edit.png', get_lang('Edit'), '', 22) . '</a>'; $actions .= '<a onclick="javascript:if(!confirm(\'' . get_lang('AreYouSureToDelete') . '\')) return false;" href="index.php?' . api_get_cidreq() . '&action=thematic_advance_delete&thematic_id=' . $thematic_id . '&thematic_advance_id=' . $thematic_advance[0] . '">' . Display::return_icon('delete.png', get_lang('Delete'), '', 22) . '</a></center>'; $data[] = array($i, $thematic_advance[1], $thematic_advance[2], $thematic_advance[3], $actions); $i++; } } } return $data; }
$term_preview = LegalManager::get_last_condition($language); } } // Version and language $form->addElement('hidden', 'legal_accept_type', $term_preview['version'] . ':' . $term_preview['language_id']); $form->addElement('hidden', 'legal_info', $term_preview['legal_id'] . ':' . $term_preview['language_id']); if ($term_preview['type'] == 1) { $form->addElement('checkbox', 'legal_accept', null, get_lang('IHaveReadAndAgree') . ' <a href="inscription.php?legal" target="_blank">' . get_lang('TermsAndConditions') . '</a>'); $form->addRule('legal_accept', get_lang('ThisFieldIsRequired'), 'required'); } else { $preview = LegalManager::show_last_condition($term_preview); $form->addElement('label', null, $preview); } } $form->addButtonCreate(get_lang('RegisterUser')); $course_code_redirect = Session::read('course_redirect'); if ($form->validate()) { $values = $form->getSubmitValues(1); // Make *sure* the login isn't too long if (isset($values['username'])) { $values['username'] = api_substr($values['username'], 0, USERNAME_MAX_LENGTH); } if (api_get_setting('registration.allow_registration_as_teacher') == 'false') { $values['status'] = STUDENT; } if (empty($values['official_code']) && !empty($values['username'])) { $values['official_code'] = api_strtoupper($values['username']); } if (api_get_setting('profile.login_is_email') == 'true') { $values['username'] = $values['email']; }
Display :: display_header(null); echo '<div class="actions">'; echo '<a href="'.api_get_path(WEB_CODE_PATH).'work/work.php?'.api_get_cidreq().'&origin='.$origin.'">'.Display::return_icon('back.png', get_lang('BackToWorksList'),'',ICON_SIZE_MEDIUM).'</a>'; if (api_is_allowed_to_session_edit(false, true) && !empty($workId)) { echo '<a href="'.api_get_path(WEB_CODE_PATH).'work/upload.php?'.api_get_cidreq().'&id='.$workId.'&origin='.$origin.'">'; echo Display::return_icon('upload_file.png', get_lang('UploadADocument'), '', ICON_SIZE_MEDIUM).'</a>'; } echo '</div>'; if (!empty($my_folder_data['title'])) { echo Display::page_subheader($my_folder_data['title']); } $error_message = Session::read('error_message'); if (!empty($error_message)) { echo $error_message; Session::erase('error_message'); } if (!empty($my_folder_data['description'])) { echo '<p><div><strong>'.get_lang('Description').':</strong><p>'.Security::remove_XSS($my_folder_data['description']).'</p></div></p>'; } $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : null; $item_id = isset($_REQUEST['item_id']) ? intval($_REQUEST['item_id']) : null; switch ($action) { case 'delete': $fileDeleted = deleteWorkItem($item_id, $courseInfo);
$time_control = false; $clock_expired_time = ExerciseLib::get_session_time_control_key($objExercise->id, $learnpath_id, $learnpath_item_id); if ($objExercise->expired_time != 0 && !empty($clock_expired_time)) { $time_control = true; } if ($time_control) { // Get time left for exipiring time $time_left = api_strtotime($clock_expired_time, 'UTC') - time(); $htmlHeadXtra[] = api_get_css(api_get_path(WEB_LIBRARY_PATH) . 'javascript/epiclock/stylesheet/jquery.epiclock.css'); $htmlHeadXtra[] = api_get_css(api_get_path(WEB_LIBRARY_PATH) . 'javascript/epiclock/renderers/minute/epiclock.minute.css'); $htmlHeadXtra[] = api_get_js('epiclock/javascript/jquery.dateformat.min.js'); $htmlHeadXtra[] = api_get_js('epiclock/javascript/jquery.epiclock.min.js'); $htmlHeadXtra[] = api_get_js('epiclock/renderers/minute/epiclock.minute.js'); $htmlHeadXtra[] = $objExercise->show_time_control_js($time_left); } $exe_id = intval(Session::read('exe_id')); $exercise_stat_info = $objExercise->get_stat_track_exercise_info_by_exe_id($exe_id); if (!empty($exercise_stat_info['data_tracking'])) { $question_list = explode(',', $exercise_stat_info['data_tracking']); } if (empty($exercise_stat_info) || empty($question_list)) { api_not_allowed(); } $nameTools = get_lang('Exercises'); $interbreadcrumb[] = array("url" => "exercise.php?" . api_get_cidreq(), "name" => get_lang('Exercises')); if ($origin != 'learnpath') { //so we are not in learnpath tool Display::display_header($nameTools, get_lang('Exercise')); } else { Display::display_reduced_header(); }
* and frames refresh * @author Denes Nagy <*****@*****.**> (original author - 2003-2004) * @author Yannick Warnier <*****@*****.**> (extended and maintained - 2005-2014) * @version v 1.2 * @access public * @package chamilo.learnpath.scorm */ // If you open the imsmanifest.xml via local machine (f.ex.: file://c:/...), then the Apiwrapper.js // of Maritime Navigation when trying to execute this row // var result = api.LMSInitialize(""); // get the error response : you are not authorized to call this function // Flag to allow for anonymous user - needs to be set before global.inc.php. $use_anonymous = true; //require_once '../inc/global.inc.php'; \Chamilo\CoreBundle\Framework\Container::$legacyTemplate = 'layout_empty.html.twig'; $file = Session::read('file'); /** @var learnpath $oLP */ $oLP = learnpath::getCurrentLpFromSession(); /** @var learnpathItem $oItem */ $oItem = isset($oLP->items[$oLP->current]) ? $oLP->items[$oLP->current] : null; if (!is_object($oItem)) { error_log('New LP - scorm_api - Could not load oItem item', 0); exit; } $autocomplete_when_80pct = 0; $user = api_get_user_info(); $userId = api_get_user_id(); header('Content-type: text/javascript'); ?> var scorm_logs=<?php echo (empty($oLP->scorm_debug) or !api_is_course_admin() && !api_is_platform_admin()) ? '0' : '3';
/** * function which redifines Question::createAnswersForm * @param FormValidator $form * @param the answers number to display */ function createAnswersForm($form) { // getting the exercise list $obj_ex = Session::read('objExercise'); $editor_config = array('ToolbarSet' => 'TestProposedAnswer', 'Width' => '100%', 'Height' => '125'); //this line define how many question by default appear when creating a choice question $nb_answers = isset($_POST['nb_answers']) ? (int) $_POST['nb_answers'] : 3; // The previous default value was 2. See task #1759. $nb_answers += isset($_POST['lessAnswers']) ? -1 : (isset($_POST['moreAnswers']) ? 1 : 0); /* Types of Feedback $feedback_option[0]=get_lang('Feedback'); $feedback_option[1]=get_lang('DirectFeedback'); $feedback_option[2]=get_lang('NoFeedback'); */ $feedback_title = ''; $comment_title = ''; if ($obj_ex->selectFeedbackType() == 1) { $editor_config['Width'] = '250'; $editor_config['Height'] = '110'; $comment_title = '<th width="50%" >' . get_lang('Comment') . '</th>'; $feedback_title = '<th width="50%" >' . get_lang('Scenario') . '</th>'; } else { $comment_title = '<th width="50%">' . get_lang('Comment') . '</th>'; } $html = '<table class="table table-striped table-hover">'; $html .= '<thead>'; $html .= '<tr>'; $html .= '<th>' . get_lang('Number') . '</th>'; $html .= '<th>' . get_lang('True') . '</th>'; $html .= '<th width="50%">' . get_lang('Answer') . '</th>'; $html .= $comment_title . $feedback_title; $html .= '<th>' . get_lang('Weighting') . '</th>'; $html .= '</tr>'; $html .= '</thead>'; $html .= '<tbody>'; $form->addHeader(get_lang('Answers')); $form->addHtml($html); $defaults = array(); $correct = 0; $answer = false; if (!empty($this->id)) { $answer = new Answer($this->id); $answer->read(); if (count($answer->nbrAnswers) > 0 && !$form->isSubmitted()) { $nb_answers = $answer->nbrAnswers; } } $temp_scenario = array(); if ($nb_answers < 1) { $nb_answers = 1; Display::display_normal_message(get_lang('YouHaveToCreateAtLeastOneAnswer')); } $editQuestion = isset($_GET['editQuestion']) ? $_GET['editQuestion'] : false; if ($editQuestion) { //fixing $nb_answers $new_list = array(); $count = 1; if (isset($_POST['lessAnswers'])) { $lessFromSession = Session::read('less_answer'); if (!isset($lessFromSession)) { Session::write('less_answer', $this->id); $nb_answers--; } } for ($k = 1; $k <= $nb_answers; ++$k) { if ($answer->position[$k] != '666') { $new_list[$count] = $count; $count++; } } } else { for ($k = 1; $k <= $nb_answers; ++$k) { $new_list[$k] = $k; } } $i = 1; //for ($k = 1 ; $k <= $real_nb_answers; $k++) { foreach ($new_list as $key) { $i = $key; $form->addElement('html', '<tr>'); if (is_object($answer)) { if ($answer->position[$i] == 666) { //we set nothing } else { if ($answer->correct[$i]) { $correct = $i; } $answer_result = $answer->answer[$i]; $weight_result = float_format($answer->weighting[$i], 1); if ($nb_answers == $i) { $weight_result = '0'; } $defaults['answer[' . $i . ']'] = $answer_result; $defaults['comment[' . $i . ']'] = $answer->comment[$i]; $defaults['weighting[' . $i . ']'] = $weight_result; $item_list = explode('@@', $answer->destination[$i]); $try = $item_list[0]; $lp = $item_list[1]; $list_dest = $item_list[2]; $url = $item_list[3]; if ($try == 0) { $try_result = 0; } else { $try_result = 1; } if ($url == 0) { $url_result = ''; } else { $url_result = $url; } $temp_scenario['url' . $i] = $url_result; $temp_scenario['try' . $i] = $try_result; $temp_scenario['lp' . $i] = $lp; $temp_scenario['destination' . $i] = $list_dest; } } $defaults['scenario'] = $temp_scenario; $renderer =& $form->defaultRenderer(); $renderer->setElementTemplate('<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>', 'correct'); $renderer->setElementTemplate('<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>', 'counter[' . $i . ']'); $renderer->setElementTemplate('<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>', 'answer[' . $i . ']'); $renderer->setElementTemplate('<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>', 'comment[' . $i . ']'); $renderer->setElementTemplate('<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>', 'weighting[' . $i . ']'); $answer_number = $form->addElement('text', 'counter[' . $i . ']', null, 'value="' . $i . '"'); $answer_number->freeze(); $form->addElement('radio', 'correct', null, null, $i, 'class="checkbox" style="margin-left: 0em;"'); $form->addHtmlEditor('answer[' . $i . ']', null, array(), false, $editor_config); $form->addHtmlEditor('comment[' . $i . ']', null, array(), false, $editor_config); $form->addElement('text', 'weighting[' . $i . ']', null, array('style' => 'width: 60px;', 'value' => '0')); $form->addElement('html', '</tr>'); $i++; } if (empty($this->id)) { $form->addElement('hidden', 'new_question', 1); } //Adding the "I don't know" question answer //if (empty($this -> id)) { $i = 666; $form->addHtml('<tr>'); $defaults['answer[' . $i . ']'] = get_lang('DontKnow'); $defaults['weighting[' . $i . ']'] = 0; $defaults['scenario'] = $temp_scenario; $renderer =& $form->defaultRenderer(); $renderer->setElementTemplate('<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>', 'correct'); $renderer->setElementTemplate('<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>', 'counter[' . $i . ']'); $renderer->setElementTemplate('<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>', 'answer[' . $i . ']'); $renderer->setElementTemplate('<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>', 'comment[' . $i . ']'); $renderer->setElementTemplate('<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>', 'weighting[' . $i . ']'); $answer_number = $form->addElement('text', 'counter[' . $i . ']', null, 'value="-"'); $answer_number->freeze(); $form->addElement('hidden', 'position[' . $i . ']', '666'); $form->addElement('radio', 'correct', null, null, $i, 'class="checkbox" style="margin-left: 0em;"'); $form->addHtmlEditor('answer[' . $i . ']', null, array(), false, $editor_config); $form->addRule('answer[' . $i . ']', get_lang('ThisFieldIsRequired'), 'required'); $form->addHtmlEditor('comment[' . $i . ']', null, array(), false, $editor_config); //$form->addElement('select', 'destination'.$i, get_lang('SelectQuestion').' : ',$select_question,'multiple'); $form->addText("weighting[{$i}]", null, false, ['style' => 'width: 60px;', 'value' => 0, 'readonly' => 'readonly']); $form->addHTml('</tr>'); $form->addHtml('</tbody></table>'); $buttonGroup = []; global $text, $class; //ie6 fix if ($obj_ex->edit_exercise_in_lp == true) { //setting the save button here and not in the question class.php $buttonGroup[] = $form->addButtonDelete(get_lang('LessAnswer'), 'lessAnswers', true); $buttonGroup[] = $form->addButtonCreate(get_lang('PlusAnswer'), 'moreAnswers', true); $buttonGroup[] = $form->addButtonSave($text, 'submitQuestion', true); $form->addGroup($buttonGroup); } //We check the first radio button to be sure a radio button will be check if ($correct == 0) { $correct = 1; } $defaults['correct'] = $correct; if (!empty($this->id)) { $form->setDefaults($defaults); } else { $form->setDefaults($defaults); } $form->addElement('hidden', 'nb_answers'); $form->setConstants(array('nb_answers' => $nb_answers)); }
/** * Direct course link see #5299 * * You can send to your students an URL like this * http://chamilodev.beeznest.com/main/auth/inscription.php?c=ABC&e=3 * Where "c" is the course code and "e" is the exercise Id, after a successful * registration the user will be sent to the course or exercise * */ public static function redirectToCourse($form_data) { $course_code_redirect = Session::read('course_redirect'); $_user = api_get_user_info(); $user_id = api_get_user_id(); if (!empty($course_code_redirect)) { $course_info = api_get_course_info($course_code_redirect); if (!empty($course_info)) { if (in_array($course_info['visibility'], array(COURSE_VISIBILITY_OPEN_PLATFORM, COURSE_VISIBILITY_OPEN_WORLD))) { if (CourseManager::is_user_subscribed_in_course($user_id, $course_info['code'])) { $form_data['action'] = $course_info['course_public_url']; $form_data['message'] = sprintf(get_lang('YouHaveBeenRegisteredToCourseX'), $course_info['title']); $form_data['button'] = Display::button('next', get_lang('GoToCourse', null, $_user['language']), array('class' => 'btn btn-primary btn-large')); $exercise_redirect = intval(Session::read('exercise_redirect')); // Specify the course id as the current context does not // hold a global $_course array $objExercise = new Exercise($course_info['real_id']); $result = $objExercise->read($exercise_redirect); if (!empty($exercise_redirect) && !empty($result)) { $form_data['action'] = api_get_path(WEB_CODE_PATH) . 'exercice/overview.php?exerciseId=' . $exercise_redirect . '&cidReq=' . $course_info['code']; $form_data['message'] .= '<br />' . get_lang('YouCanAccessTheExercise'); $form_data['button'] = Display::button('next', get_lang('Go', null, $_user['language']), array('class' => 'btn btn-primary btn-large')); } if (!empty($form_data['action'])) { header('Location: ' . $form_data['action']); exit; } } } } } return $form_data; }
require 'header_frame.inc.php'; ?> <form name="formHidden" method="post" action="<?php echo api_get_self() . '?' . api_get_cidreq(); ?> "> <input type="hidden" name="chat_size_old" value="<?php echo $chat_size_new; ?> "> <input type="hidden" name="connected_old" value="<?php echo $connected_new; ?> "> </form> <?php $origin = Session::read('origin'); if ($origin == 'whoisonline') { //check if our target has denied our request or not $talk_to = Session::read('target'); $track_user_table = Database::get_main_table(TABLE_MAIN_USER); $sql = "select chatcall_text from {$track_user_table} where ( user_id = {$talk_to} )"; $result = Database::query($sql); $row = Database::fetch_array($result); if ($row['chatcall_text'] == 'DENIED') { echo "<script language=\"javascript\" type=\"text/javascript\"> alert('" . get_lang('ChatDenied') . "'); </script>"; $sql = "update {$track_user_table} set chatcall_user_id = '', chatcall_date = '', chatcall_text='' WHERE (user_id = {$talk_to})"; $result = Database::query($sql); } } require 'footer_frame.inc.php';
$content = '<p><div><strong>' . get_lang('Description') . ':</strong><p>' . Security::remove_XSS($my_folder_data['description'], STUDENT) . '</p></div></p>'; } if (api_is_allowed_to_edit() || api_is_coach()) { // Work list $content .= '<div class="toolbar-works"><a id="open-view-list" class="btn btn-primary" href="#"><i class="fa fa-users"></i> Ver Estudiantes</a></div>'; $content .= '<div class="row">'; $content .= '<div class="col-md-12">'; $content .= '<div id="work-list" class="table-responsive">'; $content .= showTeacherWorkGrid(); $content .= '</div>'; $content .= '</div>'; $content .= '<div id="student-list-work" style="display: none" class="table-responsive">'; $content .= '<div class="toolbar"><a id="closed-view-list" href="#"><i class="fa fa-times-circle"></i> ' . get_lang('Close') . '</a></div>'; $content .= showStudentList($work_id); $content .= '</div>'; } else { $content .= showStudentWorkGrid(); } break; } Display::display_header(null); Display::display_introduction_section(TOOL_STUDENTPUBLICATION); if ($origin == 'learnpath') { echo '<div style="height:15px"> </div>'; } display_action_links($work_id, $curdirpath, $action); $message = Session::read('message'); echo $message; Session::erase('message'); echo $content; Display::display_footer();
/** * Returns the current user (logged in user) relationship with the course. * I.e his role * * @return array */ public function user() { $result = Session::read('_courseUser'); $result = $result ? $result : array(); return $result; }
$filepath = api_get_path(SYS_COURSE_PATH) . $_course['path'] . '/document/'; $dir = '/'; } if (!empty($groupId)) { $interbreadcrumb[] = array("url" => "../group/group_space.php?" . api_get_cidreq(), "name" => get_lang('GroupSpace')); $group = GroupManager::get_group_properties($groupId); $path = explode('/', $dir); if ('/' . $path[1] != $group['directory']) { api_not_allowed(true); } } $interbreadcrumb[] = array("url" => "./document.php?id=" . $document_id . '&' . api_get_cidreq(), "name" => get_lang('Documents')); if (!$is_allowed_in_course) { api_not_allowed(true); } $rights = Session::read('group_member_with_upload_rights'); if (!($is_allowed_to_edit || $rights || DocumentManager::is_my_shared_folder(api_get_user_id(), Security::remove_XSS($dir), api_get_session_id()))) { api_not_allowed(true); } /* Header */ Event::event_access_tool(TOOL_DOCUMENT); $display_dir = $dir; if (isset($group)) { $display_dir = explode('/', $dir); unset($display_dir[0]); unset($display_dir[1]); $display_dir = implode('/', $display_dir); } // Interbreadcrumb for the current directory root path $counter = 0; if (isset($document_data['parents'])) {
/** * @param int $questionId * @param int $in_display_category_name * @return null|string */ public static function returnCategoryAndTitle($questionId, $in_display_category_name = 1) { $is_student = !(api_is_allowed_to_edit(null, true) || api_is_session_admin()); $objExercise = Session::read('objExercise'); if (!empty($objExercise)) { $in_display_category_name = $objExercise->display_category_name; } $content = null; if (TestCategory::getCategoryNameForQuestion($questionId) != "" && ($in_display_category_name == 1 || !$is_student)) { $content .= '<div class="page-header">'; $content .= '<h4>' . get_lang('Category') . ": " . TestCategory::getCategoryNameForQuestion($questionId) . '</h4>'; $content .= "</div>"; } return $content; }
$url = api_get_course_url($course_code, $session_id); if ($form->validate()) { $accept_legal = $form->exportValue('accept_legal'); if ($accept_legal == 1) { CourseManager::save_user_legal($user_id, $course_code, $session_id); if (api_check_user_access_to_legal($course_info['visibility'])) { Session::write($variable, true); } if ($pluginLegal) { header('Location:' . $url); exit; } } } $user_pass_open_course = false; if (api_check_user_access_to_legal($course_info['visibility']) && Session::read($variable)) { $user_pass_open_course = true; } if (empty($session_id)) { if (CourseManager::is_user_subscribed_in_course($user_id, $course_code) || api_check_user_access_to_legal($course_info['visibility'])) { $user_accepted_legal = CourseManager::is_user_accepted_legal($user_id, $course_code); if ($user_accepted_legal || $user_pass_open_course) { //Redirect to course home header('Location: ' . $url); exit; } } else { api_not_allowed(); } } else { if (api_is_platform_admin()) {
/** * This function is used to find all the information about what's new in the forum tool * @return void * * @author Patrick Cool <*****@*****.**>, Ghent University * @version february 2006, dokeos 1.8 */ function get_whats_new() { $_user = api_get_user_info(); $_course = api_get_course_info(); $table_posts = Database::get_course_table(TABLE_FORUM_POST); $tracking_last_tool_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS); // Note: This has to be replaced by the tool constant later. But temporarily bb_forum is used since this is the only thing that is in the tracking currently. //$tool = TOOL_FORUM; $tool = TOOL_FORUM; // // to do: Remove this. For testing purposes only. //Session::erase('last_forum_access'); //Session::erase('whatsnew_post_info'); $course_id = api_get_course_int_id(); $lastForumAccess = Session::read('last_forum_access'); if (!$lastForumAccess) { $sql = "SELECT * FROM " . $tracking_last_tool_access . "\n WHERE\n access_user_id='" . Database::escape_string($_user['user_id']) . "' AND\n c_id ='" . $course_id . "' AND\n access_tool='" . Database::escape_string($tool) . "'"; $result = Database::query($sql); $row = Database::fetch_array($result); Session::write('last_forum_access', $row['access_date']); } $whatsNew = Session::read('whatsnew_post_info'); if (!$whatsNew) { if ($lastForumAccess != '') { $whatsnew_post_info = array(); $access = Session::read('last_forum_access'); $sql = "SELECT * FROM {$table_posts}\n WHERE\n c_id = {$course_id} AND\n post_date >'" . Database::escape_string($access) . "'"; // note: check the performance of this query. $result = Database::query($sql); while ($row = Database::fetch_array($result)) { $whatsnew_post_info[$row['forum_id']][$row['thread_id']][$row['post_id']] = $row['post_date']; } $_SESSION['whatsnew_post_info'] = $whatsnew_post_info; } } }
/** * Calculate the score of this evaluation * @param int $stud_id (default: all students who have results for this eval - then the average is returned) * @param string $type (best, average, ranking) * @return array (score, max) if student is given * array (sum of scores, number of scores) otherwise * or null if no scores available */ public function calc_score($stud_id = null, $type = null) { $useSession = true; if (isset($stud_id) && empty($type)) { $key = 'result_score_student_list_' . api_get_course_int_id() . '_' . api_get_session_id() . '_' . $this->id . '_' . $stud_id; $data = Session::read('calc_score'); $results = isset($data[$key]) ? $data[$key] : null; if ($useSession == false) { $results = null; } if (empty($results)) { $results = Result::load(null, $stud_id, $this->id); Session::write('calc_score', array($key => $results)); } $score = 0; /** @var Result $res */ foreach ($results as $res) { $score = $res->get_score(); } return array($score, $this->get_max()); } else { $count = 0; $sum = 0; $bestResult = 0; $weight = 0; $sumResult = 0; $key = 'result_score_student_list_' . api_get_course_int_id() . '_' . api_get_session_id() . '_' . $this->id; $data = Session::read('calc_score'); $allResults = isset($data[$key]) ? $data[$key] : null; if ($useSession == false) { $allResults = null; } if (empty($allResults)) { $allResults = Result::load(null, null, $this->id); Session::write($key, $allResults); } $students = array(); /** @var Result $res */ foreach ($allResults as $res) { $score = $res->get_score(); if (!empty($score) || $score == '0') { $count++; $sum += $score / $this->get_max(); $sumResult += $score; if ($score > $bestResult) { $bestResult = $score; } $weight = $this->get_max(); } $students[$res->get_user_id()] = $score; } if (empty($count)) { return null; } switch ($type) { case 'best': return array($bestResult, $weight); break; case 'average': return array($sumResult / $count, $weight); break; case 'ranking': $students = array(); /** @var Result $res */ foreach ($allResults as $res) { $score = $res->get_score(); $students[$res->get_user_id()] = $score; } return AbstractLink::getCurrentUserRanking($stud_id, $students); break; default: return array($sum, $count); break; } } }
foreach ($deletedItems as $item) { $message .= $item['title'] . '<br />'; } $message = Display::return_message($message, 'info', false); Session::write('message', $message); } header('Location: ' . api_get_self() . '?studentId=' . $studentId . '&' . api_get_cidreq()); exit; } break; } $interbreadcrumb[] = array('url' => api_get_path(WEB_CODE_PATH) . 'work/work.php?' . api_get_cidreq(), 'name' => get_lang('StudentPublications')); $interbreadcrumb[] = array('url' => '#', 'name' => $userInfo['complete_name']); Display::display_header(null); $workPerUser = getWorkPerUser($studentId); echo Session::read('message'); Session::erase('message'); echo '<div class="actions">'; echo '<a href="' . api_get_path(WEB_CODE_PATH) . 'work/work.php?' . api_get_cidreq() . '">' . Display::return_icon('back.png', get_lang('BackToWorksList'), '', ICON_SIZE_MEDIUM) . '</a>'; if (api_is_allowed_to_edit()) { echo '<a href="' . api_get_path(WEB_CODE_PATH) . 'work/student_work.php?action=export_to_pdf&studentId=' . $studentId . '&' . api_get_cidreq() . '">' . Display::return_icon('pdf.png', get_lang('ExportToPDF'), '', ICON_SIZE_MEDIUM) . '</a>'; echo '<a href="' . api_get_path(WEB_CODE_PATH) . 'work/student_work.php?action=download&studentId=' . $studentId . '&' . api_get_cidreq() . '">' . Display::return_icon('save.png', get_lang('Download'), '', ICON_SIZE_MEDIUM) . '</a>'; echo '<a onclick="javascript:if(!confirm(\'' . get_lang('AreYouSureToDelete') . '\')) return false;" href="' . api_get_path(WEB_CODE_PATH) . 'work/student_work.php?action=delete_all&studentId=' . $studentId . '&' . api_get_cidreq() . '">' . Display::return_icon('delete.png', get_lang('DeleteAllFiles'), '', ICON_SIZE_MEDIUM) . '</a>'; } echo '</div>'; $table = new HTML_Table(array('class' => 'data_table')); $column = 0; $row = 0; $headers = array(get_lang('Title'), get_lang('HandedOutDate'), get_lang('HandOutDateLimit'), get_lang('Feedback'), get_lang('Actions'));
$tpl->assign('profiles', $profiles); $total_skills_to_search = array(); if ($form->validate()) { $values = $form->getSubmitValues(); $skills = $values['skills']; if (!empty($skills)) { $hidden_skills = isset($values['hidden_skills']) ? $values['hidden_skills'] : array(); $skills = array_merge($skills, $hidden_skills); $skills = array_filter($skills); $skills = array_unique($skills); Session::write('skills', $skills); } else { $skills = Session::read('skills', array()); } } else { $skills = Session::read('skills', array()); } $user_list = array(); $count_skills = count($skills); $users = $skill_rel_user->get_user_by_skills($skills); if (!empty($users)) { foreach ($users as $user) { $user_info = api_get_user_info($user['user_id']); $user_list[$user['user_id']]['user'] = $user_info; $my_user_skills = $skill_rel_user->get_user_skills($user['user_id']); $user_skills = array(); $found_counts = 0; foreach ($my_user_skills as $my_skill) { $found = false; if (in_array($my_skill['skill_id'], $skills)) { $found = true;
var chamilo_xajax_handler = window.oxajax; </script>';*/ if ($learnPath->mode == 'embedframe' || $learnPath->get_hide_toc_frame() == 1) { $htmlHeadXtra[] = 'hello'; } //Impress js if ($learnPath->mode == 'impress') { $lp_id = $learnPath->get_id(); $url = api_get_path(WEB_CODE_PATH) . "newscorm/lp_impress.php?lp_id={$lp_id}&" . api_get_cidreq(); header("Location: {$url}"); exit; } // Prepare variables for the test tool (just in case) - honestly, this should disappear later on. Session::write('scorm_view_id', $learnPath->get_view_id()); Session::write('scorm_item_id', $lp_item_id); $exerciseFromSession = Session::read('exerciseResult'); // Reinit exercises variables to avoid spacename clashes (see exercise tool) if (isset($exerciseResult) || isset($exerciseFromSession)) { Session::erase('exerciseResult'); Session::erase('objExercise'); Session::erase('questionList'); } // additional APIs $htmlHeadXtra[] = '<script> chamilo_courseCode = "' . $course_code . '"; </script>'; // Document API //$htmlHeadXtra[] = '<script src="js/documentapi.js" type="text/javascript" language="javascript"></script>'; // Storage API $htmlHeadXtra[] = '<script> var sv_user = \'' . api_get_user_id() . '\';
/** * function which redefines Question::createAnswersForm * @param FormValidator $form */ public function createAnswersForm($form) { $nb_answers = isset($_POST['nb_answers']) ? $_POST['nb_answers'] : 4; $nb_answers += isset($_POST['lessAnswers']) ? -1 : (isset($_POST['moreAnswers']) ? 1 : 0); $obj_ex = Session::read('objExercise'); /* Mise en variable de Affichage "Reponses" et son icone, "N�", "Vrai", "Reponse" */ $html = '<table class="data_table"> <tr> <th width="10px"> ' . get_lang('Number') . ' </th> <th width="10px"> ' . get_lang('True') . ' </th> <th width="50%"> ' . get_lang('Answer') . ' </th>'; $html .= '<th>' . get_lang('Comment') . '</th>'; $html .= '</tr>'; $form->addElement('label', get_lang('Answers') . '<br /> <img src="../img/fill_field.png">', $html); $defaults = array(); $correct = 0; $answer = false; if (!empty($this->id)) { $answer = new Answer($this->id); $answer->read(); if (count($answer->nbrAnswers) > 0 && !$form->isSubmitted()) { $nb_answers = $answer->nbrAnswers; } } #le nombre de r�ponses est bien enregistr� sous la forme int(nb) /* Ajout mise en forme nb reponse */ $form->addElement('hidden', 'nb_answers'); $boxes_names = array(); /* V�rification : Cr�action d'au moins une r�ponse */ if ($nb_answers < 1) { $nb_answers = 1; Display::display_normal_message(get_lang('YouHaveToCreateAtLeastOneAnswer')); } //D�but affichage score global dans la modification d'une question $scoreA = "0"; //par reponse $scoreG = "0"; //Global /* boucle pour sauvegarder les donn�es dans le tableau defaults */ for ($i = 1; $i <= $nb_answers; ++$i) { /* si la reponse est de type objet */ if (is_object($answer)) { $defaults['answer[' . $i . ']'] = $answer->answer[$i]; $defaults['comment[' . $i . ']'] = $answer->comment[$i]; $defaults['correct[' . $i . ']'] = $answer->correct[$i]; // start $scoreA = $answer->weighting[$i]; } if ($scoreA > 0) { $scoreG = $scoreG + $scoreA; } //------------- Fin //------------- Debut si un des scores par reponse est egal � 0 : la coche vaut 1 (coch�) if ($scoreA == 0) { $defaults['pts'] = 1; } $renderer =& $form->defaultRenderer(); $renderer->setElementTemplate('<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>', 'correct[' . $i . ']'); $renderer->setElementTemplate('<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>', 'counter[' . $i . ']'); $renderer->setElementTemplate('<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>', 'answer[' . $i . ']'); $renderer->setElementTemplate('<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>', 'comment[' . $i . ']'); //$renderer->setElementTemplate('<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>', 'weighting['.$i.']'); $answer_number = $form->addElement('text', 'counter[' . $i . ']', null, 'value="' . $i . '"'); $answer_number->freeze(); $form->addElement('checkbox', 'correct[' . $i . ']', null, null, 'class="checkbox"'); $boxes_names[] = 'correct[' . $i . ']'; $form->addHtmlEditor('answer[' . $i . ']', null, null, array('ToolbarSet' => 'TestProposedAnswer', 'Width' => '100%', 'Height' => '100')); $form->addRule('answer[' . $i . ']', get_lang('ThisFieldIsRequired'), 'required'); $form->addHtmlEditor('comment[' . $i . ']', null, null, array('ToolbarSet' => 'TestProposedAnswer', 'Width' => '100%', 'Height' => '100')); $form->addElement('html', '</tr>'); } //--------- Mise en variable du score global lors d'une modification de la question/r�ponse $defaults['weighting[1]'] = round($scoreG); $form->addElement('html', '</div></div></table>'); //$form -> addElement ('html', '<br />'); $form->add_multiple_required_rule($boxes_names, get_lang('ChooseAtLeastOneCheckbox'), 'multiple_required'); //only 1 answer the all deal ... $form->addElement('text', 'weighting[1]', get_lang('Score')); global $pts; //--------- Creation coche pour ne pas prendre en compte les n�gatifs $form->addElement('checkbox', 'pts', '', get_lang('NoNegativeScore')); $form->addElement('html', '<br />'); // Affiche un message si le score n'est pas renseign� $form->addRule('weighting[1]', get_lang('ThisFieldIsRequired'), 'required'); global $text, $class; if ($obj_ex->edit_exercise_in_lp == true) { $form->addButtonDelete(get_lang('LessAnswer'), 'lessAnswers'); $form->addButtonCreate(get_lang('PlusAnswer'), 'moreAnswers'); $form->addButtonSave($text, 'submitQuestion'); // setting the save button here and not in the question class.php } $renderer->setElementTemplate('{element} ', 'lessAnswers'); $renderer->setElementTemplate('{element} ', 'submitQuestion'); $renderer->setElementTemplate('{element}', 'moreAnswers'); $form->addElement('html', '</div></div>'); $defaults['correct'] = $correct; if (!empty($this->id)) { $form->setDefaults($defaults); } else { if ($this->isContent == 1) { $form->setDefaults($defaults); } } $form->setConstants(array('nb_answers' => $nb_answers)); }
/** * This function was originally found in the exercise_show.php * @param int $exeId * @param int $questionId * @param int $choice the user selected * @param string $from function is called from 'exercise_show' or 'exercise_result' * @param array $exerciseResultCoordinates the hotspot coordinates $hotspot[$question_id] = coordinates * @param bool $saved_results save results in the DB or just show the reponse * @param bool $from_database gets information from DB or from the current selection * @param bool $show_result show results or not * @param int $propagate_neg * @param array $hotspot_delineation_result * * @todo reduce parameters of this function * @return string html code */ public function manage_answer($exeId, $questionId, $choice, $from = 'exercise_show', $exerciseResultCoordinates = array(), $saved_results = true, $from_database = false, $show_result = true, $propagate_neg = 0, $hotspot_delineation_result = array()) { global $debug; //needed in order to use in the exercise_attempt() for the time global $learnpath_id, $learnpath_item_id; require_once api_get_path(LIBRARY_PATH) . 'geometry.lib.php'; $feedback_type = $this->selectFeedbackType(); $results_disabled = $this->selectResultsDisabled(); if ($debug) { error_log("<------ manage_answer ------> "); error_log('exe_id: ' . $exeId); error_log('$from: ' . $from); error_log('$saved_results: ' . intval($saved_results)); error_log('$from_database: ' . intval($from_database)); error_log('$show_result: ' . $show_result); error_log('$propagate_neg: ' . $propagate_neg); error_log('$exerciseResultCoordinates: ' . print_r($exerciseResultCoordinates, 1)); error_log('$hotspot_delineation_result: ' . print_r($hotspot_delineation_result, 1)); error_log('$learnpath_id: ' . $learnpath_id); error_log('$learnpath_item_id: ' . $learnpath_item_id); error_log('$choice: ' . print_r($choice, 1)); } $extra_data = array(); $final_overlap = 0; $final_missing = 0; $final_excess = 0; $overlap_color = 0; $missing_color = 0; $excess_color = 0; $threadhold1 = 0; $threadhold2 = 0; $threadhold3 = 0; $arrques = null; $arrans = null; $questionId = intval($questionId); $exeId = intval($exeId); $TBL_TRACK_ATTEMPT = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT); $table_ans = Database::get_course_table(TABLE_QUIZ_ANSWER); // Creates a temporary Question object $course_id = $this->course_id; $objQuestionTmp = Question::read($questionId, $course_id); if ($objQuestionTmp === false) { return false; } $questionName = $objQuestionTmp->selectTitle(); $questionWeighting = $objQuestionTmp->selectWeighting(); $answerType = $objQuestionTmp->selectType(); $quesId = $objQuestionTmp->selectId(); $extra = $objQuestionTmp->extra; $next = 1; //not for now // Extra information of the question if (!empty($extra)) { $extra = explode(':', $extra); if ($debug) { error_log(print_r($extra, 1)); } // Fixes problems with negatives values using intval $true_score = floatval(trim($extra[0])); $false_score = floatval(trim($extra[1])); $doubt_score = floatval(trim($extra[2])); } $totalWeighting = 0; $totalScore = 0; // Destruction of the Question object unset($objQuestionTmp); // Construction of the Answer object $objAnswerTmp = new Answer($questionId); $nbrAnswers = $objAnswerTmp->selectNbrAnswers(); if ($debug) { error_log('Count of answers: ' . $nbrAnswers); error_log('$answerType: ' . $answerType); } if ($answerType == FREE_ANSWER || $answerType == ORAL_EXPRESSION || $answerType == CALCULATED_ANSWER) { $nbrAnswers = 1; } $nano = null; if ($answerType == ORAL_EXPRESSION) { $exe_info = Event::get_exercise_results_by_attempt($exeId); $exe_info = isset($exe_info[$exeId]) ? $exe_info[$exeId] : null; $params = array(); $params['course_id'] = $course_id; $params['session_id'] = api_get_session_id(); $params['user_id'] = isset($exe_info['exe_user_id']) ? $exe_info['exe_user_id'] : api_get_user_id(); $params['exercise_id'] = isset($exe_info['exe_exo_id']) ? $exe_info['exe_exo_id'] : $this->id; $params['question_id'] = $questionId; $params['exe_id'] = isset($exe_info['exe_id']) ? $exe_info['exe_id'] : $exeId; $nano = new Nanogong($params); //probably this attempt came in an exercise all question by page if ($feedback_type == 0) { $nano->replace_with_real_exe($exeId); } } $user_answer = ''; // Get answer list for matching $sql = "SELECT id_auto, id, answer\n FROM {$table_ans}\n WHERE c_id = {$course_id} AND question_id = {$questionId}"; $res_answer = Database::query($sql); $answerMatching = array(); while ($real_answer = Database::fetch_array($res_answer)) { $answerMatching[$real_answer['id_auto']] = $real_answer['answer']; } $real_answers = array(); $quiz_question_options = Question::readQuestionOption($questionId, $course_id); $organs_at_risk_hit = 0; $questionScore = 0; if ($debug) { error_log('Start answer loop '); } $answer_correct_array = array(); for ($answerId = 1; $answerId <= $nbrAnswers; $answerId++) { $answer = $objAnswerTmp->selectAnswer($answerId); $answerComment = $objAnswerTmp->selectComment($answerId); $answerCorrect = $objAnswerTmp->isCorrect($answerId); $answerWeighting = (double) $objAnswerTmp->selectWeighting($answerId); $answerAutoId = $objAnswerTmp->selectAutoId($answerId); $answer_correct_array[$answerId] = (bool) $answerCorrect; if ($debug) { error_log("answer auto id: {$answerAutoId} "); error_log("answer correct: {$answerCorrect} "); } // Delineation $delineation_cord = $objAnswerTmp->selectHotspotCoordinates(1); $answer_delineation_destination = $objAnswerTmp->selectDestination(1); switch ($answerType) { // for unique answer case UNIQUE_ANSWER: case UNIQUE_ANSWER_IMAGE: case UNIQUE_ANSWER_NO_OPTION: if ($from_database) { $sql = "SELECT answer FROM {$TBL_TRACK_ATTEMPT}\n WHERE\n exe_id = '" . $exeId . "' AND\n question_id= '" . $questionId . "'"; $result = Database::query($sql); $choice = Database::result($result, 0, "answer"); $studentChoice = $choice == $answerAutoId ? 1 : 0; if ($studentChoice) { $questionScore += $answerWeighting; $totalScore += $answerWeighting; } } else { $studentChoice = $choice == $answerAutoId ? 1 : 0; if ($studentChoice) { $questionScore += $answerWeighting; $totalScore += $answerWeighting; } } break; // for multiple answers // for multiple answers case MULTIPLE_ANSWER_TRUE_FALSE: if ($from_database) { $choice = array(); $sql = "SELECT answer FROM {$TBL_TRACK_ATTEMPT}\n WHERE\n exe_id = {$exeId} AND\n question_id = " . $questionId; $result = Database::query($sql); while ($row = Database::fetch_array($result)) { $ind = $row['answer']; $values = explode(':', $ind); $my_answer_id = isset($values[0]) ? $values[0] : ''; $option = isset($values[1]) ? $values[1] : ''; $choice[$my_answer_id] = $option; } } $studentChoice = isset($choice[$answerAutoId]) ? $choice[$answerAutoId] : null; if (!empty($studentChoice)) { if ($studentChoice == $answerCorrect) { $questionScore += $true_score; } else { if ($quiz_question_options[$studentChoice]['name'] == "Don't know" || $quiz_question_options[$studentChoice]['name'] == "DoubtScore") { $questionScore += $doubt_score; } else { $questionScore += $false_score; } } } else { // If no result then the user just hit don't know $studentChoice = 3; $questionScore += $doubt_score; } $totalScore = $questionScore; break; case MULTIPLE_ANSWER: //2 if ($from_database) { $choice = array(); $sql = "SELECT answer FROM " . $TBL_TRACK_ATTEMPT . "\n WHERE exe_id = '" . $exeId . "' AND question_id= '" . $questionId . "'"; $resultans = Database::query($sql); while ($row = Database::fetch_array($resultans)) { $ind = $row['answer']; $choice[$ind] = 1; } $studentChoice = isset($choice[$answerAutoId]) ? $choice[$answerAutoId] : null; $real_answers[$answerId] = (bool) $studentChoice; if ($studentChoice) { $questionScore += $answerWeighting; } } else { $studentChoice = isset($choice[$answerAutoId]) ? $choice[$answerAutoId] : null; $real_answers[$answerId] = (bool) $studentChoice; if (isset($studentChoice)) { $questionScore += $answerWeighting; } } $totalScore += $answerWeighting; if ($debug) { error_log("studentChoice: {$studentChoice}"); } break; case GLOBAL_MULTIPLE_ANSWER: if ($from_database) { $choice = array(); $sql = "SELECT answer FROM {$TBL_TRACK_ATTEMPT}\n WHERE exe_id = '" . $exeId . "' AND question_id= '" . $questionId . "'"; $resultans = Database::query($sql); while ($row = Database::fetch_array($resultans)) { $ind = $row['answer']; $choice[$ind] = 1; } $studentChoice = isset($choice[$answerAutoId]) ? $choice[$answerAutoId] : null; $real_answers[$answerId] = (bool) $studentChoice; if ($studentChoice) { $questionScore += $answerWeighting; } } else { $studentChoice = isset($choice[$answerAutoId]) ? $choice[$answerAutoId] : null; if (isset($studentChoice)) { $questionScore += $answerWeighting; } $real_answers[$answerId] = (bool) $studentChoice; } $totalScore += $answerWeighting; if ($debug) { error_log("studentChoice: {$studentChoice}"); } break; case MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE: if ($from_database) { $sql = "SELECT answer FROM " . $TBL_TRACK_ATTEMPT . "\n WHERE exe_id = {$exeId} AND question_id= " . $questionId; $resultans = Database::query($sql); while ($row = Database::fetch_array($resultans)) { $ind = $row['answer']; $result = explode(':', $ind); if (isset($result[0])) { $my_answer_id = isset($result[0]) ? $result[0] : ''; $option = isset($result[1]) ? $result[1] : ''; $choice[$my_answer_id] = $option; } } $studentChoice = isset($choice[$answerAutoId]) ? $choice[$answerAutoId] : ''; if ($answerCorrect == $studentChoice) { //$answerCorrect = 1; $real_answers[$answerId] = true; } else { //$answerCorrect = 0; $real_answers[$answerId] = false; } } else { $studentChoice = $choice[$answerAutoId]; if ($answerCorrect == $studentChoice) { //$answerCorrect = 1; $real_answers[$answerId] = true; } else { //$answerCorrect = 0; $real_answers[$answerId] = false; } } break; case MULTIPLE_ANSWER_COMBINATION: if ($from_database) { $sql = "SELECT answer FROM {$TBL_TRACK_ATTEMPT}\n WHERE exe_id = {$exeId} AND question_id= {$questionId}"; $resultans = Database::query($sql); while ($row = Database::fetch_array($resultans)) { $ind = $row['answer']; $choice[$ind] = 1; } $studentChoice = isset($choice[$answerAutoId]) ? $choice[$answerAutoId] : null; if ($answerCorrect == 1) { if ($studentChoice) { $real_answers[$answerId] = true; } else { $real_answers[$answerId] = false; } } else { if ($studentChoice) { $real_answers[$answerId] = false; } else { $real_answers[$answerId] = true; } } } else { $studentChoice = isset($choice[$answerAutoId]) ? $choice[$answerAutoId] : null; if ($answerCorrect == 1) { if ($studentChoice) { $real_answers[$answerId] = true; } else { $real_answers[$answerId] = false; } } else { if ($studentChoice) { $real_answers[$answerId] = false; } else { $real_answers[$answerId] = true; } } } break; case FILL_IN_BLANKS: $str = ''; if ($from_database) { $sql = "SELECT answer\n FROM {$TBL_TRACK_ATTEMPT}\n WHERE\n exe_id = {$exeId} AND\n question_id= " . intval($questionId); $result = Database::query($sql); $str = Database::result($result, 0, 'answer'); } if ($saved_results == false && strpos($str, 'font color') !== false) { // the question is encoded like this // [A] B [C] D [E] F::10,10,10@1 // number 1 before the "@" means that is a switchable fill in blank question // [A] B [C] D [E] F::10,10,10@ or [A] B [C] D [E] F::10,10,10 // means that is a normal fill blank question // first we explode the "::" $pre_array = explode('::', $answer); // is switchable fill blank or not $last = count($pre_array) - 1; $is_set_switchable = explode('@', $pre_array[$last]); $switchable_answer_set = false; if (isset($is_set_switchable[1]) && $is_set_switchable[1] == 1) { $switchable_answer_set = true; } $answer = ''; for ($k = 0; $k < $last; $k++) { $answer .= $pre_array[$k]; } // splits weightings that are joined with a comma $answerWeighting = explode(',', $is_set_switchable[0]); // we save the answer because it will be modified $temp = $answer; $answer = ''; $j = 0; //initialise answer tags $user_tags = $correct_tags = $real_text = array(); // the loop will stop at the end of the text while (1) { // quits the loop if there are no more blanks (detect '[') if (($pos = api_strpos($temp, '[')) === false) { // adds the end of the text $answer = $temp; $real_text[] = $answer; break; //no more "blanks", quit the loop } // adds the piece of text that is before the blank //and ends with '[' into a general storage array $real_text[] = api_substr($temp, 0, $pos + 1); $answer .= api_substr($temp, 0, $pos + 1); //take the string remaining (after the last "[" we found) $temp = api_substr($temp, $pos + 1); // quit the loop if there are no more blanks, and update $pos to the position of next ']' if (($pos = api_strpos($temp, ']')) === false) { // adds the end of the text $answer .= $temp; break; } if ($from_database) { $queryfill = "SELECT answer FROM " . $TBL_TRACK_ATTEMPT . "\n WHERE\n exe_id = '" . $exeId . "' AND\n question_id= " . intval($questionId) . ""; $resfill = Database::query($queryfill); $str = Database::result($resfill, 0, 'answer'); api_preg_match_all('#\\[([^[]*)\\]#', $str, $arr); $str = str_replace('\\r\\n', '', $str); $choice = $arr[1]; if (isset($choice[$j])) { $tmp = api_strrpos($choice[$j], ' / '); $choice[$j] = api_substr($choice[$j], 0, $tmp); $choice[$j] = trim($choice[$j]); // Needed to let characters ' and " to work as part of an answer $choice[$j] = stripslashes($choice[$j]); } else { $choice[$j] = null; } } else { // This value is the user input, not escaped while correct answer is escaped by fckeditor $choice[$j] = api_htmlentities(trim($choice[$j])); } $user_tags[] = $choice[$j]; //put the contents of the [] answer tag into correct_tags[] $correct_tags[] = api_substr($temp, 0, $pos); $j++; $temp = api_substr($temp, $pos + 1); } $answer = ''; $real_correct_tags = $correct_tags; $chosen_list = array(); for ($i = 0; $i < count($real_correct_tags); $i++) { if ($i == 0) { $answer .= $real_text[0]; } if (!$switchable_answer_set) { // Needed to parse ' and " characters $user_tags[$i] = stripslashes($user_tags[$i]); if ($correct_tags[$i] == $user_tags[$i]) { // gives the related weighting to the student $questionScore += $answerWeighting[$i]; // increments total score $totalScore += $answerWeighting[$i]; // adds the word in green at the end of the string $answer .= $correct_tags[$i]; } elseif (!empty($user_tags[$i])) { // else if the word entered by the student IS NOT the same as the one defined by the professor // adds the word in red at the end of the string, and strikes it $answer .= '<font color="red"><s>' . $user_tags[$i] . '</s></font>'; } else { // adds a tabulation if no word has been typed by the student $answer .= ''; // remove that causes issue } } else { // switchable fill in the blanks if (in_array($user_tags[$i], $correct_tags)) { $chosen_list[] = $user_tags[$i]; $correct_tags = array_diff($correct_tags, $chosen_list); // gives the related weighting to the student $questionScore += $answerWeighting[$i]; // increments total score $totalScore += $answerWeighting[$i]; // adds the word in green at the end of the string $answer .= $user_tags[$i]; } elseif (!empty($user_tags[$i])) { // else if the word entered by the student IS NOT the same as the one defined by the professor // adds the word in red at the end of the string, and strikes it $answer .= '<font color="red"><s>' . $user_tags[$i] . '</s></font>'; } else { // adds a tabulation if no word has been typed by the student $answer .= ''; // remove that causes issue } } // adds the correct word, followed by ] to close the blank $answer .= ' / <font color="green"><b>' . $real_correct_tags[$i] . '</b></font>]'; if (isset($real_text[$i + 1])) { $answer .= $real_text[$i + 1]; } } } else { // insert the student result in the track_e_attempt table, field answer // $answer is the answer like in the c_quiz_answer table for the question // student data are choice[] $listCorrectAnswers = FillBlanks::getAnswerInfo($answer); $switchableAnswerSet = $listCorrectAnswers["switchable"]; $answerWeighting = $listCorrectAnswers["tabweighting"]; // user choices is an array $choice // get existing user data in n the BDD if ($from_database) { $sql = "SELECT answer\n FROM {$TBL_TRACK_ATTEMPT}\n WHERE\n exe_id = {$exeId} AND\n question_id= " . intval($questionId); $result = Database::query($sql); $str = Database::result($result, 0, 'answer'); $listStudentResults = FillBlanks::getAnswerInfo($str, true); $choice = $listStudentResults['studentanswer']; } // loop other all blanks words if (!$switchableAnswerSet) { // not switchable answer, must be in the same place than teacher order for ($i = 0; $i < count($listCorrectAnswers['tabwords']); $i++) { $studentAnswer = isset($choice[$i]) ? trim($choice[$i]) : ''; // This value is the user input, not escaped while correct answer is escaped by fckeditor // Works with cyrillic alphabet and when using ">" chars see #7718 #7610 #7618 if (!$from_database) { $studentAnswer = htmlentities(api_utf8_encode($studentAnswer)); } $correctAnswer = $listCorrectAnswers['tabwords'][$i]; $isAnswerCorrect = 0; if (FillBlanks::isGoodStudentAnswer($studentAnswer, $correctAnswer)) { // gives the related weighting to the student $questionScore += $answerWeighting[$i]; // increments total score $totalScore += $answerWeighting[$i]; $isAnswerCorrect = 1; } $listCorrectAnswers['studentanswer'][$i] = $studentAnswer; $listCorrectAnswers['studentscore'][$i] = $isAnswerCorrect; } } else { // switchable answer $listStudentAnswerTemp = $choice; $listTeacherAnswerTemp = $listCorrectAnswers['tabwords']; // for every teacher answer, check if there is a student answer for ($i = 0; $i < count($listStudentAnswerTemp); $i++) { $studentAnswer = trim($listStudentAnswerTemp[$i]); $found = false; for ($j = 0; $j < count($listTeacherAnswerTemp); $j++) { $correctAnswer = $listTeacherAnswerTemp[$j]; if (!$found) { if (FillBlanks::isGoodStudentAnswer($studentAnswer, $correctAnswer)) { $questionScore += $answerWeighting[$i]; $totalScore += $answerWeighting[$i]; $listTeacherAnswerTemp[$j] = ""; $found = true; } } } $listCorrectAnswers['studentanswer'][$i] = $studentAnswer; if (!$found) { $listCorrectAnswers['studentscore'][$i] = 0; } else { $listCorrectAnswers['studentscore'][$i] = 1; } } } $answer = FillBlanks::getAnswerInStudentAttempt($listCorrectAnswers); } break; // for calculated answer // for calculated answer case CALCULATED_ANSWER: $calculatedAnswer = Session::read('calculatedAnswerId'); $answer = $objAnswerTmp->selectAnswer($calculatedAnswer[$questionId]); $preArray = explode('@@', $answer); $last = count($preArray) - 1; $answer = ''; for ($k = 0; $k < $last; $k++) { $answer .= $preArray[$k]; } $answerWeighting = array($answerWeighting); // we save the answer because it will be modified $temp = $answer; $answer = ''; $j = 0; //initialise answer tags $userTags = $correctTags = $realText = array(); // the loop will stop at the end of the text while (1) { // quits the loop if there are no more blanks (detect '[') if (($pos = api_strpos($temp, '[')) === false) { // adds the end of the text $answer = $temp; $realText[] = $answer; break; //no more "blanks", quit the loop } // adds the piece of text that is before the blank //and ends with '[' into a general storage array $realText[] = api_substr($temp, 0, $pos + 1); $answer .= api_substr($temp, 0, $pos + 1); //take the string remaining (after the last "[" we found) $temp = api_substr($temp, $pos + 1); // quit the loop if there are no more blanks, and update $pos to the position of next ']' if (($pos = api_strpos($temp, ']')) === false) { // adds the end of the text $answer .= $temp; break; } if ($from_database) { $queryfill = "SELECT answer FROM " . $TBL_TRACK_ATTEMPT . "\n WHERE\n exe_id = '" . $exeId . "' AND\n question_id= " . intval($questionId) . ""; $resfill = Database::query($queryfill); $str = Database::result($resfill, 0, 'answer'); api_preg_match_all('#\\[([^[]*)\\]#', $str, $arr); $str = str_replace('\\r\\n', '', $str); $choice = $arr[1]; if (isset($choice[$j])) { $tmp = api_strrpos($choice[$j], ' / '); $choice[$j] = api_substr($choice[$j], 0, $tmp); $choice[$j] = trim($choice[$j]); // Needed to let characters ' and " to work as part of an answer $choice[$j] = stripslashes($choice[$j]); } else { $choice[$j] = null; } } else { // This value is the user input, not escaped while correct answer is escaped by fckeditor $choice[$j] = api_htmlentities(trim($choice[$j])); } $userTags[] = $choice[$j]; //put the contents of the [] answer tag into correct_tags[] $correctTags[] = api_substr($temp, 0, $pos); $j++; $temp = api_substr($temp, $pos + 1); } $answer = ''; $realCorrectTags = $correctTags; for ($i = 0; $i < count($realCorrectTags); $i++) { if ($i == 0) { $answer .= $realText[0]; } // Needed to parse ' and " characters $userTags[$i] = stripslashes($userTags[$i]); if ($correctTags[$i] == $userTags[$i]) { // gives the related weighting to the student $questionScore += $answerWeighting[$i]; // increments total score $totalScore += $answerWeighting[$i]; // adds the word in green at the end of the string $answer .= $correctTags[$i]; } elseif (!empty($userTags[$i])) { // else if the word entered by the student IS NOT the same as the one defined by the professor // adds the word in red at the end of the string, and strikes it $answer .= '<font color="red"><s>' . $userTags[$i] . '</s></font>'; } else { // adds a tabulation if no word has been typed by the student $answer .= ''; // remove that causes issue } // adds the correct word, followed by ] to close the blank $answer .= ' / <font color="green"><b>' . $realCorrectTags[$i] . '</b></font>]'; if (isset($realText[$i + 1])) { $answer .= $realText[$i + 1]; } } break; // for free answer // for free answer case FREE_ANSWER: if ($from_database) { $query = "SELECT answer, marks FROM " . $TBL_TRACK_ATTEMPT . "\n WHERE exe_id = '" . $exeId . "' AND question_id= '" . $questionId . "'"; $resq = Database::query($query); $data = Database::fetch_array($resq); $choice = $data['answer']; $choice = str_replace('\\r\\n', '', $choice); $choice = stripslashes($choice); $questionScore = $data['marks']; if ($questionScore == -1) { $totalScore += 0; } else { $totalScore += $questionScore; } if ($questionScore == '') { $questionScore = 0; } $arrques = $questionName; $arrans = $choice; } else { $studentChoice = $choice; if ($studentChoice) { //Fixing negative puntation see #2193 $questionScore = 0; $totalScore += 0; } } break; case ORAL_EXPRESSION: if ($from_database) { $query = "SELECT answer, marks FROM " . $TBL_TRACK_ATTEMPT . "\n WHERE exe_id = '" . $exeId . "' AND question_id= '" . $questionId . "'"; $resq = Database::query($query); $choice = Database::result($resq, 0, 'answer'); $choice = str_replace('\\r\\n', '', $choice); $choice = stripslashes($choice); $questionScore = Database::result($resq, 0, "marks"); if ($questionScore == -1) { $totalScore += 0; } else { $totalScore += $questionScore; } $arrques = $questionName; $arrans = $choice; } else { $studentChoice = $choice; if ($studentChoice) { //Fixing negative puntation see #2193 $questionScore = 0; $totalScore += 0; } } break; case DRAGGABLE: //no break //no break case MATCHING_DRAGGABLE: //no break //no break case MATCHING: if ($from_database) { $sql = 'SELECT id, answer, id_auto FROM ' . $table_ans . ' WHERE c_id = ' . $course_id . ' AND question_id = "' . $questionId . '" AND correct = 0'; $res_answer = Database::query($sql); // Getting the real answer $real_list = array(); while ($real_answer = Database::fetch_array($res_answer)) { $real_list[$real_answer['id_auto']] = $real_answer['answer']; } $sql = 'SELECT id, answer, correct, id_auto, ponderation FROM ' . $table_ans . ' WHERE c_id = ' . $course_id . ' AND question_id="' . $questionId . '" AND correct <> 0 ORDER BY id_auto'; $res_answers = Database::query($sql); $questionScore = 0; while ($a_answers = Database::fetch_array($res_answers)) { $i_answer_id = $a_answers['id']; //3 $s_answer_label = $a_answers['answer']; // your daddy - your mother $i_answer_correct_answer = $a_answers['correct']; //1 - 2 $i_answer_id_auto = $a_answers['id_auto']; // 3 - 4 $sql = "SELECT answer FROM {$TBL_TRACK_ATTEMPT}\n WHERE\n exe_id = '{$exeId}' AND\n question_id = '{$questionId}' AND\n position = '{$i_answer_id_auto}'"; $res_user_answer = Database::query($sql); if (Database::num_rows($res_user_answer) > 0) { // rich - good looking $s_user_answer = Database::result($res_user_answer, 0, 0); } else { $s_user_answer = 0; } $i_answerWeighting = $a_answers['ponderation']; $user_answer = ''; if (!empty($s_user_answer)) { if ($answerType == DRAGGABLE) { if ($s_user_answer == $i_answer_correct_answer) { $questionScore += $i_answerWeighting; $totalScore += $i_answerWeighting; $user_answer = Display::label(get_lang('Correct'), 'success'); } else { $user_answer = Display::label(get_lang('Incorrect'), 'danger'); } } else { if ($s_user_answer == $i_answer_correct_answer) { $questionScore += $i_answerWeighting; $totalScore += $i_answerWeighting; if (isset($real_list[$i_answer_id])) { $user_answer = Display::span($real_list[$i_answer_id]); } } else { $user_answer = Display::span($real_list[$s_user_answer], ['style' => 'color: #FF0000; text-decoration: line-through;']); } } } elseif ($answerType == DRAGGABLE) { $user_answer = Display::label(get_lang('Incorrect'), 'danger'); } if ($show_result) { echo '<tr>'; echo '<td>' . $s_answer_label . '</td>'; echo '<td>' . $user_answer; if (in_array($answerType, [MATCHING, MATCHING_DRAGGABLE])) { if (isset($real_list[$i_answer_correct_answer])) { echo Display::span($real_list[$i_answer_correct_answer], ['style' => 'color: #008000; font-weight: bold;']); } } echo '</td>'; echo '</tr>'; } } break 2; // break the switch and the "for" condition } else { if ($answerCorrect) { if (isset($choice[$answerAutoId]) && $answerCorrect == $choice[$answerAutoId]) { $questionScore += $answerWeighting; $totalScore += $answerWeighting; $user_answer = Display::span($answerMatching[$choice[$answerAutoId]]); } else { if (isset($answerMatching[$choice[$answerAutoId]])) { $user_answer = Display::span($answerMatching[$choice[$answerAutoId]], ['style' => 'color: #FF0000; text-decoration: line-through;']); } } $matching[$answerAutoId] = $choice[$answerAutoId]; } break; } case HOT_SPOT: if ($from_database) { $TBL_TRACK_HOTSPOT = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT); $sql = "SELECT hotspot_correct\n FROM {$TBL_TRACK_HOTSPOT}\n WHERE\n hotspot_exe_id = '" . $exeId . "' AND\n hotspot_question_id= '" . $questionId . "' AND\n hotspot_answer_id = " . intval($answerAutoId) . ""; $result = Database::query($sql); $studentChoice = Database::result($result, 0, "hotspot_correct"); if ($studentChoice) { $questionScore += $answerWeighting; $totalScore += $answerWeighting; } } else { if (!isset($choice[$answerAutoId])) { $choice[$answerAutoId] = 0; } else { $studentChoice = $choice[$answerAutoId]; $choiceIsValid = false; if (!empty($studentChoice)) { $hotspotType = $objAnswerTmp->selectHotspotType($answerId); $hotspotCoordinates = $objAnswerTmp->selectHotspotCoordinates($answerId); $choicePoint = Geometry::decodePoint($studentChoice); switch ($hotspotType) { case 'square': $hotspotProperties = Geometry::decodeSquare($hotspotCoordinates); $choiceIsValid = Geometry::pointIsInSquare($hotspotProperties, $choicePoint); break; case 'circle': $hotspotProperties = Geometry::decodeEllipse($hotspotCoordinates); $choiceIsValid = Geometry::pointIsInEllipse($hotspotProperties, $choicePoint); break; case 'poly': $hotspotProperties = Geometry::decodePolygon($hotspotCoordinates); $choiceIsValid = Geometry::pointIsInPolygon($hotspotProperties, $choicePoint); break; } } $choice[$answerAutoId] = 0; if ($choiceIsValid) { $questionScore += $answerWeighting; $totalScore += $answerWeighting; $choice[$answerAutoId] = 1; } } } break; // @todo never added to chamilo //for hotspot with fixed order // @todo never added to chamilo //for hotspot with fixed order case HOT_SPOT_ORDER: $studentChoice = $choice['order'][$answerId]; if ($studentChoice == $answerId) { $questionScore += $answerWeighting; $totalScore += $answerWeighting; $studentChoice = true; } else { $studentChoice = false; } break; // for hotspot with delineation // for hotspot with delineation case HOT_SPOT_DELINEATION: if ($from_database) { // getting the user answer $TBL_TRACK_HOTSPOT = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT); $query = "SELECT hotspot_correct, hotspot_coordinate\n FROM {$TBL_TRACK_HOTSPOT}\n WHERE\n hotspot_exe_id = '" . $exeId . "' AND\n hotspot_question_id= '" . $questionId . "' AND\n hotspot_answer_id='1'"; //by default we take 1 because it's a delineation $resq = Database::query($query); $row = Database::fetch_array($resq, 'ASSOC'); $choice = $row['hotspot_correct']; $user_answer = $row['hotspot_coordinate']; // THIS is very important otherwise the poly_compile will throw an error!! // round-up the coordinates $coords = explode('/', $user_answer); $user_array = ''; foreach ($coords as $coord) { list($x, $y) = explode(';', $coord); $user_array .= round($x) . ';' . round($y) . '/'; } $user_array = substr($user_array, 0, -1); } else { if (!empty($studentChoice)) { $newquestionList[] = $questionId; } if ($answerId === 1) { $studentChoice = $choice[$answerId]; $questionScore += $answerWeighting; if ($hotspot_delineation_result[1] == 1) { $totalScore += $answerWeighting; //adding the total } } } $_SESSION['hotspot_coord'][1] = $delineation_cord; $_SESSION['hotspot_dest'][1] = $answer_delineation_destination; break; } // end switch Answertype if ($show_result) { if ($debug) { error_log('show result ' . $show_result); } if ($from == 'exercise_result') { if ($debug) { error_log('Showing questions $from ' . $from); } //display answers (if not matching type, or if the answer is correct) if (!in_array($answerType, [MATCHING, DRAGGABLE, MATCHING_DRAGGABLE]) || $answerCorrect) { if (in_array($answerType, array(UNIQUE_ANSWER, UNIQUE_ANSWER_IMAGE, UNIQUE_ANSWER_NO_OPTION, MULTIPLE_ANSWER, MULTIPLE_ANSWER_COMBINATION, GLOBAL_MULTIPLE_ANSWER))) { //if ($origin != 'learnpath') { ExerciseShowFunctions::display_unique_or_multiple_answer($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect, 0, 0, 0, $results_disabled); //} } elseif ($answerType == MULTIPLE_ANSWER_TRUE_FALSE) { //if ($origin!='learnpath') { ExerciseShowFunctions::display_multiple_answer_true_false($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect, 0, $questionId, 0, $results_disabled); //} } elseif ($answerType == MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE) { // if ($origin!='learnpath') { ExerciseShowFunctions::display_multiple_answer_combination_true_false($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect, 0, 0, 0, $results_disabled); //} } elseif ($answerType == FILL_IN_BLANKS) { //if ($origin!='learnpath') { ExerciseShowFunctions::display_fill_in_blanks_answer($feedback_type, $answer, 0, 0, $results_disabled); // } } elseif ($answerType == CALCULATED_ANSWER) { //if ($origin!='learnpath') { ExerciseShowFunctions::display_calculated_answer($feedback_type, $answer, 0, 0); // } } elseif ($answerType == FREE_ANSWER) { //if($origin != 'learnpath') { ExerciseShowFunctions::display_free_answer($feedback_type, $choice, $exeId, $questionId, $questionScore); //} } elseif ($answerType == ORAL_EXPRESSION) { // to store the details of open questions in an array to be used in mail //if ($origin != 'learnpath') { ExerciseShowFunctions::display_oral_expression_answer($feedback_type, $choice, 0, 0, $nano); //} } elseif ($answerType == HOT_SPOT) { //if ($origin != 'learnpath') { ExerciseShowFunctions::display_hotspot_answer($feedback_type, $answerId, $answer, $studentChoice, $answerComment, $results_disabled); // } } elseif ($answerType == HOT_SPOT_ORDER) { //if ($origin != 'learnpath') { ExerciseShowFunctions::display_hotspot_order_answer($feedback_type, $answerId, $answer, $studentChoice, $answerComment); //} } elseif ($answerType == HOT_SPOT_DELINEATION) { $user_answer = $_SESSION['exerciseResultCoordinates'][$questionId]; //round-up the coordinates $coords = explode('/', $user_answer); $user_array = ''; foreach ($coords as $coord) { list($x, $y) = explode(';', $coord); $user_array .= round($x) . ';' . round($y) . '/'; } $user_array = substr($user_array, 0, -1); if ($next) { $user_answer = $user_array; // we compare only the delineation not the other points $answer_question = $_SESSION['hotspot_coord'][1]; $answerDestination = $_SESSION['hotspot_dest'][1]; //calculating the area $poly_user = convert_coordinates($user_answer, '/'); $poly_answer = convert_coordinates($answer_question, '|'); $max_coord = poly_get_max($poly_user, $poly_answer); $poly_user_compiled = poly_compile($poly_user, $max_coord); $poly_answer_compiled = poly_compile($poly_answer, $max_coord); $poly_results = poly_result($poly_answer_compiled, $poly_user_compiled, $max_coord); $overlap = $poly_results['both']; $poly_answer_area = $poly_results['s1']; $poly_user_area = $poly_results['s2']; $missing = $poly_results['s1Only']; $excess = $poly_results['s2Only']; //$overlap = round(polygons_overlap($poly_answer,$poly_user)); // //this is an area in pixels if ($debug > 0) { error_log(__LINE__ . ' - Polygons results are ' . print_r($poly_results, 1), 0); } if ($overlap < 1) { //shortcut to avoid complicated calculations $final_overlap = 0; $final_missing = 100; $final_excess = 100; } else { // the final overlap is the percentage of the initial polygon // that is overlapped by the user's polygon $final_overlap = round((double) $overlap / (double) $poly_answer_area * 100); if ($debug > 1) { error_log(__LINE__ . ' - Final overlap is ' . $final_overlap, 0); } // the final missing area is the percentage of the initial polygon // that is not overlapped by the user's polygon $final_missing = 100 - $final_overlap; if ($debug > 1) { error_log(__LINE__ . ' - Final missing is ' . $final_missing, 0); } // the final excess area is the percentage of the initial polygon's size // that is covered by the user's polygon outside of the initial polygon $final_excess = round(((double) $poly_user_area - (double) $overlap) / (double) $poly_answer_area * 100); if ($debug > 1) { error_log(__LINE__ . ' - Final excess is ' . $final_excess, 0); } } //checking the destination parameters parsing the "@@" $destination_items = explode('@@', $answerDestination); $threadhold_total = $destination_items[0]; $threadhold_items = explode(';', $threadhold_total); $threadhold1 = $threadhold_items[0]; // overlap $threadhold2 = $threadhold_items[1]; // excess $threadhold3 = $threadhold_items[2]; //missing // if is delineation if ($answerId === 1) { //setting colors if ($final_overlap >= $threadhold1) { $overlap_color = true; //echo 'a'; } //echo $excess.'-'.$threadhold2; if ($final_excess <= $threadhold2) { $excess_color = true; //echo 'b'; } //echo '--------'.$missing.'-'.$threadhold3; if ($final_missing <= $threadhold3) { $missing_color = true; //echo 'c'; } // if pass if ($final_overlap >= $threadhold1 && $final_missing <= $threadhold3 && $final_excess <= $threadhold2) { $next = 1; //go to the oars $result_comment = get_lang('Acceptable'); $final_answer = 1; // do not update with update_exercise_attempt } else { $next = 0; $result_comment = get_lang('Unacceptable'); $comment = $answerDestination = $objAnswerTmp->selectComment(1); $answerDestination = $objAnswerTmp->selectDestination(1); //checking the destination parameters parsing the "@@" $destination_items = explode('@@', $answerDestination); } } elseif ($answerId > 1) { if ($objAnswerTmp->selectHotspotType($answerId) == 'noerror') { if ($debug > 0) { error_log(__LINE__ . ' - answerId is of type noerror', 0); } //type no error shouldn't be treated $next = 1; continue; } if ($debug > 0) { error_log(__LINE__ . ' - answerId is >1 so we\'re probably in OAR', 0); } //check the intersection between the oar and the user //echo 'user'; print_r($x_user_list); print_r($y_user_list); //echo 'official';print_r($x_list);print_r($y_list); //$result = get_intersection_data($x_list,$y_list,$x_user_list,$y_user_list); $inter = $result['success']; //$delineation_cord=$objAnswerTmp->selectHotspotCoordinates($answerId); $delineation_cord = $objAnswerTmp->selectHotspotCoordinates($answerId); $poly_answer = convert_coordinates($delineation_cord, '|'); $max_coord = poly_get_max($poly_user, $poly_answer); $poly_answer_compiled = poly_compile($poly_answer, $max_coord); $overlap = poly_touch($poly_user_compiled, $poly_answer_compiled, $max_coord); if ($overlap == false) { //all good, no overlap $next = 1; continue; } else { if ($debug > 0) { error_log(__LINE__ . ' - Overlap is ' . $overlap . ': OAR hit', 0); } $organs_at_risk_hit++; //show the feedback $next = 0; $comment = $answerDestination = $objAnswerTmp->selectComment($answerId); $answerDestination = $objAnswerTmp->selectDestination($answerId); $destination_items = explode('@@', $answerDestination); $try_hotspot = $destination_items[1]; $lp_hotspot = $destination_items[2]; $select_question_hotspot = $destination_items[3]; $url_hotspot = $destination_items[4]; } } } else { // the first delineation feedback if ($debug > 0) { error_log(__LINE__ . ' first', 0); } } } elseif (in_array($answerType, [MATCHING, MATCHING_DRAGGABLE])) { echo '<tr>'; echo Display::tag('td', $answerMatching[$answerId]); echo Display::tag('td', "{$user_answer} / " . Display::tag('strong', $answerMatching[$answerCorrect], ['style' => 'color: #008000; font-weight: bold;'])); echo '</tr>'; } } } else { if ($debug) { error_log('Showing questions $from ' . $from); } switch ($answerType) { case UNIQUE_ANSWER: case UNIQUE_ANSWER_IMAGE: case UNIQUE_ANSWER_NO_OPTION: case MULTIPLE_ANSWER: case GLOBAL_MULTIPLE_ANSWER: case MULTIPLE_ANSWER_COMBINATION: if ($answerId == 1) { ExerciseShowFunctions::display_unique_or_multiple_answer($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect, $exeId, $questionId, $answerId, $results_disabled); } else { ExerciseShowFunctions::display_unique_or_multiple_answer($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect, $exeId, $questionId, "", $results_disabled); } break; case MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE: if ($answerId == 1) { ExerciseShowFunctions::display_multiple_answer_combination_true_false($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect, $exeId, $questionId, $answerId, $results_disabled); } else { ExerciseShowFunctions::display_multiple_answer_combination_true_false($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect, $exeId, $questionId, "", $results_disabled); } break; case MULTIPLE_ANSWER_TRUE_FALSE: if ($answerId == 1) { ExerciseShowFunctions::display_multiple_answer_true_false($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect, $exeId, $questionId, $answerId, $results_disabled); } else { ExerciseShowFunctions::display_multiple_answer_true_false($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect, $exeId, $questionId, "", $results_disabled); } break; case FILL_IN_BLANKS: ExerciseShowFunctions::display_fill_in_blanks_answer($feedback_type, $answer, $exeId, $questionId, $results_disabled, $str); break; case CALCULATED_ANSWER: ExerciseShowFunctions::display_calculated_answer($feedback_type, $answer, $exeId, $questionId); break; case FREE_ANSWER: echo ExerciseShowFunctions::display_free_answer($feedback_type, $choice, $exeId, $questionId, $questionScore); break; case ORAL_EXPRESSION: echo '<tr> <td valign="top">' . ExerciseShowFunctions::display_oral_expression_answer($feedback_type, $choice, $exeId, $questionId, $nano) . '</td> </tr> </table>'; break; case HOT_SPOT: ExerciseShowFunctions::display_hotspot_answer($feedback_type, $answerId, $answer, $studentChoice, $answerComment, $results_disabled); break; case HOT_SPOT_DELINEATION: $user_answer = $user_array; if ($next) { //$tbl_track_e_hotspot = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT); // Save into db /* $sql = "INSERT INTO $tbl_track_e_hotspot ( * hotspot_user_id, * hotspot_course_code, * hotspot_exe_id, * hotspot_question_id, * hotspot_answer_id, * hotspot_correct, * hotspot_coordinate * ) VALUES ( * '".Database::escape_string($_user['user_id'])."', * '".Database::escape_string($_course['id'])."', * '".Database::escape_string($exeId)."', '".Database::escape_string($questionId)."', * '".Database::escape_string($answerId)."', * '".Database::escape_string($studentChoice)."', * '".Database::escape_string($user_array)."')"; $result = Database::query($sql,__FILE__,__LINE__); */ $user_answer = $user_array; // we compare only the delineation not the other points $answer_question = $_SESSION['hotspot_coord'][1]; $answerDestination = $_SESSION['hotspot_dest'][1]; //calculating the area $poly_user = convert_coordinates($user_answer, '/'); $poly_answer = convert_coordinates($answer_question, '|'); $max_coord = poly_get_max($poly_user, $poly_answer); $poly_user_compiled = poly_compile($poly_user, $max_coord); $poly_answer_compiled = poly_compile($poly_answer, $max_coord); $poly_results = poly_result($poly_answer_compiled, $poly_user_compiled, $max_coord); $overlap = $poly_results['both']; $poly_answer_area = $poly_results['s1']; $poly_user_area = $poly_results['s2']; $missing = $poly_results['s1Only']; $excess = $poly_results['s2Only']; //$overlap = round(polygons_overlap($poly_answer,$poly_user)); //this is an area in pixels if ($debug > 0) { error_log(__LINE__ . ' - Polygons results are ' . print_r($poly_results, 1), 0); } if ($overlap < 1) { //shortcut to avoid complicated calculations $final_overlap = 0; $final_missing = 100; $final_excess = 100; } else { // the final overlap is the percentage of the initial polygon that is overlapped by the user's polygon $final_overlap = round((double) $overlap / (double) $poly_answer_area * 100); if ($debug > 1) { error_log(__LINE__ . ' - Final overlap is ' . $final_overlap, 0); } // the final missing area is the percentage of the initial polygon that is not overlapped by the user's polygon $final_missing = 100 - $final_overlap; if ($debug > 1) { error_log(__LINE__ . ' - Final missing is ' . $final_missing, 0); } // the final excess area is the percentage of the initial polygon's size that is covered by the user's polygon outside of the initial polygon $final_excess = round(((double) $poly_user_area - (double) $overlap) / (double) $poly_answer_area * 100); if ($debug > 1) { error_log(__LINE__ . ' - Final excess is ' . $final_excess, 0); } } //checking the destination parameters parsing the "@@" $destination_items = explode('@@', $answerDestination); $threadhold_total = $destination_items[0]; $threadhold_items = explode(';', $threadhold_total); $threadhold1 = $threadhold_items[0]; // overlap $threadhold2 = $threadhold_items[1]; // excess $threadhold3 = $threadhold_items[2]; //missing // if is delineation if ($answerId === 1) { //setting colors if ($final_overlap >= $threadhold1) { $overlap_color = true; //echo 'a'; } //echo $excess.'-'.$threadhold2; if ($final_excess <= $threadhold2) { $excess_color = true; //echo 'b'; } //echo '--------'.$missing.'-'.$threadhold3; if ($final_missing <= $threadhold3) { $missing_color = true; //echo 'c'; } // if pass if ($final_overlap >= $threadhold1 && $final_missing <= $threadhold3 && $final_excess <= $threadhold2) { $next = 1; //go to the oars $result_comment = get_lang('Acceptable'); $final_answer = 1; // do not update with update_exercise_attempt } else { $next = 0; $result_comment = get_lang('Unacceptable'); $comment = $answerDestination = $objAnswerTmp->selectComment(1); $answerDestination = $objAnswerTmp->selectDestination(1); //checking the destination parameters parsing the "@@" $destination_items = explode('@@', $answerDestination); } } elseif ($answerId > 1) { if ($objAnswerTmp->selectHotspotType($answerId) == 'noerror') { if ($debug > 0) { error_log(__LINE__ . ' - answerId is of type noerror', 0); } //type no error shouldn't be treated $next = 1; continue; } if ($debug > 0) { error_log(__LINE__ . ' - answerId is >1 so we\'re probably in OAR', 0); } //check the intersection between the oar and the user //echo 'user'; print_r($x_user_list); print_r($y_user_list); //echo 'official';print_r($x_list);print_r($y_list); //$result = get_intersection_data($x_list,$y_list,$x_user_list,$y_user_list); $inter = $result['success']; //$delineation_cord=$objAnswerTmp->selectHotspotCoordinates($answerId); $delineation_cord = $objAnswerTmp->selectHotspotCoordinates($answerId); $poly_answer = convert_coordinates($delineation_cord, '|'); $max_coord = poly_get_max($poly_user, $poly_answer); $poly_answer_compiled = poly_compile($poly_answer, $max_coord); $overlap = poly_touch($poly_user_compiled, $poly_answer_compiled, $max_coord); if ($overlap == false) { //all good, no overlap $next = 1; continue; } else { if ($debug > 0) { error_log(__LINE__ . ' - Overlap is ' . $overlap . ': OAR hit', 0); } $organs_at_risk_hit++; //show the feedback $next = 0; $comment = $answerDestination = $objAnswerTmp->selectComment($answerId); $answerDestination = $objAnswerTmp->selectDestination($answerId); $destination_items = explode('@@', $answerDestination); $try_hotspot = $destination_items[1]; $lp_hotspot = $destination_items[2]; $select_question_hotspot = $destination_items[3]; $url_hotspot = $destination_items[4]; } } } else { // the first delineation feedback if ($debug > 0) { error_log(__LINE__ . ' first', 0); } } break; case HOT_SPOT_ORDER: ExerciseShowFunctions::display_hotspot_order_answer($feedback_type, $answerId, $answer, $studentChoice, $answerComment); break; case DRAGGABLE: //no break //no break case MATCHING_DRAGGABLE: //no break //no break case MATCHING: echo '<tr>'; echo Display::tag('td', $answerMatching[$answerId]); echo Display::tag('td', "{$user_answer} / " . Display::tag('strong', $answerMatching[$answerCorrect], ['style' => 'color: #008000; font-weight: bold;'])); echo '</tr>'; break; } } } if ($debug) { error_log(' ------ '); } } // end for that loops over all answers of the current question if ($debug) { error_log('-- end answer loop --'); } $final_answer = true; foreach ($real_answers as $my_answer) { if (!$my_answer) { $final_answer = false; } } //we add the total score after dealing with the answers if ($answerType == MULTIPLE_ANSWER_COMBINATION || $answerType == MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE) { if ($final_answer) { //getting only the first score where we save the weight of all the question $answerWeighting = $objAnswerTmp->selectWeighting(1); $questionScore += $answerWeighting; $totalScore += $answerWeighting; } } //Fixes multiple answer question in order to be exact //if ($answerType == MULTIPLE_ANSWER || $answerType == GLOBAL_MULTIPLE_ANSWER) { /* if ($answerType == GLOBAL_MULTIPLE_ANSWER) { $diff = @array_diff($answer_correct_array, $real_answers); // All good answers or nothing works like exact $counter = 1; $correct_answer = true; foreach ($real_answers as $my_answer) { if ($debug) error_log(" my_answer: $my_answer answer_correct_array[counter]: ".$answer_correct_array[$counter]); if ($my_answer != $answer_correct_array[$counter]) { $correct_answer = false; break; } $counter++; } if ($debug) error_log(" answer_correct_array: ".print_r($answer_correct_array, 1).""); if ($debug) error_log(" real_answers: ".print_r($real_answers, 1).""); if ($debug) error_log(" correct_answer: ".$correct_answer); if ($correct_answer == false) { $questionScore = 0; } // This makes the result non exact if (!empty($diff)) { $questionScore = 0; } }*/ $extra_data = array('final_overlap' => $final_overlap, 'final_missing' => $final_missing, 'final_excess' => $final_excess, 'overlap_color' => $overlap_color, 'missing_color' => $missing_color, 'excess_color' => $excess_color, 'threadhold1' => $threadhold1, 'threadhold2' => $threadhold2, 'threadhold3' => $threadhold3); if ($from == 'exercise_result') { // if answer is hotspot. To the difference of exercise_show.php, // we use the results from the session (from_db=0) // TODO Change this, because it is wrong to show the user // some results that haven't been stored in the database yet if ($answerType == HOT_SPOT || $answerType == HOT_SPOT_ORDER || $answerType == HOT_SPOT_DELINEATION) { if ($debug) { error_log('$from AND this is a hotspot kind of question '); } $my_exe_id = 0; $from_database = 0; if ($answerType == HOT_SPOT_DELINEATION) { if (0) { if ($overlap_color) { $overlap_color = 'green'; } else { $overlap_color = 'red'; } if ($missing_color) { $missing_color = 'green'; } else { $missing_color = 'red'; } if ($excess_color) { $excess_color = 'green'; } else { $excess_color = 'red'; } if (!is_numeric($final_overlap)) { $final_overlap = 0; } if (!is_numeric($final_missing)) { $final_missing = 0; } if (!is_numeric($final_excess)) { $final_excess = 0; } if ($final_overlap > 100) { $final_overlap = 100; } $table_resume = '<table class="data_table"> <tr class="row_odd" > <td></td> <td ><b>' . get_lang('Requirements') . '</b></td> <td><b>' . get_lang('YourAnswer') . '</b></td> </tr> <tr class="row_even"> <td><b>' . get_lang('Overlap') . '</b></td> <td>' . get_lang('Min') . ' ' . $threadhold1 . '</td> <td><div style="color:' . $overlap_color . '">' . ($final_overlap < 0 ? 0 : intval($final_overlap)) . '</div></td> </tr> <tr> <td><b>' . get_lang('Excess') . '</b></td> <td>' . get_lang('Max') . ' ' . $threadhold2 . '</td> <td><div style="color:' . $excess_color . '">' . ($final_excess < 0 ? 0 : intval($final_excess)) . '</div></td> </tr> <tr class="row_even"> <td><b>' . get_lang('Missing') . '</b></td> <td>' . get_lang('Max') . ' ' . $threadhold3 . '</td> <td><div style="color:' . $missing_color . '">' . ($final_missing < 0 ? 0 : intval($final_missing)) . '</div></td> </tr> </table>'; if ($next == 0) { $try = $try_hotspot; $lp = $lp_hotspot; $destinationid = $select_question_hotspot; $url = $url_hotspot; } else { //show if no error //echo 'no error'; $comment = $answerComment = $objAnswerTmp->selectComment($nbrAnswers); $answerDestination = $objAnswerTmp->selectDestination($nbrAnswers); } echo '<h1><div style="color:#333;">' . get_lang('Feedback') . '</div></h1> <p style="text-align:center">'; $message = '<p>' . get_lang('YourDelineation') . '</p>'; $message .= $table_resume; $message .= '<br />' . get_lang('ResultIs') . ' ' . $result_comment . '<br />'; if ($organs_at_risk_hit > 0) { $message .= '<p><b>' . get_lang('OARHit') . '</b></p>'; } $message .= '<p>' . $comment . '</p>'; echo $message; } else { echo $hotspot_delineation_result[0]; //prints message $from_database = 1; // the hotspot_solution.swf needs this variable } //save the score attempts if (1) { //getting the answer 1 or 0 comes from exercise_submit_modal.php $final_answer = $hotspot_delineation_result[1]; if ($final_answer == 0) { $questionScore = 0; } // we always insert the answer_id 1 = delineation Event::saveQuestionAttempt($questionScore, 1, $quesId, $exeId, 0); //in delineation mode, get the answer from $hotspot_delineation_result[1] Event::saveExerciseAttemptHotspot($exeId, $quesId, 1, $hotspot_delineation_result[1], $exerciseResultCoordinates[$quesId]); } else { if ($final_answer == 0) { $questionScore = 0; $answer = 0; Event::saveQuestionAttempt($questionScore, $answer, $quesId, $exeId, 0); if (is_array($exerciseResultCoordinates[$quesId])) { foreach ($exerciseResultCoordinates[$quesId] as $idx => $val) { Event::saveExerciseAttemptHotspot($exeId, $quesId, $idx, 0, $val); } } } else { Event::saveQuestionAttempt($questionScore, $answer, $quesId, $exeId, 0); if (is_array($exerciseResultCoordinates[$quesId])) { foreach ($exerciseResultCoordinates[$quesId] as $idx => $val) { Event::saveExerciseAttemptHotspot($exeId, $quesId, $idx, $choice[$idx], $val); } } } } $my_exe_id = $exeId; } } if ($answerType == HOT_SPOT || $answerType == HOT_SPOT_ORDER) { // We made an extra table for the answers if ($show_result) { // if ($origin != 'learnpath') { echo '</table></td></tr>'; echo "\n <tr>\n <td colspan=\"2\">\n <p><em>" . get_lang('HotSpot') . "</em></p>\n <div id=\"hotspot-solution-{$questionId}\"></div>\n\n <script>\n \$(document).on('ready', function () {\n new HotspotQuestion({\n questionId: {$questionId},\n exerciseId: {$exeId},\n selector: '#hotspot-solution-{$questionId}',\n for: 'solution'\n });\n });\n </script>\n </td>\n </tr>\n "; // } } } //if ($origin != 'learnpath') { if ($show_result) { echo '</table>'; } // } } unset($objAnswerTmp); $totalWeighting += $questionWeighting; // Store results directly in the database // For all in one page exercises, the results will be // stored by exercise_results.php (using the session) if ($saved_results) { if ($debug) { error_log("Save question results {$saved_results}"); } if ($debug) { error_log(print_r($choice, 1)); } if (empty($choice)) { $choice = 0; } if ($answerType == MULTIPLE_ANSWER_TRUE_FALSE || $answerType == MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE) { if ($choice != 0) { $reply = array_keys($choice); for ($i = 0; $i < sizeof($reply); $i++) { $ans = $reply[$i]; Event::saveQuestionAttempt($questionScore, $ans . ':' . $choice[$ans], $quesId, $exeId, $i, $this->id); if ($debug) { error_log('result =>' . $questionScore . ' ' . $ans . ':' . $choice[$ans]); } } } else { Event::saveQuestionAttempt($questionScore, 0, $quesId, $exeId, 0, $this->id); } } elseif ($answerType == MULTIPLE_ANSWER || $answerType == GLOBAL_MULTIPLE_ANSWER) { if ($choice != 0) { $reply = array_keys($choice); if ($debug) { error_log("reply " . print_r($reply, 1) . ""); } for ($i = 0; $i < sizeof($reply); $i++) { $ans = $reply[$i]; Event::saveQuestionAttempt($questionScore, $ans, $quesId, $exeId, $i, $this->id); } } else { Event::saveQuestionAttempt($questionScore, 0, $quesId, $exeId, 0, $this->id); } } elseif ($answerType == MULTIPLE_ANSWER_COMBINATION) { if ($choice != 0) { $reply = array_keys($choice); for ($i = 0; $i < sizeof($reply); $i++) { $ans = $reply[$i]; Event::saveQuestionAttempt($questionScore, $ans, $quesId, $exeId, $i, $this->id); } } else { Event::saveQuestionAttempt($questionScore, 0, $quesId, $exeId, 0, $this->id); } } elseif (in_array($answerType, [MATCHING, DRAGGABLE, MATCHING_DRAGGABLE])) { if (isset($matching)) { foreach ($matching as $j => $val) { Event::saveQuestionAttempt($questionScore, $val, $quesId, $exeId, $j, $this->id); } } } elseif ($answerType == FREE_ANSWER) { $answer = $choice; Event::saveQuestionAttempt($questionScore, $answer, $quesId, $exeId, 0, $this->id); } elseif ($answerType == ORAL_EXPRESSION) { $answer = $choice; Event::saveQuestionAttempt($questionScore, $answer, $quesId, $exeId, 0, $this->id, $nano); } elseif (in_array($answerType, [UNIQUE_ANSWER, UNIQUE_ANSWER_IMAGE, UNIQUE_ANSWER_NO_OPTION])) { $answer = $choice; Event::saveQuestionAttempt($questionScore, $answer, $quesId, $exeId, 0, $this->id); // } elseif ($answerType == HOT_SPOT || $answerType == HOT_SPOT_DELINEATION) { } elseif ($answerType == HOT_SPOT) { $answer = []; if (isset($exerciseResultCoordinates[$questionId]) && !empty($exerciseResultCoordinates[$questionId])) { Database::delete(Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT), ['hotspot_exe_id = ? AND hotspot_question_id = ? AND c_id = ?' => [$exeId, $questionId, api_get_course_int_id()]]); foreach ($exerciseResultCoordinates[$questionId] as $idx => $val) { $answer[] = $val; Event::saveExerciseAttemptHotspot($exeId, $quesId, $idx, $choice[$idx], $val, false, $this->id); } } Event::saveQuestionAttempt($questionScore, implode('|', $answer), $quesId, $exeId, 0, $this->id); } else { Event::saveQuestionAttempt($questionScore, $answer, $quesId, $exeId, 0, $this->id); } } if ($propagate_neg == 0 && $questionScore < 0) { $questionScore = 0; } if ($saved_results) { $stat_table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES); $sql = 'UPDATE ' . $stat_table . ' SET exe_result = exe_result + ' . floatval($questionScore) . ' WHERE exe_id = ' . $exeId; if ($debug) { error_log($sql); } Database::query($sql); } $return_array = array('score' => $questionScore, 'weight' => $questionWeighting, 'extra' => $extra_data, 'open_question' => $arrques, 'open_answer' => $arrans, 'answer_type' => $answerType); return $return_array; }
if (!empty($exercise_stat_info)) { $total_score = $exercise_stat_info['exe_result']; } $max_score = $objExercise->get_max_score(); Display::display_normal_message(get_lang('Saved') . '<br />', false); // Display and save questions ExerciseLib::display_question_list_by_attempt($objExercise, $exe_id, true); //Unset session for clock time ExerciseLib::exercise_time_control_delete($objExercise->id, $learnpath_id, $learnpath_item_id); ExerciseLib::delete_chat_exercise_session($exe_id); if ($origin != 'learnpath') { echo '<hr>'; echo Display::url(get_lang('ReturnToCourseHomepage'), api_get_course_url(), array('class' => 'btn btn-primary')); if (api_is_allowed_to_session_edit()) { Session::erase('objExercise'); Session::erase('exe_id'); } Display::display_footer(); } else { $lp_mode = Session::read('lp_mode'); $url = '../newscorm/lp_controller.php?cidReq=' . api_get_course_id() . '&action=view&lp_id=' . $learnpath_id . '&lp_item_id=' . $learnpath_item_id . '&exeId=' . $exercise_stat_info['exe_id'] . '&fb_type=' . $objExercise->feedback_type; $href = $lp_mode == 'fullscreen' ? ' window.opener.location.href="' . $url . '" ' : ' top.location.href="' . $url . '"'; if (api_is_allowed_to_session_edit()) { Session::erase('objExercise'); Session::erase('exe_id'); } // Record the results in the learning path, using the SCORM interface (API) echo "<script>window.parent.API.void_save_asset('{$total_score}', '{$max_score}', 0, 'completed');</script>"; echo '<script type="text/javascript">' . $href . '</script>'; echo '</body></html>'; }
/** * Returns the form to update or create a document * @param string Action (add/edit) * @param integer ID of the lp_item (if already exists) * @param mixed Integer if document ID, string if info ('new') * @return string HTML form */ public function display_document_form($action = 'add', $id = 0, $extra_info = 'new') { $course_id = api_get_course_int_id(); $tbl_lp_item = Database::get_course_table(TABLE_LP_ITEM); $tbl_doc = Database::get_course_table(TABLE_DOCUMENT); $no_display_edit_textarea = false; //If action==edit document //We don't display the document form if it's not an editable document (html or txt file) if ($action == "edit") { if (is_array($extra_info)) { $path_parts = pathinfo($extra_info['dir']); if ($path_parts['extension'] != "txt" && $path_parts['extension'] != "html") { $no_display_edit_textarea = true; } } } $no_display_add = false; // If action==add an existing document // We don't display the document form if it's not an editable document (html or txt file). if ($action == "add") { if (is_numeric($extra_info)) { $sql_doc = "SELECT path FROM " . $tbl_doc . " WHERE c_id = " . $course_id . " AND id = " . Database::escape_string($extra_info); $result = Database::query($sql_doc); $path_file = Database::result($result, 0, 0); $path_parts = pathinfo($path_file); if ($path_parts['extension'] != "txt" && $path_parts['extension'] != "html") { $no_display_add = true; } } } if ($id != 0 && is_array($extra_info)) { $item_title = stripslashes($extra_info['title']); $item_description = stripslashes($extra_info['description']); $item_terms = stripslashes($extra_info['terms']); if (empty($item_title)) { $path_parts = pathinfo($extra_info['path']); $item_title = stripslashes($path_parts['filename']); } } elseif (is_numeric($extra_info)) { $sql_doc = "SELECT path, title FROM " . $tbl_doc . "\n WHERE c_id = " . $course_id . " AND id = " . Database::escape_string($extra_info); $result = Database::query($sql_doc); $row = Database::fetch_array($result); $explode = explode('.', $row['title']); if (count($explode) > 1) { for ($i = 0; $i < count($explode) - 1; $i++) { $item_title .= $explode[$i]; } } else { $item_title = $row['title']; } $item_title = str_replace('_', ' ', $item_title); if (empty($item_title)) { $path_parts = pathinfo($row['path']); $item_title = stripslashes($path_parts['filename']); } } else { $item_title = ''; $item_description = ''; } $return = '<legend>'; if ($id != 0 && is_array($extra_info)) { $parent = $extra_info['parent_item_id']; } else { $parent = 0; } $sql = "SELECT * FROM " . $tbl_lp_item . "\n WHERE c_id = " . $course_id . " AND lp_id = " . $this->lp_id; $result = Database::query($sql); $arrLP = array(); while ($row = Database::fetch_array($result)) { $arrLP[] = array('id' => $row['id'], 'item_type' => $row['item_type'], 'title' => $row['title'], 'path' => $row['path'], 'description' => $row['description'], 'parent_item_id' => $row['parent_item_id'], 'previous_item_id' => $row['previous_item_id'], 'next_item_id' => $row['next_item_id'], 'display_order' => $row['display_order'], 'max_score' => $row['max_score'], 'min_score' => $row['min_score'], 'mastery_score' => $row['mastery_score'], 'prerequisite' => $row['prerequisite']); } $this->tree_array($arrLP); $arrLP = null; if (isset($this->arrMenu)) { $arrLP = $this->arrMenu; unset($this->arrMenu); } if ($action == 'add') { $return .= get_lang('CreateTheDocument'); } elseif ($action == 'move') { $return .= get_lang('MoveTheCurrentDocument'); } else { $return .= get_lang('EditTheCurrentDocument'); } $return .= '</legend>'; if (isset($_GET['edit']) && $_GET['edit'] == 'true') { $return .= Display::return_warning_message('<strong>' . get_lang('Warning') . ' !</strong><br />' . get_lang('WarningEditingDocument'), false); } $form = new FormValidator('form', 'POST', api_get_self() . '?' . $_SERVER['QUERY_STRING'], '', array('enctype' => "multipart/form-data")); $defaults['title'] = Security::remove_XSS($item_title); if (empty($item_title)) { $defaults['title'] = Security::remove_XSS($item_title); } $defaults['description'] = $item_description; $form->addElement('html', $return); if ($action != 'move') { $form->addElement('text', 'title', get_lang('Title'), array('id' => 'idTitle', 'class' => 'span4')); $form->applyFilter('title', 'html_filter'); } //$arrHide = array($id); $arrHide[0]['value'] = $this->name; $arrHide[0]['padding'] = 3; for ($i = 0; $i < count($arrLP); $i++) { if ($action != 'add') { if (($arrLP[$i]['item_type'] == 'dokeos_module' || $arrLP[$i]['item_type'] == 'dokeos_chapter' || $arrLP[$i]['item_type'] == 'dir') && !in_array($arrLP[$i]['id'], $arrHide) && !in_array($arrLP[$i]['parent_item_id'], $arrHide)) { $arrHide[$arrLP[$i]['id']]['value'] = $arrLP[$i]['title']; $arrHide[$arrLP[$i]['id']]['padding'] = 3 + $arrLP[$i]['depth'] * 10; if ($parent == $arrLP[$i]['id']) { $s_selected_parent = $arrHide[$arrLP[$i]['id']]; } } } else { if ($arrLP[$i]['item_type'] == 'dokeos_module' || $arrLP[$i]['item_type'] == 'dokeos_chapter' || $arrLP[$i]['item_type'] == 'dir') { $arrHide[$arrLP[$i]['id']]['value'] = $arrLP[$i]['title']; $arrHide[$arrLP[$i]['id']]['padding'] = 3 + $arrLP[$i]['depth'] * 10; if ($parent == $arrLP[$i]['id']) { $s_selected_parent = $arrHide[$arrLP[$i]['id']]; } } } } $parent_select = $form->addElement('select', 'parent', get_lang('Parent'), '', 'class="learnpath_item_form" id="idParent" style="width:40%;" onchange="javascript: load_cbo(this.value);"'); $my_count = 0; foreach ($arrHide as $key => $value) { if ($my_count != 0) { // The LP name is also the first section and is not in the same charset like the other sections. $value['value'] = Security::remove_XSS($value['value']); $parent_select->addOption($value['value'], $key, 'style="padding-left:' . $value['padding'] . 'px;"'); } else { $value['value'] = Security::remove_XSS($value['value']); $parent_select->addOption($value['value'], $key, 'style="padding-left:' . $value['padding'] . 'px;"'); } $my_count++; } if (!empty($id)) { $parent_select->setSelected($parent); } else { $parent_item_id = Session::read('parent_item_id'); $parent_select->setSelected($parent_item_id); } if (is_array($arrLP)) { reset($arrLP); } $arrHide = array(); $s_selected_position = null; //POSITION for ($i = 0; $i < count($arrLP); $i++) { if ($arrLP[$i]['parent_item_id'] == $parent && $arrLP[$i]['id'] != $id) { if (isset($extra_info['previous_item_id']) && $extra_info['previous_item_id'] == $arrLP[$i]['id']) { $s_selected_position = $arrLP[$i]['id']; } elseif ($action == 'add') { $s_selected_position = $arrLP[$i]['id']; } $arrHide[$arrLP[$i]['id']]['value'] = get_lang('After') . ' "' . $arrLP[$i]['title'] . '"'; } } $position = $form->addElement('select', 'previous', get_lang('Position'), '', 'id="previous" class="learnpath_item_form" style="width:40%;"'); $position->addOption(get_lang('FirstPosition'), 0); foreach ($arrHide as $key => $value) { $padding = isset($value['padding']) ? $value['padding'] : 0; $position->addOption($value['value'], $key, 'style="padding-left:' . $padding . 'px;"'); } $position->setSelected($s_selected_position); if (is_array($arrLP)) { reset($arrLP); } if ($action != 'move') { $id_prerequisite = 0; if (is_array($arrLP)) { foreach ($arrLP as $key => $value) { if ($value['id'] == $id) { $id_prerequisite = $value['prerequisite']; break; } } } $arrHide = array(); for ($i = 0; $i < count($arrLP); $i++) { if ($arrLP[$i]['id'] != $id && $arrLP[$i]['item_type'] != 'dokeos_chapter') { if (isset($extra_info['previous_item_id']) && $extra_info['previous_item_id'] == $arrLP[$i]['id']) { $s_selected_position = $arrLP[$i]['id']; } elseif ($action == 'add') { $s_selected_position = $arrLP[$i]['id']; } $arrHide[$arrLP[$i]['id']]['value'] = $arrLP[$i]['title']; } } if (!$no_display_add) { if ($extra_info == 'new' || $extra_info['item_type'] == TOOL_DOCUMENT || $_GET['edit'] == 'true') { if (isset($_POST['content'])) { $content = stripslashes($_POST['content']); } elseif (is_array($extra_info)) { //If it's an html document or a text file if (!$no_display_edit_textarea) { $content = $this->display_document($extra_info['path'], false, false); } } elseif (is_numeric($extra_info)) { $content = $this->display_document($extra_info, false, false); } else { $content = ''; } if (!$no_display_edit_textarea) { // We need to calculate here some specific settings for the online editor. // The calculated settings work for documents in the Documents tool // (on the root or in subfolders). // For documents in native scorm packages it is unclear whether the // online editor should be activated or not. // A new document, it is in the root of the repository. $relative_path = ''; $relative_prefix = ''; if (is_array($extra_info) && $extra_info != 'new') { // The document already exists. Whe have to determine its relative path towards the repository root. $relative_path = explode('/', $extra_info['dir']); $cnt = count($relative_path) - 2; if ($cnt < 0) { $cnt = 0; } $relative_prefix = str_repeat('../', $cnt); $relative_path = array_slice($relative_path, 1, $cnt); $relative_path = implode('/', $relative_path); if (strlen($relative_path) > 0) { $relative_path = $relative_path . '/'; } } else { $_course = api_get_course_info(); $result = $this->generate_lp_folder($_course); $relative_path = api_substr($result['dir'], 1, strlen($result['dir'])); $relative_prefix = '../../'; } $editor_config = array('ToolbarSet' => 'LearningPathDocuments', 'Width' => '100%', 'Height' => '500', 'FullPage' => true, 'CreateDocumentDir' => $relative_prefix, 'CreateDocumentWebDir' => api_get_path(WEB_COURSE_PATH) . api_get_course_path() . '/document/', 'BaseHref' => api_get_path(WEB_COURSE_PATH) . api_get_course_path() . '/document/' . $relative_path); if ($_GET['action'] == 'add_item') { $class = 'add'; $text = get_lang('LPCreateDocument'); } else { if ($_GET['action'] == 'edit_item') { $class = 'save'; $text = get_lang('SaveDocument'); } } $form->addElement('style_submit_button', 'submit_button', $text, 'class="' . $class . '"'); $renderer = $form->defaultRenderer(); $renderer->setElementTemplate('<br /> {label}<br />{element}', 'content_lp'); $form->addElement('html', '<div>'); $form->addElement('html_editor', 'content_lp', '', null, $editor_config); $form->addElement('html', '</div>'); $defaults['content_lp'] = $content; } } elseif (is_numeric($extra_info)) { $form->addElement('style_submit_button', 'submit_button', get_lang('SaveDocument'), 'class="save"'); $return = $this->display_document($extra_info, true, true, true); $form->addElement('html', $return); } } } if ($action == 'move') { $form->addElement('hidden', 'title', $item_title); $form->addElement('hidden', 'description', $item_description); } if (is_numeric($extra_info)) { $form->addElement('style_submit_button', 'submit_button', get_lang('SaveDocument'), 'value="submit_button", class="save"'); $form->addElement('hidden', 'path', $extra_info); } elseif (is_array($extra_info)) { $form->addElement('style_submit_button', 'submit_button', get_lang('SaveDocument'), 'class="save"'); $form->addElement('hidden', 'path', $extra_info['path']); } $form->addElement('hidden', 'type', TOOL_DOCUMENT); $form->addElement('hidden', 'post_time', time()); $form->setDefaults($defaults); return $form->return_form(); }