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
/**
18
 * Question statistics calculations class. Used in the quiz statistics report.
19
 *
20
 * @package    core_question
21
 * @copyright  2018 Ryan Wyllie <ryan@moodle.com>
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
namespace core_question\statistics\questions;
26
 
27
defined('MOODLE_INTERNAL') || die();
28
 
29
require_once($CFG->dirroot . '/question/engine/lib.php');
30
 
31
/**
32
 * Class calculated_question_summary
33
 *
34
 * This class is used to indicate the statistics for a random question slot should
35
 * be rendered with a link to a summary of the displayed questions.
36
 *
37
 * It's used in the limited view of the statistics calculation in lieu of adding
38
 * the stats for each subquestion individually.
39
 *
40
 * @copyright 2018 Ryan Wyllie <ryan@moodle.com>
41
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
42
 */
43
class calculated_question_summary extends calculated {
44
 
45
    /**
46
     * @var int only set immediately before display in the table. The order of display in the table.
47
     */
48
    public $subqdisplayorder;
49
 
50
    /**
51
     * @var calculated[] The instances storing the calculated stats of the questions that are being summarised.
52
     */
53
    protected $subqstats;
54
 
55
    /**
56
     * calculated_question_summary constructor.
57
     *
58
     * @param \stdClass $question
59
     * @param int $slot
60
     * @param calculated[] $subqstats The instances of the calculated stats of the questions that are being summarised.
61
     */
62
    public function __construct($question, $slot, $subqstats) {
63
        parent::__construct($question, $slot);
64
 
65
        $this->subqstats = $subqstats;
66
        $this->subquestions = implode(',', array_column($subqstats, 'questionid'));
67
    }
68
 
69
    /**
70
     * This is a summary stat so never breakdown by variant.
71
     *
72
     * @return bool
73
     */
74
    public function break_down_by_variant() {
75
        return false;
76
    }
77
 
78
    /**
79
     * Returns the minimum and maximum values of the given attribute in the summarised calculated stats.
80
     *
81
     * @param string $attribute The attribute that we are looking for its extremums.
82
     * @return array An array of [min,max]
83
     */
84
    public function get_min_max_of($attribute) {
85
        $getmethod = 'get_min_max_of_' . $attribute;
86
        if (method_exists($this, $getmethod)) {
87
            return $this->$getmethod();
88
        } else {
89
            $min = $max = null;
90
            $set = false;
91
 
92
            // We cannot simply use min or max functions because, in theory, some attributes might be non-scalar.
93
            foreach (array_column($this->subqstats, $attribute) as $value) {
94
                if (is_scalar($value) || is_null($value)) {
95
                    if (!$set) {    // It is not good enough to check if (!isset($min)),
96
                                    // because $min might have been set to null in an earlier iteration.
97
                        $min = $value;
98
                        $max = $value;
99
                        $set = true;
100
                    }
101
 
102
                    $min  = $this->min($min, $value);
103
                    $max  = $this->max($max, $value);
104
                }
105
            }
106
 
107
            return [$min, $max];
108
        }
109
    }
110
 
111
    /**
112
     * Returns the minimum and maximum values of the standard deviation in the summarised calculated stats.
113
     * @return array An array of [min,max]
114
     */
115
    protected function get_min_max_of_sd() {
116
        $min = $max = null;
117
        $set = false;
118
 
119
        foreach ($this->subqstats as $subqstat) {
120
            if (isset($subqstat->sd) && $subqstat->maxmark > \question_utils::MARK_TOLERANCE) {
121
                $value = $subqstat->sd / $subqstat->maxmark;
122
            } else {
123
                $value = null;
124
            }
125
 
126
            if (!$set) {    // It is not good enough to check if (!isset($min)),
127
                            // because $min might have been set to null in an earlier iteration.
128
                $min = $value;
129
                $max = $value;
130
                $set = true;
131
            }
132
 
133
            $min = $this->min($min, $value);
134
            $max = $this->max($max, $value);
135
        }
136
 
137
        return [$min, $max];
138
    }
139
 
140
    /**
141
     * Find higher value.
142
     * A zero value is almost considered equal to zero in comparisons. The only difference is that when being compared to zero,
143
     * zero is higher than null.
144
     *
145
     * @param float|null $value1
146
     * @param float|null $value2
147
     * @return float|null
148
     */
149
    protected function max(float $value1 = null, float $value2 = null) {
150
        $temp1 = $value1 ?: 0;
151
        $temp2 = $value2 ?: 0;
152
 
153
        $tempmax = max($temp1, $temp2);
154
 
155
        if (!$tempmax && $value1 !== 0 && $value2 !== 0) {
156
            $max = null;
157
        } else {
158
            $max = $tempmax;
159
        }
160
 
161
        return $max;
162
    }
163
 
164
    /**
165
     * Find lower value.
166
     * A zero value is almost considered equal to zero in comparisons. The only difference is that when being compared to zero,
167
     * zero is lower than null.
168
     *
169
     * @param float|null $value1
170
     * @param float|null $value2
171
     * @return mixed|null
172
     */
173
    protected function min(float $value1 = null, float $value2 = null) {
174
        $temp1 = $value1 ?: 0;
175
        $temp2 = $value2 ?: 0;
176
 
177
        $tempmin = min($temp1, $temp2);
178
 
179
        if (!$tempmin && $value1 !== 0 && $value2 !== 0) {
180
            $min = null;
181
        } else {
182
            $min = $tempmin;
183
        }
184
 
185
        return $min;
186
    }
187
}