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 * Drop out course target. 19 * 20 * @package core_course 21 * @copyright 2016 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 core_course\analytics\target; 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 require_once($CFG->dirroot . '/course/lib.php'); 30 require_once($CFG->dirroot . '/lib/gradelib.php'); 31 require_once($CFG->dirroot . '/lib/completionlib.php'); 32 require_once($CFG->dirroot . '/completion/completion_completion.php'); 33 34 /** 35 * Drop out course target. 36 * 37 * @package core_course 38 * @copyright 2016 David Monllao {@link http://www.davidmonllao.com} 39 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 40 */ 41 class course_dropout extends course_enrolments { 42 43 /** 44 * Returns the name. 45 * 46 * If there is a corresponding '_help' string this will be shown as well. 47 * 48 * @return \lang_string 49 */ 50 public static function get_name() : \lang_string { 51 return new \lang_string('target:coursedropout', 'course'); 52 } 53 54 /** 55 * classes_description 56 * 57 * @return string[] 58 */ 59 protected static function classes_description() { 60 return array( 61 get_string('targetlabelstudentdropoutno', 'course'), 62 get_string('targetlabelstudentdropoutyes', 'course') 63 ); 64 } 65 66 /** 67 * Discards courses that are not yet ready to be used for training or prediction. 68 * 69 * @param \core_analytics\analysable $course 70 * @param bool $fortraining 71 * @return true|string 72 */ 73 public function is_valid_analysable(\core_analytics\analysable $course, $fortraining = true) { 74 global $DB; 75 76 $isvalid = parent::is_valid_analysable($course, $fortraining); 77 78 if (is_string($isvalid)) { 79 return $isvalid; 80 } 81 82 if ($fortraining) { 83 // Not a valid target for training if there are not enough course accesses between the course start and end dates. 84 $params = array('courseid' => $course->get_id(), 'anonymous' => 0, 'start' => $course->get_start(), 85 'end' => $course->get_end()); 86 list($studentssql, $studentparams) = $DB->get_in_or_equal($this->students, SQL_PARAMS_NAMED); 87 // Using anonymous to use the db index, not filtering by timecreated to speed it up. 88 $select = 'courseid = :courseid AND anonymous = :anonymous AND timecreated > :start AND timecreated < :end ' . 89 'AND userid ' . $studentssql; 90 91 if (!$logstore = \core_analytics\manager::get_analytics_logstore()) { 92 throw new \coding_exception('No available log stores'); 93 } 94 $nlogs = $logstore->get_events_select_count($select, array_merge($params, $studentparams)); 95 96 // At least a minimum of students activity. 97 $nstudents = count($this->students); 98 if ($nlogs / $nstudents < 10) { 99 return get_string('nocourseactivity', 'course'); 100 } 101 } 102 103 return true; 104 } 105 106 /** 107 * calculate_sample 108 * 109 * The meaning of a drop out changes depending on the settings enabled in the course. Following these priorities order: 110 * 1.- Course completion 111 * 2.- No logs during the last quarter of the course 112 * 113 * @param int $sampleid 114 * @param \core_analytics\analysable $course 115 * @param int $starttime 116 * @param int $endtime 117 * @return float|null 0 -> not at risk, 1 -> at risk 118 */ 119 protected function calculate_sample($sampleid, \core_analytics\analysable $course, $starttime = false, $endtime = false) { 120 121 if (!$this->enrolment_active_during_analysis_time($sampleid, $starttime, $endtime)) { 122 // We should not use this sample as the analysis results could be misleading. 123 return null; 124 } 125 126 $userenrol = $this->retrieve('user_enrolments', $sampleid); 127 128 // We use completion as a success metric only when it is enabled. 129 $completion = new \completion_info($course->get_course_data()); 130 if ($completion->is_enabled() && $completion->has_criteria()) { 131 $ccompletion = new \completion_completion(array('userid' => $userenrol->userid, 'course' => $course->get_id())); 132 if ($ccompletion->is_complete()) { 133 return 0; 134 } else { 135 return 1; 136 } 137 } 138 139 if (!$logstore = \core_analytics\manager::get_analytics_logstore()) { 140 throw new \coding_exception('No available log stores'); 141 } 142 143 // No logs during the last quarter of the course. 144 $courseduration = $course->get_end() - $course->get_start(); 145 $limit = intval($course->get_end() - ($courseduration / 4)); 146 $select = "courseid = :courseid AND userid = :userid AND timecreated > :limit"; 147 $params = array('userid' => $userenrol->userid, 'courseid' => $course->get_id(), 'limit' => $limit); 148 $nlogs = $logstore->get_events_select_count($select, $params); 149 if ($nlogs == 0) { 150 return 1; 151 } 152 return 0; 153 } 154 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body