Merge branch 'MDL-41760-master-v8' of https://github.com/jamiepratt/moodle
[moodle.git] / mod / quiz / report / statistics / statistics_question_table.php
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/>.
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  */
26 defined('MOODLE_INTERNAL') || die();
28 require_once($CFG->libdir . '/tablelib.php');
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  */
42 class quiz_statistics_question_table extends flexible_table {
43     /** @var object full question object for this question. */
44     protected $questiondata;
46     /** @var  int no of attempts. */
47     protected $s;
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     }
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;
71         $this->define_baseurl($reporturl->out());
72         $this->collapsible(false);
73         $this->set_attribute('class', 'generaltable generalbox boxaligncenter quizresponseanalysis');
75         // Define the table columns.
76         $columns = array();
77         $headers = array();
79         if ($responseanalysis->has_subparts()) {
80             $columns[] = 'part';
81             $headers[] = get_string('partofquestion', 'quiz_statistics');
82         }
84         if ($responseanalysis->has_multiple_response_classes()) {
85             $columns[] = 'responseclass';
86             $headers[] = get_string('modelresponse', 'quiz_statistics');
88             if ($responseanalysis->has_actual_responses()) {
89                 $columns[] = 'response';
90                 $headers[] = get_string('actualresponse', 'quiz_statistics');
91             }
93         } else {
94             $columns[] = 'response';
95             $headers[] = get_string('response', 'quiz_statistics');
96         }
98         $columns[] = 'fraction';
99         $headers[] = get_string('optiongrade', 'quiz_statistics');
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         }
112         $columns[] = 'frequency';
113         $headers[] = get_string('frequency', 'quiz_statistics');
115         $this->define_columns($columns);
116         $this->define_headers($headers);
117         $this->sortable(false);
119         $this->column_class('fraction', 'numcol');
120         $this->column_class('count', 'numcol');
121         $this->column_class('frequency', 'numcol');
123         $this->column_suppress('part');
124         $this->column_suppress('responseclass');
126         parent::setup();
127     }
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     }
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         }
149         return $this->format_percentage($response->fraction);
150     }
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     }
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 {
181             return null;
182         }
183     }