Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.
   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  namespace core_course\analytics;
  18  
  19  defined('MOODLE_INTERNAL') || die();
  20  
  21  global $CFG;
  22  require_once (__DIR__ . '/../../../lib/completionlib.php');
  23  require_once (__DIR__ . '/../../../completion/criteria/completion_criteria_self.php');
  24  require_once (__DIR__ . '/../../../analytics/tests/fixtures/test_target_course_users.php');
  25  
  26  /**
  27   * Unit tests for core_course indicators.
  28   *
  29   * @package   core_course
  30   * @category  test
  31   * @copyright 2017 David MonllaĆ³ {@link http://www.davidmonllao.com}
  32   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  33   */
  34  class indicators_test extends \advanced_testcase {
  35  
  36      /**
  37       * test_no_teacher
  38       *
  39       * @return void
  40       */
  41      public function test_no_teacher() {
  42          global $DB;
  43  
  44          $this->resetAfterTest(true);
  45  
  46          $course1 = $this->getDataGenerator()->create_course();
  47          $course2 = $this->getDataGenerator()->create_course();
  48          $coursecontext1 = \context_course::instance($course1->id);
  49          $coursecontext2 = \context_course::instance($course2->id);
  50  
  51          $user = $this->getDataGenerator()->create_user();
  52  
  53          $this->getDataGenerator()->enrol_user($user->id, $course1->id, 'student');
  54          $this->getDataGenerator()->enrol_user($user->id, $course2->id, 'teacher');
  55  
  56          $indicator = new \core_course\analytics\indicator\no_teacher();
  57  
  58          $sampleids = array($course1->id => $course1->id, $course2->id => $course2->id);
  59          $data = array(
  60              $course1->id => array(
  61                  'context' => $coursecontext1,
  62                  'course' => $course1,
  63              ),
  64              $course2->id => array(
  65                  'context' => $coursecontext2,
  66                  'course' => $course2,
  67              ));
  68          $indicator->add_sample_data($data);
  69  
  70          list($values, $ignored) = $indicator->calculate($sampleids, 'course');
  71          $this->assertEquals($indicator::get_min_value(), $values[$course1->id][0]);
  72          $this->assertEquals($indicator::get_max_value(), $values[$course2->id][0]);
  73      }
  74  
  75      /**
  76       * test_completion_enabled
  77       *
  78       * @return void
  79       */
  80      public function test_completion_enabled() {
  81          global $DB;
  82  
  83          $this->resetAfterTest(true);
  84  
  85          $course1 = $this->getDataGenerator()->create_course(array('enablecompletion' => 0));
  86          $course2 = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
  87          $course3 = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
  88  
  89          // Criteria only for the last one.
  90          $criteriadata = new \stdClass();
  91          $criteriadata->id = $course3->id;
  92          $criteriadata->criteria_self = 1;
  93          $criterion = new \completion_criteria_self();
  94          $criterion->update_config($criteriadata);
  95  
  96          $indicator = new \core_course\analytics\indicator\completion_enabled();
  97  
  98          $sampleids = array($course1->id => $course1->id, $course2->id => $course2->id, $course3->id => $course3->id);
  99          $data = array(
 100              $course1->id => array(
 101                  'course' => $course1,
 102              ),
 103              $course2->id => array(
 104                  'course' => $course2,
 105              ),
 106              $course3->id => array(
 107                  'course' => $course3,
 108              ));
 109          $indicator->add_sample_data($data);
 110  
 111          // Calculate using course samples.
 112          list($values, $ignored) = $indicator->calculate($sampleids, 'course');
 113          $this->assertEquals($indicator::get_min_value(), $values[$course1->id][0]);
 114          $this->assertEquals($indicator::get_min_value(), $values[$course2->id][0]);
 115          $this->assertEquals($indicator::get_max_value(), $values[$course3->id][0]);
 116  
 117          // Calculate using course_modules samples.
 118          $indicator->clear_sample_data();
 119          $data1 = $this->getDataGenerator()->create_module('data', array('course' => $course3->id),
 120                                                               array('completion' => 0));
 121          $data2 = $this->getDataGenerator()->create_module('data', array('course' => $course3->id),
 122                                                               array('completion' => 1));
 123  
 124          $sampleids = array($data1->cmid => $data1->cmid, $data2->cmid => $data2->cmid);
 125          $cm1 = $DB->get_record('course_modules', array('id' => $data1->cmid));
 126          $cm2 = $DB->get_record('course_modules', array('id' => $data2->cmid));
 127          $data = array(
 128              $cm1->id => array(
 129                  'course' => $course3,
 130                  'course_modules' => $cm1,
 131              ),
 132              $cm2->id => array(
 133                  'course' => $course3,
 134                  'course_modules' => $cm2,
 135              ));
 136          $indicator->add_sample_data($data);
 137  
 138          list($values, $ignored) = $indicator->calculate($sampleids, 'course_modules');
 139          $this->assertEquals($indicator::get_min_value(), $values[$cm1->id][0]);
 140          $this->assertEquals($indicator::get_max_value(), $values[$cm2->id][0]);
 141      }
 142  
 143      /**
 144       * test_potential_cognitive
 145       *
 146       * @return void
 147       */
 148      public function test_potential_cognitive() {
 149          global $DB;
 150  
 151          $this->resetAfterTest(true);
 152  
 153          $course1 = $this->getDataGenerator()->create_course();
 154  
 155          $course2 = $this->getDataGenerator()->create_course();
 156          $page = $this->getDataGenerator()->create_module('page', array('course' => $course2->id));
 157  
 158          $course3 = $this->getDataGenerator()->create_course();
 159          $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course3->id));
 160          $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course3->id));
 161  
 162          $course4 = $this->getDataGenerator()->create_course();
 163          $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course4->id));
 164          $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course4->id));
 165  
 166          $indicator = new \core_course\analytics\indicator\potential_cognitive_depth();
 167  
 168          $sampleids = array($course1->id => $course1->id, $course2->id => $course2->id, $course3->id => $course3->id,
 169              $course4->id => $course4->id);
 170          $data = array(
 171              $course1->id => array(
 172                  'course' => $course1,
 173              ),
 174              $course2->id => array(
 175                  'course' => $course2,
 176              ),
 177              $course3->id => array(
 178                  'course' => $course3,
 179              ),
 180              $course4->id => array(
 181                  'course' => $course4,
 182              ));
 183          $indicator->add_sample_data($data);
 184  
 185          list($values, $ignored) = $indicator->calculate($sampleids, 'course');
 186          $this->assertEquals($indicator::get_min_value(), $values[$course1->id][0]);
 187  
 188          // General explanation about the points, the max level is 5 so level 1 is -1, level 2 is -0.5, level 3 is 0,
 189          // level 4 is 0.5 and level 5 is 1.
 190  
 191          // Page cognitive is level 1 (the lower one).
 192          $this->assertEquals($indicator::get_min_value(), $values[$course2->id][0]);
 193  
 194          // The maximum cognitive depth level is 5, assign level is 5 therefore the potential cognitive depth is the max.
 195          $this->assertEquals($indicator::get_max_value(), $values[$course3->id][0]);
 196  
 197          // Forum level is 4.
 198          $this->assertEquals(0.5, $values[$course4->id][0]);
 199  
 200          // Calculate using course_modules samples.
 201          $course5 = $this->getDataGenerator()->create_course();
 202          $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course5->id));
 203          $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course5->id));
 204  
 205          $sampleids = array($assign->cmid => $assign->cmid, $forum->cmid => $forum->cmid);
 206          $cm1 = $DB->get_record('course_modules', array('id' => $assign->cmid));
 207          $cm2 = $DB->get_record('course_modules', array('id' => $forum->cmid));
 208          $data = array(
 209              $cm1->id => array(
 210                  'course' => $course5,
 211                  'course_modules' => $cm1,
 212              ),
 213              $cm2->id => array(
 214                  'course' => $course5,
 215                  'course_modules' => $cm2,
 216              ));
 217          $indicator->clear_sample_data();
 218          $indicator->add_sample_data($data);
 219  
 220          list($values, $ignored) = $indicator->calculate($sampleids, 'course_modules');
 221          // Assign level is 5, the maximum level.
 222          $this->assertEquals($indicator::get_max_value(), $values[$cm1->id][0]);
 223          // Forum level is 4.
 224          $this->assertEquals(0.5, $values[$cm2->id][0]);
 225  
 226      }
 227  
 228      /**
 229       * test_potential_social
 230       *
 231       * @return void
 232       */
 233      public function test_potential_social() {
 234          global $DB;
 235  
 236          $this->resetAfterTest(true);
 237  
 238          $course1 = $this->getDataGenerator()->create_course();
 239  
 240          $course2 = $this->getDataGenerator()->create_course();
 241          $page = $this->getDataGenerator()->create_module('page', array('course' => $course2->id));
 242  
 243          $course3 = $this->getDataGenerator()->create_course();
 244          $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course3->id));
 245          $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course3->id));
 246  
 247          $course4 = $this->getDataGenerator()->create_course();
 248          $page = $this->getDataGenerator()->create_module('page', array('course' => $course4->id));
 249          $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course4->id));
 250  
 251          $indicator = new \core_course\analytics\indicator\potential_social_breadth();
 252  
 253          $sampleids = array($course1->id => $course1->id, $course2->id => $course2->id, $course3->id => $course3->id,
 254              $course4->id => $course4->id);
 255          $data = array(
 256              $course1->id => array(
 257                  'course' => $course1,
 258              ),
 259              $course2->id => array(
 260                  'course' => $course2,
 261              ),
 262              $course3->id => array(
 263                  'course' => $course3,
 264              ),
 265              $course4->id => array(
 266                  'course' => $course4,
 267              ));
 268          $indicator->add_sample_data($data);
 269  
 270          list($values, $ignored) = $indicator->calculate($sampleids, 'course');
 271          $this->assertEquals($indicator::get_min_value(), $values[$course1->id][0]);
 272  
 273          // General explanation about the points, the max level is 2 so level 1 is -1, level 2 is 1.
 274  
 275          // Page social is level 1 (the lower level).
 276          $this->assertEquals($indicator::get_min_value(), $values[$course2->id][0]);
 277  
 278          // Forum is level 2 and assign is level 2.
 279          $this->assertEquals($indicator::get_max_value(), $values[$course3->id][0]);
 280  
 281          // Page is level 1 and assign is level 2, so potential level is the max one.
 282          $this->assertEquals($indicator::get_max_value(), $values[$course4->id][0]);
 283  
 284          // Calculate using course_modules samples.
 285          $course5 = $this->getDataGenerator()->create_course();
 286          $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course5->id));
 287          $page = $this->getDataGenerator()->create_module('page', array('course' => $course5->id));
 288  
 289          $sampleids = array($assign->cmid => $assign->cmid, $page->cmid => $page->cmid);
 290          $cm1 = $DB->get_record('course_modules', array('id' => $assign->cmid));
 291          $cm2 = $DB->get_record('course_modules', array('id' => $page->cmid));
 292          $data = array(
 293              $cm1->id => array(
 294                  'course' => $course5,
 295                  'course_modules' => $cm1,
 296              ),
 297              $cm2->id => array(
 298                  'course' => $course5,
 299                  'course_modules' => $cm2,
 300              ));
 301          $indicator->clear_sample_data();
 302          $indicator->add_sample_data($data);
 303  
 304          list($values, $ignored) = $indicator->calculate($sampleids, 'course_modules');
 305          // Assign social is level 2 (the max level).
 306          $this->assertEquals($indicator::get_max_value(), $values[$cm1->id][0]);
 307          // Page social is level 1 (the lower level).
 308          $this->assertEquals($indicator::get_min_value(), $values[$cm2->id][0]);
 309      }
 310  
 311      /**
 312       * test_activities_due
 313       *
 314       * @return void
 315       */
 316      public function test_activities_due() {
 317          global $DB;
 318  
 319          $this->resetAfterTest(true);
 320          $this->setAdminuser();
 321  
 322          $course1 = $this->getDataGenerator()->create_course();
 323          $user1 = $this->getDataGenerator()->create_user();
 324          $this->getDataGenerator()->enrol_user($user1->id, $course1->id, 'student');
 325  
 326          $target = \core_analytics\manager::get_target('test_target_course_users');
 327          $indicators = array('\core_course\analytics\indicator\activities_due');
 328          foreach ($indicators as $key => $indicator) {
 329              $indicators[$key] = \core_analytics\manager::get_indicator($indicator);
 330          }
 331  
 332          $model = \core_analytics\model::create($target, $indicators);
 333          $model->enable('\core\analytics\time_splitting\single_range');
 334          $model->train();
 335      }
 336  }