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
 * Representation of a prediction.
19
 *
20
 * @package   core_analytics
21
 * @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
22
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
namespace core_analytics;
26
 
27
defined('MOODLE_INTERNAL') || die();
28
 
29
/**
30
 * Representation of a prediction.
31
 *
32
 * @package   core_analytics
33
 * @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
34
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35
 */
36
class prediction {
37
 
38
    /**
39
     * Prediction details (one of the default prediction actions)
40
     */
41
    const ACTION_PREDICTION_DETAILS = 'predictiondetails';
42
 
43
    /**
44
     * Prediction useful (one of the default prediction actions)
45
     */
46
    const ACTION_USEFUL = 'useful';
47
 
48
    /**
49
     * Prediction not useful (one of the default prediction actions)
50
     */
51
    const ACTION_NOT_USEFUL = 'notuseful';
52
 
53
    /**
54
     * Prediction already fixed (one of the default prediction actions)
55
     */
56
    const ACTION_FIXED = 'fixed';
57
 
58
    /**
59
     * Prediction not applicable.
60
     */
61
    const ACTION_NOT_APPLICABLE = 'notapplicable';
62
 
63
    /**
64
     * Prediction incorrectly flagged.
65
     */
66
    const ACTION_INCORRECTLY_FLAGGED = 'incorrectlyflagged';
67
 
68
    /**
69
     * @var \stdClass
70
     */
71
    private $prediction;
72
 
73
    /**
74
     * @var array
75
     */
76
    private $sampledata;
77
 
78
    /**
79
     * @var array
80
     */
81
    private $calculations = array();
82
 
83
    /**
84
     * Constructor
85
     *
86
     * @param \stdClass|int $prediction
87
     * @param array $sampledata
88
     * @return void
89
     */
90
    public function __construct($prediction, $sampledata) {
91
        global $DB;
92
 
93
        if (is_scalar($prediction)) {
94
            $prediction = $DB->get_record('analytics_predictions', array('id' => $prediction), '*', MUST_EXIST);
95
        }
96
        $this->prediction = $prediction;
97
 
98
        $this->sampledata = $sampledata;
99
 
100
        $this->format_calculations();
101
    }
102
 
103
    /**
104
     * Get prediction object data.
105
     *
106
     * @return \stdClass
107
     */
108
    public function get_prediction_data() {
109
        return $this->prediction;
110
    }
111
 
112
    /**
113
     * Get prediction sample data.
114
     *
115
     * @return array
116
     */
117
    public function get_sample_data() {
118
        return $this->sampledata;
119
    }
120
 
121
    /**
122
     * Gets the prediction calculations
123
     *
124
     * @return array
125
     */
126
    public function get_calculations() {
127
        return $this->calculations;
128
    }
129
 
130
    /**
131
     * Stores the executed action.
132
 
133
     * Prediction instances should be retrieved using \core_analytics\manager::get_prediction,
134
     * It is the caller responsability to check that the user can see the prediction.
135
     *
136
     * @param string $actionname
137
     * @param \core_analytics\local\target\base $target
138
     */
139
    public function action_executed($actionname, \core_analytics\local\target\base $target) {
140
        global $USER, $DB;
141
 
142
        $context = \context::instance_by_id($this->get_prediction_data()->contextid, IGNORE_MISSING);
143
        if (!$context) {
144
            throw new \moodle_exception('errorpredictioncontextnotavailable', 'analytics');
145
        }
146
 
147
        // Check that the provided action exists.
148
        $actions = $target->prediction_actions($this, true);
149
        foreach ($actions as $action) {
150
            if ($action->get_action_name() === $actionname) {
151
                $found = true;
152
            }
153
        }
154
        $bulkactions = $target->bulk_actions([$this]);
155
        foreach ($bulkactions as $action) {
156
            if ($action->get_action_name() === $actionname) {
157
                $found = true;
158
            }
159
        }
160
        if (empty($found)) {
161
            throw new \moodle_exception('errorunknownaction', 'analytics');
162
        }
163
 
164
        $predictionid = $this->get_prediction_data()->id;
165
 
166
        $action = new \stdClass();
167
        $action->predictionid = $predictionid;
168
        $action->userid = $USER->id;
169
        $action->actionname = $actionname;
170
        $action->timecreated = time();
171
        $DB->insert_record('analytics_prediction_actions', $action);
172
 
173
        $eventdata = array (
174
            'context' => $context,
175
            'objectid' => $predictionid,
176
            'other' => array('actionname' => $actionname)
177
        );
178
        \core\event\prediction_action_started::create($eventdata)->trigger();
179
    }
180
 
181
    /**
182
     * Get the executed actions.
183
     *
184
     * Actions could be filtered by actionname.
185
     *
186
     * @param array $actionnamefilter Limit the results obtained to this list of action names.
187
     * @param int $userid the user id. Current user by default.
188
     * @return array of actions.
189
     */
190
    public function get_executed_actions(array $actionnamefilter = null, int $userid = 0): array {
191
        global $USER, $DB;
192
 
193
        $conditions[] = "predictionid = :predictionid";
194
        $params['predictionid'] = $this->get_prediction_data()->id;
195
        if (!$userid) {
196
            $userid = $USER->id;
197
        }
198
        $conditions[] = "userid = :userid";
199
        $params['userid'] = $userid;
200
        if ($actionnamefilter) {
201
            list($actionsql, $actionparams) = $DB->get_in_or_equal($actionnamefilter, SQL_PARAMS_NAMED);
202
            $conditions[] = "actionname $actionsql";
203
            $params = $params + $actionparams;
204
        }
205
        return $DB->get_records_select('analytics_prediction_actions', implode(' AND ', $conditions), $params);
206
    }
207
 
208
    /**
209
     * format_calculations
210
     *
211
     * @return \stdClass[]
212
     */
213
    private function format_calculations() {
214
 
215
        $calculations = json_decode($this->prediction->calculations, true);
216
 
217
        foreach ($calculations as $featurename => $value) {
218
 
219
            list($indicatorclass, $subtype) = $this->parse_feature_name($featurename);
220
 
221
            if ($indicatorclass === 'range') {
222
                // Time range indicators don't belong to any indicator class, we don't store them.
223
                continue;
224
            } else if (!\core_analytics\manager::is_valid($indicatorclass, '\core_analytics\local\indicator\base')) {
225
                throw new \moodle_exception('errorpredictionformat', 'analytics');
226
            }
227
 
228
            $this->calculations[$featurename] = new \stdClass();
229
            $this->calculations[$featurename]->subtype = $subtype;
230
            $this->calculations[$featurename]->indicator = \core_analytics\manager::get_indicator($indicatorclass);
231
            $this->calculations[$featurename]->value = $value;
232
        }
233
    }
234
 
235
    /**
236
     * parse_feature_name
237
     *
238
     * @param string $featurename
239
     * @return string[]
240
     */
241
    private function parse_feature_name($featurename) {
242
 
243
        $indicatorclass = $featurename;
244
        $subtype = false;
245
 
246
        // Some indicator result in more than 1 feature, we need to see which feature are we dealing with.
247
        $separatorpos = strpos($featurename, '/');
248
        if ($separatorpos !== false) {
249
            $subtype = substr($featurename, ($separatorpos + 1));
250
            $indicatorclass = substr($featurename, 0, $separatorpos);
251
        }
252
 
253
        return array($indicatorclass, $subtype);
254
    }
255
}