Proyectos de Subversion Moodle

Rev

Ir a la última revisión | | 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
/**
18
 * Unit tests for (some of) /question/engine/statistics.php
19
 *
20
 * @package   quiz_statistics
21
 * @category  test
22
 * @copyright 2008 Jamie Pratt
23
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24
 */
25
 
26
namespace quiz_statistics;
27
 
28
defined('MOODLE_INTERNAL') || die();
29
 
30
global $CFG;
31
require_once($CFG->libdir . '/questionlib.php');
32
require_once($CFG->dirroot . '/mod/quiz/locallib.php');
33
require_once($CFG->dirroot . '/mod/quiz/report/reportlib.php');
34
 
35
class testable_all_calculated_for_qubaid_condition extends \core_question\statistics\questions\all_calculated_for_qubaid_condition {
36
 
37
    /**
38
     * Disabling caching in tests so we are always sure to force the calculation of stats right then and there.
39
     *
40
     * @param qubaid_condition $qubaids
41
     */
42
    public function cache($qubaids) {
43
 
44
    }
45
}
46
 
47
/**
48
 * Test helper subclass of question_statistics
49
 *
50
 * @copyright 2010 The Open University
51
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
52
 */
53
class testable_question_statistics extends \core_question\statistics\questions\calculator {
54
 
55
    /**
56
     * @var stdClass[]
57
     */
58
    protected $lateststeps;
59
 
60
    protected $statscollectionclassname = '\quiz_statistics\testable_all_calculated_for_qubaid_condition';
61
 
62
    public function set_step_data($states) {
63
        $this->lateststeps = $states;
64
    }
65
 
66
    protected function get_random_guess_score($questiondata) {
67
        return 0;
68
    }
69
 
70
    /**
71
     * @param $qubaids qubaid_condition is ignored in this test
72
     * @return array with two items
73
     *              - $lateststeps array of latest step data for the question usages
74
     *              - $summarks    array of total marks for each usage, indexed by usage id
75
     */
76
    protected function get_latest_steps($qubaids) {
77
        $summarks = [];
78
        $fakeusageid = 0;
79
        foreach ($this->lateststeps as $step) {
80
            // The same 'sumgrades' field is available in step data for every slot, we will ignore all slots but slot 1.
81
            // The step for slot 1 is always the first one in the csv file for each usage, we will use that to separate steps from
82
            // each usage.
83
            if ($step->slot == 1) {
84
                $fakeusageid++;
85
                $summarks[$fakeusageid] = $step->sumgrades;
86
            }
87
            unset($step->sumgrades);
88
            $step->questionusageid = $fakeusageid;
89
        }
90
 
91
        return [$this->lateststeps, $summarks];
92
    }
93
 
94
    protected function cache_stats($qubaids) {
95
        // No caching wanted for tests.
96
    }
97
}
98
/**
99
 * Unit tests for (some of) question_statistics.
100
 *
101
 * @copyright 2008 Jamie Pratt
102
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
103
 */
