MDL-59057 analytics: Split up course analyser in 2
authorDavid Monllao <davidm@moodle.com>
Fri, 9 Jun 2017 18:32:07 +0000 (20:32 +0200)
committerDavid Monllao <davidm@moodle.com>
Mon, 24 Jul 2017 06:36:45 +0000 (08:36 +0200)
One at course level so teachers can get insights and another
one at system level so the insights go to the site admin.

Part of MDL-57791 epic.

admin/tool/models/classes/analytics/target/no_teaching.php
admin/tool/models/db/install.php
analytics/classes/local/analyser/courses.php
analytics/classes/local/analyser/site_courses.php [new file with mode: 0644]
analytics/classes/local/time_splitting/base.php
analytics/classes/local/time_splitting/single_range.php

index 88536e2..eaff611 100644 (file)
@@ -58,7 +58,7 @@ class no_teaching extends \core_analytics\local\target\binary {
         $course = $sampledata['course'];
 
         $url = new \moodle_url('/course/view.php', array('id' => $course->id));
-        $pix = new \pix_icon('i/course', get_string('enrolledusers', 'enrol'));
+        $pix = new \pix_icon('i/course', get_string('course'));
         $actions['viewcourse'] = new \core_analytics\prediction_action('viewcourse', $prediction,
             $url, $pix, get_string('view'));
 
@@ -97,18 +97,30 @@ class no_teaching extends \core_analytics\local\target\binary {
     }
 
     public function get_analyser_class() {
-        return '\\core_analytics\\local\\analyser\\courses';
+        return '\\core_analytics\\local\\analyser\\site_courses';
     }
 
-    public function is_valid_analysable(\core_analytics\analysable $site, $fortraining = true) {
+    public function is_valid_analysable(\core_analytics\analysable $analysable, $fortraining = true) {
         // The analysable is the site, so yes, it is always valid.
         return true;
     }
 
-    public function is_valid_sample($sampleid, \core_analytics\analysable $site) {
+    /**
+     * Only process samples which start date is getting close.
+     *
+     * @param mixed $sampleid
+     * @param \core_analytics\analysable $analysable
+     * @return void
+     */
+    public function is_valid_sample($sampleid, \core_analytics\analysable $analysable) {
 
         $course = $this->retrieve('course', $sampleid);
-        if (!$course->startdate || $course->startdate - WEEKSECS > time()) {
+
+        $now = time();
+
+        // No courses without start date, no finished courses nor predictions before start - 1 week.
+        if (!$course->startdate || (!empty($course->enddate) && $course->enddate < $now) ||
+                $course->startdate - WEEKSECS > $now) {
             return false;
         }
         return true;
@@ -118,10 +130,10 @@ class no_teaching extends \core_analytics\local\target\binary {
      * calculate_sample
      *
      * @param int $sampleid
-     * @param \core_analytics\analysable $site
+     * @param \core_analytics\analysable $analysable
      * @return void
      */
-    protected function calculate_sample($sampleid, \core_analytics\analysable $site, $starttime = false, $endtime = false) {
+    protected function calculate_sample($sampleid, \core_analytics\analysable $analysable, $starttime = false, $endtime = false) {
 
         $noteachersindicator = $this->retrieve('\core_course\analytics\indicator\no_teacher', $sampleid);
         if ($noteachersindicator == \core_course\analytics\indicator\no_teacher::get_min_value()) {
index f1408fa..ec86a90 100644 (file)
@@ -40,7 +40,7 @@ function xmldb_tool_models_install() {
 
     // Course without teachers.
     $target = \core_analytics\manager::get_target('\tool_models\analytics\target\no_teaching');
-    $weekbeforestart = '\core_analytics\local\time_splitting\week_before_course_start';
+    $weekbeforestart = '\core_analytics\local\time_splitting\single_range';
     $noteacher = \core_analytics\manager::get_indicator('\core_course\analytics\indicator\no_teacher');
     \core_analytics\model::create($target, array($noteacher->get_id() => $noteacher), $weekbeforestart);
 }
index 65efca4..3596866 100644 (file)
@@ -15,6 +15,7 @@
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 /**
+ * Courses analyser working at course level (insights for the course teachers).
  *
  * @package   core_analytics
  * @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
@@ -26,12 +27,13 @@ namespace core_analytics\local\analyser;
 defined('MOODLE_INTERNAL') || die();
 
 /**
+ * Courses analyser working at course level (insights for the course teachers).
  *
  * @package   core_analytics
  * @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-class courses extends sitewide {
+class courses extends by_course {
 
     public function get_samples_origin() {
         return 'course';
@@ -44,7 +46,7 @@ class courses extends sitewide {
      * @return \core_analytics\analysable
      */
     public function get_sample_analysable($sampleid) {
-        return new \core_analytics\site();
+        return new \core_analytics\course($sampleid);
     }
 
     protected function provided_sample_data() {
@@ -52,28 +54,34 @@ class courses extends sitewide {
     }
 
     public function sample_access_context($sampleid) {
-        return \context_system::instance();
+        return \context_course::instance($sampleid);
     }
 
-    protected function get_all_samples(\core_analytics\analysable $site) {
+    /**
+     * get_all_samples
+     *
+     * @param \core_analytics\analysable $course
+     * @return array
+     */
+    protected function get_all_samples(\core_analytics\analysable $course) {
         global $DB;
 
-        // Getting courses from DB instead of from the site as these samples
-        // will be stored in memory and we just want the id.
-        $select = 'id != 1';
-        $courses = $DB->get_records_select('course', $select, null, '', '*');
-
-        $courseids = array_keys($courses);
-        $sampleids = array_combine($courseids, $courseids);
+        $coursedata = $course->get_course_data();
+        $context = \context_course::instance($course->get_id());
 
-        $courses = array_map(function($course) {
-            return array('course' => $course, 'context' => \context_course::instance($course->id));
-        }, $courses);
-
-        // No related data attached.
-        return array($sampleids, $courses);
+        // Just 1 sample per analysable.
+        return array(
+            array($course->get_id() => $course->get_id()),
+            array($course->get_id() => array('course' => $course, 'context' => $context))
+        );
     }
 
+    /**
+     * get_samples
+     *
+     * @param int[] $sampleids
+     * @return array
+     */
     public function get_samples($sampleids) {
         global $DB;
 
@@ -97,7 +105,7 @@ class courses extends sitewide {
      * @param int $sampleid
      * @param int $contextid
      * @param array $sampledata
-     * @return void
+     * @return array
      */
     public function sample_description($sampleid, $contextid, $sampledata) {
         $description = format_string($sampledata['course']->fullname, true, array('context' => $sampledata['context']));
diff --git a/analytics/classes/local/analyser/site_courses.php b/analytics/classes/local/analyser/site_courses.php
new file mode 100644 (file)
index 0000000..b130f51
--- /dev/null
@@ -0,0 +1,109 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Site courses analyser working at system level (insights for the site admin).
+ *
+ * @package   core_analytics
+ * @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace core_analytics\local\analyser;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Site courses analyser working at system level (insights for the site admin).
+ *
+ * @package   core_analytics
+ * @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class site_courses extends sitewide {
+
+    public function get_samples_origin() {
+        return 'course';
+    }
+
+    /**
+     * get_sample_analysable
+     *
+     * @param int $sampleid
+     * @return \core_analytics\analysable
+     */
+    public function get_sample_analysable($sampleid) {
+        return new \core_analytics\site();
+    }
+
+    protected function provided_sample_data() {
+        return array('course', 'context');
+    }
+
+    public function sample_access_context($sampleid) {
+        return \context_system::instance();
+    }
+
+    protected function get_all_samples(\core_analytics\analysable $site) {
+        global $DB;
+
+        // Getting courses from DB instead of from the site as these samples
+        // will be stored in memory and we just want the id.
+        $select = 'id != 1';
+        $courses = $DB->get_records_select('course', $select, null, '', '*');
+
+        $courseids = array_keys($courses);
+        $sampleids = array_combine($courseids, $courseids);
+
+        $courses = array_map(function($course) {
+            return array('course' => $course, 'context' => \context_course::instance($course->id));
+        }, $courses);
+
+        // No related data attached.
+        return array($sampleids, $courses);
+    }
+
+    public function get_samples($sampleids) {
+        global $DB;
+
+        list($sql, $params) = $DB->get_in_or_equal($sampleids, SQL_PARAMS_NAMED);
+        $courses = $DB->get_records_select('course', "id $sql", $params);
+
+        $courseids = array_keys($courses);
+        $sampleids = array_combine($courseids, $courseids);
+
+        $courses = array_map(function($course) {
+            return array('course' => $course, 'context' => \context_course::instance($course->id));
+        }, $courses);
+
+        // No related data attached.
+        return array($sampleids, $courses);
+    }
+
+    /**
+     * sample_description
+     *
+     * @param int $sampleid
+     * @param int $contextid
+     * @param array $sampledata
+     * @return void
+     */
+    public function sample_description($sampleid, $contextid, $sampledata) {
+        $description = format_string($sampledata['course']->fullname, true, array('context' => $sampledata['context']));
+        $courseimage = new \pix_icon('i/course', get_string('course'));
+        return array($description, $courseimage);
+    }
+}
index 5e721e3..b65abec 100644 (file)
@@ -107,7 +107,7 @@ abstract class base {
     }
 
     /**
-     * Calculates the course students indicators and targets.
+     * Calculates indicators and targets.
      *
      * @param array $sampleids
      * @param string $samplesorigin
@@ -153,7 +153,7 @@ abstract class base {
     }
 
     /**
-     * Calculates indicators for all course students.
+     * Calculates indicators.
      *
      * @return array
      */
index 61d2a29..cf55c94 100644 (file)
@@ -33,11 +33,12 @@ class single_range extends base {
     }
 
     protected function define_ranges() {
+        // time == 0 because we want it to start predicting from the beginning.
         return [
             [
                 'start' => $this->analysable->get_start(),
                 'end' => $this->analysable->get_end(),
-                'time' => $this->analysable->get_end()
+                'time' => 0
             ]
         ];
     }