6fa46f73cdc36793fe66e21180c7854cc4f3f987
[moodle.git] / mod / scorm / report / graphs / classes / report.php
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  * Core Report class of graphs reporting plugin
18  *
19  * @package    scormreport_graphs
20  * @copyright  2012 Ankit Kumar Agarwal
21  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22  */
24 namespace scormreport_graphs;
26 defined('MOODLE_INTERNAL') || die();
28 use context_module;
29 use core\chart_bar;
30 use core\chart_series;
31 use moodle_url;
33 /**
34  * Main class to control the graphs reporting
35  *
36  * @package    scormreport_graphs
37  * @copyright  2012 Ankit Kumar Agarwal
38  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39  */
41 class report extends \mod_scorm\report {
43     /** Number of bars. */
44     const BANDS = 11;
46     /** Range of each bar. */
47     const BANDWIDTH = 10;
49     /**
50      * Get the data for the report.
51      *
52      * @param int $scoid The sco ID.
53      * @param array $allowedlist The SQL and params to get the userlist.
54      * @return array of data indexed per bar.
55      */
56     protected function get_data($scoid, $allowedlistsql) {
57         global $DB;
58         $data = array_fill(0, self::BANDS, 0);
60         list($allowedlist, $params) = $allowedlistsql;
61         $params = array_merge($params, ['scoid' => $scoid]);
63         // Construct the SQL.
64         $sql = "SELECT DISTINCT " . $DB->sql_concat('st.userid', '\'#\'', 'COALESCE(st.attempt, 0)') . " AS uniqueid,
65                        st.userid AS userid,
66                        st.scormid AS scormid,
67                        st.attempt AS attempt,
68                        st.scoid AS scoid
69                   FROM {scorm_scoes_track} st
70                  WHERE st.userid IN ({$allowedlistsql}) AND st.scoid = :scoid";
71         $attempts = $DB->get_records_sql($sql, $params);
73         $usergrades = [];
74         foreach ($attempts as $attempt) {
75             if ($trackdata = scorm_get_tracks($scoid, $attempt->userid, $attempt->attempt)) {
76                 if (isset($trackdata->score_raw)) {
77                     $score = (int) $trackdata->score_raw;
78                     if (empty($trackdata->score_min)) {
79                         $minmark = 0;
80                     } else {
81                         $minmark = $trackdata->score_min;
82                     }
83                     // TODO MDL-55004: Get this value from elsewhere?
84                     if (empty($trackdata->score_max)) {
85                         $maxmark = 100;
86                     } else {
87                         $maxmark = $trackdata->score_max;
88                     }
89                     $range = ($maxmark - $minmark);
90                     if (empty($range)) {
91                         continue;
92                     }
93                     $percent = round((($score * 100) / $range), 2);
94                     if (empty($usergrades[$attempt->userid]) || !isset($usergrades[$attempt->userid])
95                             || ($percent > $usergrades[$attempt->userid]) || ($usergrades[$attempt->userid] === '*')) {
96                         $usergrades[$attempt->userid] = $percent;
97                     }
98                     unset($percent);
99                 } else {
100                     // User has made an attempt but either SCO was not able to record the score or something else is broken in SCO.
101                     if (!isset($usergrades[$attempt->userid])) {
102                         $usergrades[$attempt->userid] = '*';
103                     }
104                 }
105             }
106         }
108         // Recording all users who attempted the SCO, but resulting data was invalid.
109         foreach ($usergrades as $userpercent) {
110             if ($userpercent === '*') {
111                 $data[0]++;
112             } else {
113                 $gradeband = floor($userpercent / self::BANDWIDTH);
114                 if ($gradeband != (self::BANDS - 1)) {
115                     $gradeband++;
116                 }
117                 $data[$gradeband]++;
118             }
119         }
121         return $data;
122     }
124     /**
125      * Displays the full report.
126      *
127      * @param \stdClass $scorm full SCORM object
128      * @param \stdClass $cm - full course_module object
129      * @param \stdClass $course - full course object
130      * @param string $download - type of download being requested
131      * @return void
132      */
133     public function display($scorm, $cm, $course, $download) {
134         global $DB, $OUTPUT, $PAGE;
136         $contextmodule = context_module::instance($cm->id);
138         if ($groupmode = groups_get_activity_groupmode($cm)) {   // Groups are being used.
139             groups_print_activity_menu($cm, new moodle_url($PAGE->url));
140         }
142         // Find out current restriction.
143         $group = groups_get_activity_group($cm, true);
144         $allowedlistsql = get_enrolled_sql($contextmodule, 'mod/scorm:savetrack', (int) $group);
146         // Labels.
147         $labels = [get_string('invaliddata', 'scormreport_graphs')];
148         for ($i = 1; $i <= self::BANDS - 1; $i++) {
149             $labels[] = ($i - 1) * self::BANDWIDTH . ' - ' . $i * self::BANDWIDTH;
150         }
152         if ($scoes = $DB->get_records('scorm_scoes', array("scorm" => $scorm->id), 'sortorder, id')) {
153             foreach ($scoes as $sco) {
154                 if ($sco->launch != '') {
156                     $data = $this->get_data($sco->id, $allowedlistsql);
157                     $series = new chart_series($sco->title, $data);
159                     $chart = new chart_bar();
160                     $chart->set_labels($labels);
161                     $chart->add_series($series);
162                     $chart->get_xaxis(0, true)->set_label(get_string('percent', 'scormreport_graphs'));
163                     $yaxis = $chart->get_yaxis(0, true);
164                     $yaxis->set_label(get_string('participants', 'scormreport_graphs'));
165                     $yaxis->set_stepsize(max(1, round(max($data) / 10)));
167                     echo $OUTPUT->heading($sco->title, 3);
168                     echo $OUTPUT->render($chart);
169                 }
170             }
171         }
172     }