Merge branch 'MDL-41756-master' of https://github.com/jamiepratt/moodle
[moodle.git] / question / classes / statistics / questions / calculated.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  * Question statistics calculations class. Used in the quiz statistics report but also available for use elsewhere.
19  *
20  * @package    core
21  * @subpackage questionbank
22  * @copyright  2013 Open University
23  * @author     Jamie Pratt <me@jamiep.org>
24  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25  */
27 namespace core_question\statistics\questions;
28 defined('MOODLE_INTERNAL') || die();
30 /**
31  * This class is used to return the stats as calculated by {@link \core_question\statistics\questions\calculator}
32  *
33  * @copyright 2013 Open University
34  * @author    Jamie Pratt <me@jamiep.org>
35  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36  */
37 class calculated {
39     public $questionid;
41     // These first fields are the final fields cached in the db and shown in reports.
43     // See : http://docs.moodle.org/dev/Quiz_statistics_calculations#Position_statistics .
45     public $slot = null;
47     /**
48      * @var null|integer if this property is not null then this is the stats for a variant of a question or when inherited by
49      *                   calculated_for_subquestion and not null then this is the stats for a variant of a sub question.
50      */
51     public $variant = null;
53     /**
54      * @var bool is this a sub question.
55      */
56     public $subquestion = false;
58     /**
59      * @var int total attempts at this question.
60      */
61     public $s = 0;
63     /**
64      * @var float effective weight of this question.
65      */
66     public $effectiveweight;
68     /**
69      * @var bool is covariance of this questions mark with other question marks negative?
70      */
71     public $negcovar;
73     /**
74      * @var float
75      */
76     public $discriminationindex;
78     /**
79      * @var float
80      */
81     public $discriminativeefficiency;
83     /**
84      * @var float standard deviation
85      */
86     public $sd;
88     /**
89      * @var float
90      */
91     public $facility;
93     /**
94      * @var float max mark achievable for this question.
95      */
96     public $maxmark;
98     /**
99      * @var string comma separated list of the positions in which this question appears.
100      */
101     public $positions;
103     /**
104      * @var null|float The average score that students would have got by guessing randomly. Or null if not calculable.
105      */
106     public $randomguessscore = null;
109     // End of fields in db.
111     protected $fieldsindb = array('questionid', 'slot', 'subquestion', 's', 'effectiveweight', 'negcovar', 'discriminationindex',
112         'discriminativeefficiency', 'sd', 'facility', 'subquestions', 'maxmark', 'positions', 'randomguessscore', 'variant');
114     // Fields used for intermediate calculations.
116     public $totalmarks = 0;
118     public $totalothermarks = 0;
120     /**
121      * @var float The total of marks achieved for all positions in all attempts where this item was seen.
122      */
123     public $totalsummarks = 0;
125     public $markvariancesum = 0;
127     public $othermarkvariancesum = 0;
129     public $covariancesum = 0;
131     public $covariancemaxsum = 0;
133     public $subquestions = '';
135     public $covariancewithoverallmarksum = 0;
137     public $markarray = array();
139     public $othermarksarray = array();
141     public $markaverage;
143     public $othermarkaverage;
145     /**
146      * @var float The average for all attempts, of the sum of the marks for all positions in which this item appeared.
147      */
148     public $summarksaverage;
150     public $markvariance;
151     public $othermarkvariance;
152     public $covariance;
153     public $covariancemax;
154     public $covariancewithoverallmark;
156     /**
157      * @var object full question data
158      */
159     public $question;
161     /**
162      * An array of calculated stats for each variant of the question. Even when there is just one variant we still calculate this
163      * data as there is no way to know if there are variants before we have finished going through the attempt data one time.
164      *
165      * @var calculated[] $variants
166      */
167     public $variantstats = array();
169     /**
170      * Set if this record has been retrieved from cache. This is the time that the statistics were calculated.
171      *
172      * @var integer
173      */
174     public $timemodified;
176     /**
177      * Cache calculated stats stored in this object in 'question_statistics' table.
178      *
179      * @param \qubaid_condition $qubaids
180      */
181     public function cache($qubaids) {
182         global $DB;
183         $toinsert = new \stdClass();
184         $toinsert->hashcode = $qubaids->get_hash_code();
185         $toinsert->timemodified = time();
186         foreach ($this->fieldsindb as $field) {
187             $toinsert->{$field} = $this->{$field};
188         }
189         $DB->insert_record('question_statistics', $toinsert, false);
191         if (count($this->variantstats) > 1) {
192             foreach ($this->variantstats as $variantstat) {
193                 $variantstat->cache($qubaids);
194             }
195         }
196     }
198     /**
199      * @param object $record Given a record from 'question_statistics' copy stats from record to properties.
200      */
201     public function populate_from_record($record) {
202         foreach ($this->fieldsindb as $field) {
203             $this->$field = $record->$field;
204         }
205         $this->timemodified = $record->timemodified;
206     }