1<?php 2// This file is part of Moodle - http://moodle.org/ 3// 4// Moodle is free software: you can redistribute it and/or modify 5// it under the terms of the GNU General Public License as published by 6// the Free Software Foundation, either version 3 of the License, or 7// (at your option) any later version. 8// 9// Moodle is distributed in the hope that it will be useful, 10// but WITHOUT ANY WARRANTY; without even the implied warranty of 11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12// GNU General Public License for more details. 13// 14// You should have received a copy of the GNU General Public License 15// along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17/** 18 * Quiz statistics report, table for showing response analysis for a particular question (or sub question). 19 * 20 * @package quiz_statistics 21 * @copyright 2014 Open University 22 * @author James Pratt <me@jamiep.org> 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26defined('MOODLE_INTERNAL') || die(); 27 28require_once($CFG->libdir . '/tablelib.php'); 29 30/** 31 * This table shows statistics about a particular question. 32 * 33 * Lists the responses that students made to this question, with frequency counts. 34 * 35 * The responses may be grouped, either by sub-part of the question, or by the 36 * answer they match. 37 * 38 * @copyright 2014 Open University 39 * @author James Pratt <me@jamiep.org> 40 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 41 */ 42class quiz_statistics_question_table extends flexible_table { 43 /** @var object full question object for this question. */ 44 protected $questiondata; 45 46 /** @var int no of attempts. */ 47 protected $s; 48 49 /** 50 * Constructor. 51 * 52 * @param int $qid the id of the particular question whose statistics are being 53 * displayed. 54 */ 55 public function __construct($qid) { 56 parent::__construct('mod-quiz-report-statistics-question-table' . $qid); 57 } 58 59 /** 60 * Set up columns and column names and other table settings. 61 * 62 * @param moodle_url $reporturl 63 * @param object $questiondata 64 * @param integer $s number of attempts on this question. 65 * @param \core_question\statistics\responses\analysis_for_question $responseanalysis 66 */ 67 public function question_setup($reporturl, $questiondata, $s, $responseanalysis) { 68 $this->questiondata = $questiondata; 69 $this->s = $s; 70 71 $this->define_baseurl($reporturl->out()); 72 $this->collapsible(false); 73 $this->set_attribute('class', 'generaltable generalbox boxaligncenter quizresponseanalysis'); 74 75 // Define the table columns. 76 $columns = array(); 77 $headers = array(); 78 79 if ($responseanalysis->has_subparts()) { 80 $columns[] = 'part'; 81 $headers[] = get_string('partofquestion', 'quiz_statistics'); 82 } 83 84 if ($responseanalysis->has_multiple_response_classes()) { 85 $columns[] = 'responseclass'; 86 $headers[] = get_string('modelresponse', 'quiz_statistics'); 87 88 if ($responseanalysis->has_actual_responses()) { 89 $columns[] = 'response'; 90 $headers[] = get_string('actualresponse', 'quiz_statistics'); 91 } 92 93 } else { 94 $columns[] = 'response'; 95 $headers[] = get_string('response', 'quiz_statistics'); 96 } 97 98 $columns[] = 'fraction'; 99 $headers[] = get_string('optiongrade', 'quiz_statistics'); 100 101 if (!$responseanalysis->has_multiple_tries_data()) { 102 $columns[] = 'totalcount'; 103 $headers[] = get_string('count', 'quiz_statistics'); 104 } else { 105 $countcolumns = range(1, $responseanalysis->get_maximum_tries()); 106 foreach ($countcolumns as $countcolumn) { 107 $columns[] = 'trycount'.$countcolumn; 108 $headers[] = get_string('counttryno', 'quiz_statistics', $countcolumn); 109 } 110 } 111 112 $columns[] = 'frequency'; 113 $headers[] = get_string('frequency', 'quiz_statistics'); 114 115 $this->define_columns($columns); 116 $this->define_headers($headers); 117 $this->sortable(false); 118 119 $this->column_class('fraction', 'numcol'); 120 $this->column_class('count', 'numcol'); 121 $this->column_class('frequency', 'numcol'); 122 123 $this->column_suppress('part'); 124 $this->column_suppress('responseclass'); 125 126 parent::setup(); 127 } 128 129 /** 130 * Take a float where 1 represents 100% and return a string representing the percentage. 131 * 132 * @param float $fraction The fraction. 133 * @return string The fraction as a percentage. 134 */ 135 protected function format_percentage($fraction) { 136 return format_float($fraction * 100, 2) . '%'; 137 } 138 139 /** 140 * The mark fraction that this response earns. 141 * @param object $response containst the data to display. 142 * @return string contents of this table cell. 143 */ 144 protected function col_fraction($response) { 145 if (is_null($response->fraction)) { 146 return ''; 147 } 148 149 return $this->format_percentage($response->fraction); 150 } 151 152 /** 153 * The frequency with which this response was given. 154 * @param object $response contains the data to display. 155 * @return string contents of this table cell. 156 */ 157 protected function col_frequency($response) { 158 if (!$this->s) { 159 return ''; 160 } 161 return $this->format_percentage($response->totalcount / $this->s); 162 } 163 164 /** 165 * If there is not a col_{column name} method then we call this method. If it returns null 166 * that means just output the property as in the table raw data. If this returns none null 167 * then this is the output for this cell of the table. 168 * 169 * @param string $colname The name of this column. 170 * @param object $response The raw data for this row. 171 * @return string|null The value for this cell of the table or null means use raw data. 172 */ 173 public function other_cols($colname, $response) { 174 if (preg_match('/^trycount(\d+)$/', $colname, $matches)) { 175 if (isset($response->trycount[$matches[1]])) { 176 return $response->trycount[$matches[1]]; 177 } else { 178 return 0; 179 } 180 } else if ($colname == 'part' || $colname == 'responseclass' || $colname == 'response') { 181 return s($response->$colname); 182 } else { 183 return null; 184 } 185 } 186} 187