104
class statistics_test extends \basic_testcase {
105
    /** @var testable_all_calculated_for_qubaid_condition object created to test class. */
106
    protected $qstats;
107
 
108
    public function test_qstats() {
109
        global $CFG;
110
        // Data is taken from randomly generated attempts data generated by
111
        // contrib/tools/generators/qagenerator/.
112
        $steps = $this->get_records_from_csv(__DIR__.'/fixtures/mdl_question_states.csv');
113
        // Data is taken from questions mostly generated by
114
        // contrib/tools/generators/generator.php.
115
        $questions = $this->get_records_from_csv(__DIR__.'/fixtures/mdl_question.csv');
116
        $calculator = new testable_question_statistics($questions);
117
        $calculator->set_step_data($steps);
118
        $this->qstats = $calculator->calculate(null);
119
 
120
        // Values expected are taken from contrib/tools/quiz_tools/stats.xls.
121
        $facility = [0, 0, 0, 0, null, null, null, 41.19318182, 81.36363636,
122
            71.36363636, 65.45454545, 65.90909091, 36.36363636, 59.09090909, 50,
123
            59.09090909, 63.63636364, 45.45454545, 27.27272727, 50];
124
        $this->qstats_q_fields('facility', $facility, 100);
125
        $sd = [0, 0, 0, 0, null, null, null, 1912.733589, 251.2738111,
126
            322.6312277, 333.4199022, 337.5811591, 492.3659639, 503.2362797,
127
            511.7663157, 503.2362797, 492.3659639, 509.6471914, 455.8423058, 511.7663157];
128
        $this->qstats_q_fields('sd', $sd, 1000);
129
        $effectiveweight = [0, 0, 0, 0, 0, 0, 0, 26.58464457, 3.368456046,
130
            3.253955259, 7.584083694, 3.79658376, 3.183278505, 4.532356904,
131
            7.78856243, 10.08351572, 8.381139345, 8.727645713, 7.946277111, 4.769500946];
132
        $this->qstats_q_fields('effectiveweight', $effectiveweight);
133
        $discriminationindex = [null, null, null, null, null, null, null,
134
            25.88327077, 1.170256965, -4.207816809, 28.16930644, -2.513606859,
135
            -12.99017581, -8.900638238, 8.670004606, 29.63337745, 15.18945843,
136
            16.21079629, 15.52451404, -8.396734802];
137
        $this->qstats_q_fields('discriminationindex', $discriminationindex);
138
        $discriminativeefficiency = [null, null, null, null, null, null, null,
139
            27.23492723, 1.382386552, -4.691171307, 31.12404354, -2.877487579,
140
            -17.5074184, -10.27568922, 10.86956522, 34.58997279, 17.4790556,
141
            20.14359793, 22.06477733, -10];
142
        $this->qstats_q_fields('discriminativeefficiency', $discriminativeefficiency);
143
    }
144
 
145
    public function qstats_q_fields($fieldname, $values, $multiplier=1) {
146
        foreach ($this->qstats->get_all_slots() as $slot) {
147
            $value = array_shift($values);
148
            if ($value !== null) {
149
                $this->assertEqualsWithDelta($value, $this->qstats->for_slot($slot)->{$fieldname} * $multiplier, 1E-6);
150
            } else {
151
                $this->assertEquals($value, $this->qstats->for_slot($slot)->{$fieldname} * $multiplier);
152
            }
153
        }
154
    }
155
 
156
    public function get_fields_from_csv($line) {
157
        $line = trim($line);
158
        $items = preg_split('!,!', $line);
159
        $cnt = count($items);
160
        for ($key = 0; $key < $cnt; $key++) {
161
            if ($items[$key]!='') {
162
                if ($start = ($items[$key][0]=='"')) {
163
                    $items[$key] = substr($items[$key], 1);
164
                    while (!$end = ($items[$key][strlen($items[$key])-1]=='"')) {
165
                        $item = $items[$key];
166
                        unset($items[$key]);
167
                        $key++;
168
                        $items[$key] = $item . ',' . $items[$key];
169
                    }
170
                    $items[$key] = substr($items[$key], 0, strlen($items[$key])-1);
171
                }
172
 
173
            }
174
        }
175
        return $items;
176
    }
177
 
178
    public function get_records_from_csv($filename) {
179
        $filecontents = file($filename, FILE_IGNORE_NEW_LINES);
180
        $records = [];
181
        // Skip the first line containing field names.
182
        $keys = $this->get_fields_from_csv(array_shift($filecontents));
183
        while (null !== ($line = array_shift($filecontents))) {
184
            $data = $this->get_fields_from_csv($line);
185
            $arraykey = reset($data);
186
            $object = new \stdClass();
187
            foreach ($keys as $key) {
188
                $value = array_shift($data);
189
                if ($value !== null) {
190
                    $object->{$key} = $value;
191
                } else {
192
                    $object->{$key} = '';
193
                }
194
            }
195
            $records[$arraykey] = $object;
196
        }
197
        return $records;
198
    }
199
}