'admin_quiz', 'type' => '_quiz_results', 'member_id' => $member_id], get_module_zone('admin_quiz')), 'menu/cms/quiz/quiz_results']; } return $modules; } /** * Get sections to inject to about tab of the member profile. * * @param MEMBER $member_id The ID of the member we are getting sections for * @return array List of sections. Each tuple is Tempcode. */ public function get_sections(int $member_id) : array { if (!addon_installed('quizzes')) { return []; } if (($member_id != get_member()) && (!has_privilege(get_member(), 'view_others_quiz_results'))) { return []; } require_css('quizzes'); require_lang('quiz'); require_code('quiz'); // Sorting $order = get_param_string('sort_quiz_results', 'q_time DESC', INPUT_FILTER_GET_COMPLEX); $_selectors = [ 'q_name ASC' => 'ALPHABETICAL_FORWARD', 'q_name DESC' => 'ALPHABETICAL_BACKWARD', 'q_time ASC' => 'OLDEST_RESULTS_FIRST', 'q_time DESC' => 'NEWEST_RESULTS_FIRST', ]; if (!array_key_exists($order, $_selectors)) { log_hack_attack_and_exit('ORDERBY_HACK'); warn_exit(do_lang_tempcode('INTERNAL_ERROR', escape_html('5c716d5eea045f50bbccc91e08ed945f'))); } $selectors = new Tempcode(); foreach ($_selectors as $selector_value => $selector_name) { $selected = ($order == $selector_value); $selectors->attach(do_template('PAGINATION_SORTER', ['_GUID' => '87b66fd533e5b2b185b00ed97c1d4c6b', 'SELECTED' => $selected, 'NAME' => do_lang_tempcode($selector_name), 'VALUE' => $selector_value])); } $sort_url = get_self_url(false, false, ['sort_quiz_results' => null]); $sorting = do_template('PAGINATION_SORT', ['_GUID' => '80b6bfaaf33fe0f455d57e9d940abf96', 'SORT' => 'sort_quiz_results', 'URL' => $sort_url, 'SELECTORS' => $selectors]); if ($order == 'q_name ASC' || $order == 'q_name DESC') { $order = str_replace('q_name', $GLOBALS['SITE_DB']->translate_field_ref('q_name'), $order); } $entries = $GLOBALS['SITE_DB']->query_select( 'quiz_entries e JOIN ' . get_table_prefix() . 'quizzes q ON q.id=e.q_quiz_id', ['e.id AS e_id', 'e.q_time', 'q.*'], ['q_member' => $member_id, 'q_type' => 'TEST', 'q_validated' => 1], 'ORDER BY ' . $order, null, 0, false, ['q_name' => 'SHORT_TRANS'] ); //$_has_points = $GLOBALS['SITE_DB']->query_select_value('quizzes', 'SUM(q_points_for_passing)', ['q_type' => 'TEST', 'q_validated' => 1]); $has_points = (@intval($_has_points) > 0); $categories = []; foreach ($entries as $entry) { list( $marks, $potential_extra_marks, $out_of, , , , , , , $marks_range, $percentage_range, , , , , , $passed, ) = score_quiz($entry['e_id'], $entry['id'], $entry); $quiz_name = get_translated_text($entry['q_name']); if (strpos($quiz_name, ': ') !== false) { list($category_title, $quiz_name) = explode(': ', $quiz_name, 2); } else { $category_title = do_lang('OTHER'); } if (isset($categories[$category_title]['QUIZZES'][$entry['id']])) { continue; } if (!isset($categories[$category_title])) { $categories[$category_title] = [ 'QUIZZES' => [], 'RUNNING_MARKS' => 0.0, 'RUNNING_OUT_OF' => 0, 'RUNNING_PERCENTAGE' => 0.0, // These are not in the template by default. It is used if you are fudging the q_points_for_passing as a credit for full passing of the test. // That's not very normal, but works for people who need more complex course-wide score reporting. 'RUNNING_MARKS__CREDIT' => 0.0, 'RUNNING_OUT_OF__CREDIT' => 0, 'RUNNING_PERCENTAGE__CREDIT' => 0.0, ]; } /*if (!$has_points) { $entry['q_points_for_passing']=$out_of; }*/ $just_entry_row = db_map_restrict(['id' => $entry['e_id']] + $entry, ['id', 'q_start_text']); $categories[$category_title]['QUIZZES'][$entry['id']] = [ 'QUIZ_NAME' => $quiz_name, 'QUIZ_START_TEXT' => get_translated_tempcode('quizzes', $just_entry_row, 'q_start_text'), 'QUIZ_ID' => strval($entry['id']), 'QUIZ_URL' => build_url(['page' => 'quiz', 'type' => 'do', 'id' => $entry['id']], get_module_zone('quiz')), 'ENTRY_ID' => strval($entry['e_id']), 'ENTRY_DATE' => get_timezoned_date($entry['q_time']), '_ENTRY_DATE' => strval($entry['q_time']), 'OUT_OF' => strval($out_of), 'MARKS_RANGE' => $marks_range, 'PERCENTAGE_RANGE' => $percentage_range, 'PASSED' => $passed, 'POINTS' => strval($entry['q_points_for_passing']), ]; $categories[$category_title]['RUNNING_MARKS'] += $marks; $categories[$category_title]['RUNNING_OUT_OF'] += $out_of - $potential_extra_marks; /*manually marking discounted to limit us to certainties*/ $adjusted_out_of = $out_of - $potential_extra_marks; if ($adjusted_out_of == 0) { $adjusted_out_of = 1; } $categories[$category_title]['RUNNING_MARKS__CREDIT'] += floatval($entry['q_points_for_passing']) * $marks / floatval($adjusted_out_of); $categories[$category_title]['RUNNING_OUT_OF__CREDIT'] += $entry['q_points_for_passing']; } foreach ($categories as &$category) { $category['RUNNING_PERCENTAGE'] = float_to_raw_string(100.0 * $category['RUNNING_MARKS'] / floatval($category['RUNNING_OUT_OF'])); $category['RUNNING_MARKS'] = float_to_raw_string($category['RUNNING_MARKS']); $category['RUNNING_OUT_OF'] = strval($category['RUNNING_OUT_OF']); if ($category['RUNNING_OUT_OF__CREDIT'] == 0) { $category['RUNNING_PERCENTAGE__CREDIT'] = '0.0'; } else { $category['RUNNING_PERCENTAGE__CREDIT'] = float_to_raw_string(100.0 * $category['RUNNING_MARKS__CREDIT'] / floatval($category['RUNNING_OUT_OF__CREDIT'])); } $category['RUNNING_MARKS__CREDIT'] = float_to_raw_string($category['RUNNING_MARKS__CREDIT']); $category['RUNNING_OUT_OF__CREDIT'] = strval($category['RUNNING_OUT_OF__CREDIT']); } $delete_url = new Tempcode(); if (has_actual_page_access(get_member(), 'admin_quiz')) { $delete_url = build_url(['page' => 'admin_quiz', 'type' => 'delete_quiz_results'], get_module_zone('admin_quiz')); } return [do_template('MEMBER_QUIZ_ENTRIES', [ '_GUID' => '3143daff524b1e8e8de090d445e20b28', 'CATEGORIES' => $categories, 'MEMBER_ID' => strval($member_id), 'SORTING' => $sorting, 'DELETE_URL' => $delete_url, ])]; } }