MDL-54989 scormreport_graphs: Use the new charting library
authorFrederic Massart <fred@moodle.com>
Fri, 24 Jun 2016 04:24:28 +0000 (12:24 +0800)
committerDan Poltawski <dan@moodle.com>
Mon, 25 Jul 2016 09:42:52 +0000 (10:42 +0100)
Part of MDL-54987 epic.

mod/scorm/report/graphs/classes/report.php
mod/scorm/report/graphs/graph.php

index 4a4b263..8174686 100644 (file)
 namespace scormreport_graphs;
 
 defined('MOODLE_INTERNAL') || die();
+
+use context_module;
+use core\chart_bar;
+use core\chart_series;
+use moodle_url;
+
 /**
  * Main class to control the graphs reporting
  *
@@ -33,31 +39,144 @@ defined('MOODLE_INTERNAL') || die();
  */
 
 class report extends \mod_scorm\report {
+
+    /** Number of bars. */
+    const BANDS = 11;
+
+    /** Range of each bar. */
+    const BANDWIDTH = 10;
+
+    /**
+     * Get the data for the report.
+     *
+     * @param int $scoid The sco ID.
+     * @param array $allowedlist The list of user IDs allowed to be displayed.
+     * @return array of data indexed per bar.
+     */
+    protected function get_data($scoid, $allowedlist = []) {
+        global $DB;
+        $data = array_fill(0, self::BANDS, 0);
+        if (empty($allowedlist)) {
+            return $data;
+        }
+
+        list($usql, $params) = $DB->get_in_or_equal($allowedlist);
+        $params[] = $scoid;
+
+        // Construct the SQL.
+        $sql = "SELECT DISTINCT " . $DB->sql_concat('st.userid', '\'#\'', 'COALESCE(st.attempt, 0)') . " AS uniqueid,
+                       st.userid AS userid,
+                       st.scormid AS scormid,
+                       st.attempt AS attempt,
+                       st.scoid AS scoid
+                  FROM {scorm_scoes_track} st
+                 WHERE st.userid $usql AND st.scoid = ?";
+        $attempts = $DB->get_records_sql($sql, $params);
+
+        $usergrades = [];
+        foreach ($attempts as $attempt) {
+            if ($trackdata = scorm_get_tracks($scoid, $attempt->userid, $attempt->attempt)) {
+                if (isset($trackdata->score_raw)) {
+                    $score = $trackdata->score_raw;
+                    if (empty($trackdata->score_min)) {
+                        $minmark = 0;
+                    } else {
+                        $minmark = $trackdata->score_min;
+                    }
+                    // TODO MDL-55004: Get this value from elsewhere?
+                    if (empty($trackdata->score_max)) {
+                        $maxmark = 100;
+                    } else {
+                        $maxmark = $trackdata->score_max;
+                    }
+                    $range = ($maxmark - $minmark);
+                    if (empty($range)) {
+                        continue;
+                    }
+                    $percent = round((($score * 100) / $range), 2);
+                    if (empty($usergrades[$attempt->userid]) || !isset($usergrades[$attempt->userid])
+                            || ($percent > $usergrades[$attempt->userid]) || ($usergrades[$attempt->userid] === '*')) {
+                        $usergrades[$attempt->userid] = $percent;
+                    }
+                    unset($percent);
+                } else {
+                    // User has made an attempt but either SCO was not able to record the score or something else is broken in SCO.
+                    if (!isset($usergrades[$attempt->userid])) {
+                        $usergrades[$attempt->userid] = '*';
+                    }
+                }
+            }
+        }
+
+        // Recording all users who attempted the SCO, but resulting data was invalid.
+        foreach ($usergrades as $userpercent) {
+            if ($userpercent === '*') {
+                $data[0]++;
+            } else {
+                $gradeband = floor($userpercent / self::BANDWIDTH);
+                if ($gradeband != (self::BANDS - 1)) {
+                    $gradeband++;
+                }
+                $data[$gradeband]++;
+            }
+        }
+
+        return $data;
+    }
+
     /**
-     * Displays the full report
+     * Displays the full report.
      *
      * @param \stdClass $scorm full SCORM object
      * @param \stdClass $cm - full course_module object
      * @param \stdClass $course - full course object
      * @param string $download - type of download being requested
+     * @return void
      */
     public function display($scorm, $cm, $course, $download) {
         global $DB, $OUTPUT, $PAGE;
 
+        $contextmodule = context_module::instance($cm->id);
+
         if ($groupmode = groups_get_activity_groupmode($cm)) {   // Groups are being used.
-            groups_print_activity_menu($cm, new \moodle_url($PAGE->url));
+            groups_print_activity_menu($cm, new moodle_url($PAGE->url));
+        }
+
+        // Find out current restriction.
+        $group = groups_get_activity_group($cm, true);
+        if (empty($group)) {
+            // All users who can attempt scoes.
+            $students = get_users_by_capability($contextmodule, 'mod/scorm:savetrack', 'u.id' , '', '', '', '', '', false);
+            $allowedlist = empty($students) ? array() : array_keys($students);
+        } else {
+            // All users who can attempt scoes and who are in the currently selected group.
+            $groupstudents = get_users_by_capability($contextmodule, 'mod/scorm:savetrack', 'u.id', '', '', '', $group, '', false);
+            $allowedlist = empty($groupstudents) ? array() : array_keys($groupstudents);
+        }
+
+        // Labels.
+        $labels = [get_string('invaliddata', 'scormreport_graphs')];
+        for ($i = 1; $i <= self::BANDS - 1; $i++) {
+            $labels[] = ($i - 1) * self::BANDWIDTH . ' - ' . $i * self::BANDWIDTH;
         }
 
         if ($scoes = $DB->get_records('scorm_scoes', array("scorm" => $scorm->id), 'sortorder, id')) {
             foreach ($scoes as $sco) {
                 if ($sco->launch != '') {
-                    $imageurl = new \moodle_url('/mod/scorm/report/graphs/graph.php',
-                            array('scoid' => $sco->id));
-                    $graphname = $sco->title;
-                    echo $OUTPUT->heading($graphname, 3);
-                    echo \html_writer::tag('div', \html_writer::empty_tag('img',
-                            array('src' => $imageurl, 'alt' => $graphname)),
-                            array('class' => 'graph'));
+
+                    $data = $this->get_data($sco->id, $allowedlist);
+                    $series = new chart_series($sco->title, $data);
+
+                    $chart = new chart_bar();
+                    $chart->set_labels($labels);
+                    $chart->add_series($series);
+                    $chart->get_xaxis(0, true)->set_label(get_string('percent', 'scormreport_graphs'));
+                    $yaxis = $chart->get_yaxis(0, true);
+                    $yaxis->set_label(get_string('participants', 'scormreport_graphs'));
+                    $yaxis->set_stepsize(max(1, round(max($data) / 10)));
+
+                    echo $OUTPUT->heading($sco->title, 3);
+                    echo $OUTPUT->render($chart);
                 }
             }
         }
index dea5e0d..7ab5486 100644 (file)
  * @package    scormreport_graphs
  * @copyright  2012 Ankit Kumar Agarwal
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @deprecated since Moodle 3.2
  */
 
 define('NO_DEBUG_DISPLAY', true);
 
 require_once(__DIR__ . '/../../../../config.php');
-require_once($CFG->libdir . '/graphlib.php');
-require_once($CFG->dirroot.'/mod/scorm/report/reportlib.php');
-require_once($CFG->dirroot.'/mod/scorm/locallib.php');
+require_once($CFG->libdir . '/filelib.php');
 
-$scoid = required_param('scoid', PARAM_INT);// SCO ID.
-
-$sco = $DB->get_record('scorm_scoes', array('id' => $scoid), '*', MUST_EXIST);
-$scorm = $DB->get_record('scorm', array('id' => $sco->scorm), '*', MUST_EXIST);
-$cm = get_coursemodule_from_instance('scorm', $scorm->id, 0, false, MUST_EXIST);
-$course = $DB->get_record('course', array('id' => $scorm->course), '*', MUST_EXIST);
-
-
-// Capability Checks.
-require_login($course, false, $cm);
-$contextmodule = context_module::instance($cm->id);
-require_capability('mod/scorm:viewreport', $contextmodule);
-
-// Find out current groups mode.
-$currentgroup = groups_get_activity_group($cm, true);
-
-// Group Check.
-if (empty($currentgroup)) {
-    // All users who can attempt scoes.
-    $students = get_users_by_capability($contextmodule, 'mod/scorm:savetrack', 'u.id' , '', '', '', '', '', false);
-    $allowedlist = empty($students) ? array() : array_keys($students);
-} else {
-    // All users who can attempt scoes and who are in the currently selected group.
-    $groupstudents = get_users_by_capability($contextmodule, 'mod/scorm:savetrack', 'u.id', '', '', '', $currentgroup, '', false);
-    $allowedlist = empty($groupstudents) ? array() : array_keys($groupstudents);
-}
-
-$params = array();
-$bands = 11;
-$bandwidth = 10;
-
-// Determine maximum % secured for each user.
-$usergrades = array();
-$graphdata = array();
-for ($i = 0; $i < $bands; $i++) {
-    $graphdata[$i] = 0;
-}
-
-// Do this only if we have students to report.
-if (!empty($allowedlist)) {
-    list($usql, $params) = $DB->get_in_or_equal($allowedlist);
-    $params[] = $scoid;
-    // Construct the SQL.
-    $select = 'SELECT DISTINCT '.$DB->sql_concat('st.userid', '\'#\'', 'COALESCE(st.attempt, 0)').' AS uniqueid, ';
-    $select .= 'st.userid AS userid, st.scormid AS scormid, st.attempt AS attempt, st.scoid AS scoid ';
-    $from = 'FROM {scorm_scoes_track} st ';
-    $where = ' WHERE st.userid ' .$usql. ' and st.scoid = ?';
-    $attempts = $DB->get_records_sql($select.$from.$where, $params);
-
-    foreach ($attempts as $attempt) {
-        if ($trackdata = scorm_get_tracks($scoid, $attempt->userid, $attempt->attempt)) {
-            if (isset($trackdata->score_raw)) {
-                $score = $trackdata->score_raw;
-                if (empty($trackdata->score_min)) {
-                    $minmark = 0;
-                } else {
-                    $minmark = $trackdata->score_min;
-                }
-                if (empty($trackdata->score_max)) {
-                    $maxmark = 100;
-                } else {
-                    $maxmark = $trackdata->score_max;
-                }
-                $range = ($maxmark - $minmark);
-                if (empty($range)) {
-                    continue;
-                }
-                $percent = round((($score * 100) / $range), 2);
-                if (empty($usergrades[$attempt->userid]) || !isset($usergrades[$attempt->userid])
-                        || ($percent > $usergrades[$attempt->userid]) || ($usergrades[$attempt->userid] === '*')) {
-                    $usergrades[$attempt->userid] = $percent;
-                }
-                unset($percent);
-            } else {
-                // User has made an attempt but either SCO was not able to record the score or something else is broken in SCO.
-                if (!isset($usergrades[$attempt->userid])) {
-                    $usergrades[$attempt->userid] = '*';
-                }
-            }
-        }
-    }
-}
-
-$bandlabels[] = get_string('invaliddata', 'scormreport_graphs');
-for ($i = 1; $i <= $bands - 1; $i++) {
-    $bandlabels[] = ($i - 1) * $bandwidth . ' - ' . $i * $bandwidth;
-}
-// Recording all users  who attempted the SCO,but resulting data was invalid.
-foreach ($usergrades as $userpercent) {
-    if ($userpercent === '*') {
-        $graphdata[0]++;
-    } else {
-        $gradeband = floor($userpercent / 10);
-        if ($gradeband != ($bands - 1)) {
-            $gradeband++;
-        }
-        $graphdata[$gradeband]++;
-    }
-}
-
-$line = new graph(800, 600);
-$line->parameter['title'] = '';
-$line->parameter['y_label_left'] = get_string('participants', 'scormreport_graphs');
-$line->parameter['x_label'] = get_string('percent', 'scormreport_graphs');
-$line->parameter['y_label_angle'] = 90;
-$line->parameter['x_label_angle'] = 0;
-$line->parameter['x_axis_angle'] = 60;
-
-// Following two lines seem to silence notice warnings from graphlib.php.
-$line->y_tick_labels = null;
-$line->offset_relation = null;
-
-$line->parameter['bar_size'] = 1;
-// Don't forget to increase spacing so that graph doesn't become one big block of colour.
-$line->parameter['bar_spacing'] = 10;
-$line->x_data = $bandlabels;
-
-$line->y_format['allusers'] = array(
-    'colour' => 'red',
-    'bar' => 'fill',
-    'shadow_offset' => 1,
-    'legend' => get_string('allparticipants')
-);
-ksort($graphdata);
-$line->y_data['allusers'] = $graphdata;
-$line->y_order = array('allusers');
-
-$ymax = max($line->y_data['allusers']);
-$line->parameter['y_min_left'] = 0;  // Start at 0.
-$line->parameter['y_max_left'] = $ymax;
-$line->parameter['y_decimal_left'] = 0; // 2 decimal places for y axis.
-
-// Pick a sensible number of gridlines depending on max value on graph.
-$gridlines = $ymax;
-while ($gridlines >= 10) {
-    if ($gridlines >= 50) {
-        $gridlines /= 5;
-    } else {
-        $gridlines /= 2;
-    }
-}
-$gridlines = max(2, ($gridlines + 1)); // We need a minimum of two lines.
-$line->parameter['y_axis_gridlines'] = $gridlines;
-
-$line->draw();
+debugging('This way of generating the chart is deprecated, refer to \\scormreport_graphs\\report::display().', DEBUG_DEVELOPER);
+send_file_not_found();