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
 * Single insight view page.
19
 *
20
 * @package    report_insights
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 report_insights\output;
26
 
27
use core_analytics\prediction;
28
 
29
defined('MOODLE_INTERNAL') || die();
30
 
31
/**
32
 * Single insight view page.
33
 *
34
 * @package    report_insights
35
 * @copyright  2017 David Monllao {@link http://www.davidmonllao.com}
36
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37
 */
38
class insight implements \renderable, \templatable {
39
 
40
    /**
41
     * @var \core_analytics\model
42
     */
43
    protected $model;
44
 
45
    /**
46
     * @var \core_analytics\prediction
47
     */
48
    protected $prediction;
49
 
50
    /**
51
     * @var bool
52
     */
53
    protected $includedetailsaction = false;
54
 
55
    /**
56
     * @var \context
57
     */
58
    protected $context;
59
 
60
    /**
61
     * Constructor
62
     *
63
     * @param \core_analytics\prediction $prediction
64
     * @param \core_analytics\model $model
65
     * @param bool $includedetailsaction
66
     * @param \context $context
67
     * @return void
68
     */
69
    public function __construct(\core_analytics\prediction $prediction, \core_analytics\model $model, $includedetailsaction,
70
            \context $context) {
71
 
72
        $this->prediction = $prediction;
73
        $this->model = $model;
74
        $this->includedetailsaction = $includedetailsaction;
75
        $this->context = $context;
76
    }
77
 
78
    /**
79
     * Exports the data.
80
     *
81
     * @param \renderer_base $output
82
     * @return \stdClass
83
     */
84
    public function export_for_template(\renderer_base $output) {
85
        // Get the prediction data.
86
        $predictiondata = $this->prediction->get_prediction_data();
87
 
88
        $target = $this->model->get_target();
89
 
90
        $data = new \stdClass();
91
        $data->modelid = $this->model->get_id();
92
        $data->contextid = $this->context->id;
93
        $data->predictionid = $predictiondata->id;
94
 
95
        $targetname = $target->get_name();
96
        $data->insightname = format_string($targetname);
97
 
98
        $targetinfostr = $targetname->get_identifier() . 'info';
99
        if (get_string_manager()->string_exists($targetinfostr, $targetname->get_component())) {
100
            $data->insightdescription = get_string($targetinfostr, $targetname->get_component());
101
        }
102
 
103
        $data->showpredictionheading = true;
104
        if (!$target->is_linear()) {
105
            $nclasses = count($target::get_classes());
106
            $nignoredclasses = count($target->ignored_predicted_classes());
107
            if ($nclasses - $nignoredclasses <= 1) {
108
                // Hide the prediction heading if there is only 1 class displayed. Otherwise it is redundant with the insight name.
109
                $data->showpredictionheading = false;
110
            }
111
        }
112
 
113
        // Get the details.
114
        $data->timecreated = userdate($predictiondata->timecreated);
115
        $data->timerange = '';
116
 
117
        if (!empty($predictiondata->timestart) && !empty($predictiondata->timeend)) {
118
            $timerange = new \stdClass();
119
            $timerange->timestart = userdate($predictiondata->timestart);
120
            $timerange->timeend = userdate($predictiondata->timeend);
121
            $data->timerange = get_string('timerangewithdata', 'report_insights', $timerange);
122
        }
123
 
124
        // Sample info (determined by the analyser).
125
        list($data->sampledescription, $samplerenderable) = $this->model->prediction_sample_description($this->prediction);
126
 
127
        // Sampleimage is a renderable we should pass it to HTML.
128
        if ($samplerenderable) {
129
            $data->sampleimage = $output->render($samplerenderable);
130
        }
131
 
132
        // Prediction info.
133
        $predictedvalue = $predictiondata->prediction;
134
        $data->predictiondisplayvalue = $target->get_display_value($predictedvalue);
135
        list($data->style, $data->outcomeicon) = self::get_calculation_display($target,
136
            floatval($predictedvalue), $output);
137
 
138
        $data->actions = actions_exporter::add_prediction_actions($target, $output, $this->prediction,
139
            $this->includedetailsaction);
140
        $data->bulkactions = actions_exporter::add_bulk_actions($target, $output, [$this->prediction], $this->context);
141
 
142
        // Calculated indicators values.
143
        $data->calculations = array();
144
        $calculations = $this->prediction->get_calculations();
145
        foreach ($calculations as $calculation) {
146
 
147
            // Hook for indicators with extra features that should not be displayed (e.g. discrete indicators).
148
            if (!$calculation->indicator->should_be_displayed($calculation->value, $calculation->subtype)) {
149
                continue;
150
            }
151
 
152
            if ($calculation->value === null) {
153
                // We don't show values that could not be calculated.
154
                continue;
155
            }
156
 
157
            $obj = new \stdClass();
158
            $obj->name = call_user_func(array($calculation->indicator, 'get_name'));
159
            $obj->displayvalue = $calculation->indicator->get_display_value($calculation->value, $calculation->subtype);
160
            list($obj->style, $obj->outcomeicon) = self::get_calculation_display($calculation->indicator,
161
                floatval($calculation->value), $output, $calculation->subtype);
162
 
163
            $identifier = $calculation->indicator->get_name()->get_identifier() . 'def';
164
            $component = $calculation->indicator->get_name()->get_component();
165
            if (get_string_manager()->string_exists($identifier, $component)) {
166
                $obj->outcomehelp = (new \help_icon($identifier, $component))->export_for_template($output);
167
            }
168
            $data->calculations[] = $obj;
169
        }
170
 
171
        if (empty($data->calculations)) {
172
            $data->nocalculations = (object)array(
173
                'message' => get_string('nodetailsavailable', 'report_insights'),
174
                'closebutton' => false
175
            );
176
        }
177
 
178
        // This is only rendered in report_insights/insight_details template for predictions with no action.
179
        // We need it to automatically enable the bulk action buttons in report/insights/prediction.php.
180
        $filtered = [
181
            \core_analytics\prediction::ACTION_FIXED,
182
            \core_analytics\prediction::ACTION_NOT_USEFUL,
183
            \core_analytics\prediction::ACTION_USEFUL,
184
            \core_analytics\prediction::ACTION_NOT_APPLICABLE,
185
            \core_analytics\prediction::ACTION_INCORRECTLY_FLAGGED,
186
        ];
187
        if (!$this->prediction->get_executed_actions($filtered)) {
188
            $toggleall = new \core\output\checkbox_toggleall('insight-bulk-action-' . $predictedvalue, true, [
189
                'id' => 'id-toggle-all-' . $predictedvalue,
190
                'name' => 'toggle-all-' . $predictedvalue,
191
                'classes' => 'hidden',
192
                'label' => get_string('selectall'),
193
                'labelclasses' => 'sr-only',
194
                'checked' => false,
195
            ]);
196
            $data->hiddencheckboxtoggleall = $output->render($toggleall);
197
 
198
            $toggle = new \core\output\checkbox_toggleall('insight-bulk-action-' . $predictedvalue, false, [
199
                'id' => 'id-select-' . $data->predictionid,
200
                'name' => 'select-' . $data->predictionid,
201
                'label' => get_string('selectprediction', 'report_insights', $data->sampledescription),
202
                'labelclasses' => 'accesshide',
203
            ]);
204
            $data->toggleslave = $output->render($toggle);
205
        }
206
 
207
        return $data;
208
    }
209
 
210
    /**
211
     * Returns display info for the calculated value outcome.
212
     *
213
     * @param \core_analytics\calculable $calculable
214
     * @param float $value
215
     * @param \renderer_base $output
216
     * @param string|false $subtype
217
     * @return array The style as 'success', 'info', 'warning' or 'danger' and pix_icon
218
     */
219
    public static function get_calculation_display(\core_analytics\calculable $calculable, $value, $output, $subtype = false) {
220
        $outcome = $calculable->get_calculation_outcome($value, $subtype);
221
        switch ($outcome) {
222
            case \core_analytics\calculable::OUTCOME_NEUTRAL:
223
                $style = '';
224
                $text = get_string('outcomeneutral', 'report_insights');
225
                $icon = 't/check';
226
                break;
227
            case \core_analytics\calculable::OUTCOME_VERY_POSITIVE:
228
                $style = 'success';
229
                $text = get_string('outcomeverypositive', 'report_insights');
230
                $icon = 't/approve';
231
                break;
232
            case \core_analytics\calculable::OUTCOME_OK:
233
                $style = 'info';
234
                $text = get_string('outcomeok', 'report_insights');
235
                $icon = 't/check';
236
                break;
237
            case \core_analytics\calculable::OUTCOME_NEGATIVE:
238
                $style = 'warning';
239
                $text = get_string('outcomenegative', 'report_insights');
240
                $icon = 'i/warning';
241
                break;
242
            case \core_analytics\calculable::OUTCOME_VERY_NEGATIVE:
243
                $style = 'danger';
244
                $text = get_string('outcomeverynegative', 'report_insights');
245
                $icon = 'i/warning';
246
                break;
247
            default:
248
                throw new \coding_exception('The outcome returned by ' . get_class($calculable) . '::get_calculation_outcome is ' .
249
                    'not one of the accepted values. Please use \core_analytics\calculable::OUTCOME_VERY_POSITIVE, ' .
250
                    '\core_analytics\calculable::OUTCOME_OK, \core_analytics\calculable::OUTCOME_NEGATIVE, ' .
251
                    '\core_analytics\calculable::OUTCOME_VERY_NEGATIVE or \core_analytics\calculable::OUTCOME_NEUTRAL');
252
        }
253
        $icon = new \pix_icon($icon, $text);
254
        return array($style, $icon->export_for_template($output));
255
    }
256
 
257
    /**
258
     * Model getter.
259
     *
260
     * @return \core_analytics\model
261
     */
262
    public function get_model(): \core_analytics\model {
263
        return $this->model;
264
    }
265
}