Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
namespace quiz_statistics;
18
 
19
defined('MOODLE_INTERNAL') || die();
20
 
21
/**
22
 * The statistics calculator returns an instance of this class which contains the calculated statistics.
23
 *
24
 * These quiz statistics calculations are described here :
25
 *
26
 * http://docs.moodle.org/dev/Quiz_statistics_calculations#Test_statistics
27
 *
28
 * @package    quiz_statistics
29
 * @copyright  2013 The Open University
30
 * @author     James Pratt me@jamiep.org
31
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
32
 */
33
class calculated {
34
 
35
    /**
36
     * @param  string $whichattempts which attempts to use, represented internally as one of the constants as used in
37
     *                                   $quiz->grademethod ie.
38
     *                                   QUIZ_GRADEAVERAGE, QUIZ_GRADEHIGHEST, QUIZ_ATTEMPTLAST or QUIZ_ATTEMPTFIRST
39
     *                                   we calculate stats based on which attempts would affect the grade for each student,
40
     *                                   the default null value is used when constructing an instance whose values will be
41
     *                                   populated from a db record.
42
     */
43
    public function __construct($whichattempts = null) {
44
        if ($whichattempts !== null) {
45
            $this->whichattempts = $whichattempts;
46
        }
47
    }
48
 
49
    /**
50
     * @var int which attempts we are calculating calculate stats from.
51
     */
52
    public $whichattempts;
53
 
54
    /* Following stats all described here : http://docs.moodle.org/dev/Quiz_statistics_calculations#Test_statistics  */
55
 
56
    public $firstattemptscount = 0;
57
 
58
    public $allattemptscount = 0;
59
 
60
    public $lastattemptscount = 0;
61
 
62
    public $highestattemptscount = 0;
63
 
64
    public $firstattemptsavg;
65
 
66
    public $allattemptsavg;
67
 
68
    public $lastattemptsavg;
69
 
70
    public $highestattemptsavg;
71
 
72
    public $median;
73
 
74
    public $standarddeviation;
75
 
76
    public $skewness;
77
 
78
    public $kurtosis;
79
 
80
    public $cic;
81
 
82
    public $errorratio;
83
 
84
    public $standarderror;
85
 
86
    /**
87
     * @var int time these stats where calculated and cached.
88
     */
89
    public $timemodified;
90
 
91
    /**
92
     * Count of attempts selected by $this->whichattempts
93
     *
94
     * @return int
95
     */
96
    public function s() {
97
        return $this->get_field('count');
98
    }
99
 
100
    /**
101
     * Average grade for the attempts selected by $this->whichattempts
102
     *
103
     * @return float
104
     */
105
    public function avg() {
106
        return $this->get_field('avg');
107
    }
108
 
109
    /**
110
     * Get the right field name to fetch a stat for these attempts that is calculated for more than one $whichattempts (count or
111
     * avg).
112
     *
113
     * @param string $field name of field
114
     * @return int|float
115
     */
116
    protected function get_field($field) {
117
        $fieldname = calculator::using_attempts_string_id($this->whichattempts).$field;
118
        return $this->{$fieldname};
119
    }
120
 
121
    /**
122
     * @param $course
123
     * @param $cm
124
     * @param $quiz
125
     * @return array to display in table or spreadsheet.
126
     */
127
    public function get_formatted_quiz_info_data($course, $cm, $quiz) {
128
 
129
        // You can edit this array to control which statistics are displayed.
130
        $todisplay = ['firstattemptscount' => 'number',
131
                           'allattemptscount' => 'number',
132
                           'firstattemptsavg' => 'summarks_as_percentage',
133
                           'allattemptsavg' => 'summarks_as_percentage',
134
                           'lastattemptsavg' => 'summarks_as_percentage',
135
                           'highestattemptsavg' => 'summarks_as_percentage',
136
                           'median' => 'summarks_as_percentage',
137
                           'standarddeviation' => 'summarks_as_percentage',
138
                           'skewness' => 'number_format',
139
                           'kurtosis' => 'number_format',
140
                           'cic' => 'number_format_percent',
141
                           'errorratio' => 'number_format_percent',
142
                           'standarderror' => 'summarks_as_percentage'];
143
 
144
        // General information about the quiz.
145
        $quizinfo = [];
146
        $quizinfo[get_string('quizname', 'quiz_statistics')] = format_string($quiz->name);
147
        $quizinfo[get_string('coursename', 'quiz_statistics')] = format_string($course->fullname);
148
        if ($cm->idnumber) {
149
            $quizinfo[get_string('idnumbermod')] = $cm->idnumber;
150
        }
151
        if ($quiz->timeopen) {
152
            $quizinfo[get_string('quizopen', 'quiz')] = userdate($quiz->timeopen);
153
        }
154
        if ($quiz->timeclose) {
155
            $quizinfo[get_string('quizclose', 'quiz')] = userdate($quiz->timeclose);
156
        }
157
        if ($quiz->timeopen && $quiz->timeclose) {
158
            $quizinfo[get_string('duration', 'quiz_statistics')] =
159
                format_time($quiz->timeclose - $quiz->timeopen);
160
        }
161
 
162
        // The statistics.
163
        foreach ($todisplay as $property => $format) {
164
            if (!isset($this->$property) || !$format) {
165
                continue;
166
            }
167
            $value = $this->$property;
168
 
169
            switch ($format) {
170
                case 'summarks_as_percentage':
171
                    $formattedvalue = quiz_report_scale_summarks_as_percentage($value, $quiz);
172
                    break;
173
                case 'number_format_percent':
174
                    $formattedvalue = quiz_format_grade($quiz, $value) . '%';
175
                    break;
176
                case 'number_format':
177
                    // 2 extra decimal places, since not a percentage,
178
                    // and we want the same number of sig figs.
179
                    $formattedvalue = format_float($value, $quiz->decimalpoints + 2);
180
                    break;
181
                case 'number':
182
                    $formattedvalue = $value + 0;
183
                    break;
184
                default:
185
                    $formattedvalue = $value;
186
            }
187
 
188
            $quizinfo[get_string($property, 'quiz_statistics',
189
                                 calculator::using_attempts_lang_string($this->whichattempts))] = $formattedvalue;
190
        }
191
 
192
        return $quizinfo;
193
    }
194
 
195
    /**
196
     * @var array of names of properties of this class that are cached in db record.
197
     */
198
    protected $fieldsindb = ['whichattempts', 'firstattemptscount', 'allattemptscount', 'firstattemptsavg', 'allattemptsavg',
199
                                    'lastattemptscount', 'highestattemptscount', 'lastattemptsavg', 'highestattemptsavg',
200
                                    'median', 'standarddeviation', 'skewness',
201
                                    'kurtosis', 'cic', 'errorratio', 'standarderror'];
202
 
203
    /**
204
     * Cache the stats contained in this class.
205
     *
206
     * @param $qubaids \qubaid_condition
207
     */
208
    public function cache($qubaids) {
209
        global $DB;
210
 
211
        $toinsert = new \stdClass();
212
 
213
        foreach ($this->fieldsindb as $field) {
214
            $toinsert->{$field} = $this->{$field};
215
        }
216
 
217
        $toinsert->hashcode = $qubaids->get_hash_code();
218
        $toinsert->timemodified = time();
219
 
220
        // Fix up some dodgy data.
221
        if (isset($toinsert->errorratio) && is_nan($toinsert->errorratio)) {
222
            $toinsert->errorratio = null;
223
        }
224
        if (isset($toinsert->standarderror) && is_nan($toinsert->standarderror)) {
225
            $toinsert->standarderror = null;
226
        }
227
 
228
        // Delete older statistics before we save the new ones.
229
        $transaction = $DB->start_delegated_transaction();
230
        $DB->delete_records('quiz_statistics', ['hashcode' => $qubaids->get_hash_code()]);
231
 
232
        // Store the data.
233
        $DB->insert_record('quiz_statistics', $toinsert);
234
        $transaction->allow_commit();
235
    }
236
 
237
    /**
238
     * Given a record from 'quiz_statistics' table load the data into the properties of this class.
239
     *
240
     * @param $record \stdClass from db.
241
     */
242
    public function populate_from_record($record) {
243
        foreach ($this->fieldsindb as $field) {
244
            $this->$field = $record->$field;
245
        }
246
        $this->timemodified = $record->timemodified;
247
    }
248
}