diff --git a/course/classes/analytics/indicator/completion_enabled.php b/course/classes/analytics/indicator/completion_enabled.php new file mode 100644 index 00000000000..f2598e080da --- /dev/null +++ b/course/classes/analytics/indicator/completion_enabled.php @@ -0,0 +1,89 @@ +. + +/** + * Completion enabled set indicator. + * + * @package core_course + * @copyright 2017 David Monllao {@link http://www.davidmonllao.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_course\analytics\indicator; + +defined('MOODLE_INTERNAL') || die(); + +require_once($CFG->dirroot . '/lib/completionlib.php'); + +/** + * Completion enabled set indicator. + * + * @package core_course + * @copyright 2016 David Monllao {@link http://www.davidmonllao.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class completion_enabled extends \core_analytics\local\indicator\binary { + + /** + * get_name + * + * @return new \lang_string + */ + public static function get_name() : \lang_string { + return new \lang_string('indicator:completionenabled', 'moodle'); + } + + /** + * required_sample_data + * + * @return string[] + */ + public static function required_sample_data() { + // Minimum course although it also accepts course_modules. + return array('course'); + } + + /** + * Is completion enabled? Work both with courses and activities. + * + * @param int $sampleid + * @param string $sampleorigin + * @param int|false $notusedstarttime + * @param int|false $notusedendtime + * @return float + */ + public function calculate_sample($sampleid, $sampleorigin, $notusedstarttime = false, $notusedendtime = false) { + + $course = $this->retrieve('course', $sampleid); + + $cm = false; + if ($sampleorigin === 'course_modules') { + $cm = $this->retrieve('course_modules', $sampleid); + } + + $completion = new \completion_info($course); + + if (!$completion->is_enabled($cm)) { + $value = self::get_min_value(); + } else if (!$cm && !$completion->has_criteria()) { + // Course completion enabled with no criteria counts as nothing. + $value = self::get_min_value(); + } else { + $value = self::get_max_value(); + } + return $value; + } +} diff --git a/course/classes/analytics/indicator/potential_cognitive_depth.php b/course/classes/analytics/indicator/potential_cognitive_depth.php new file mode 100644 index 00000000000..ea96e426bae --- /dev/null +++ b/course/classes/analytics/indicator/potential_cognitive_depth.php @@ -0,0 +1,136 @@ +. + +/** + * Potential cognitive depth indicator. + * + * @package core_course + * @copyright 2017 David Monllao {@link http://www.davidmonllao.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_course\analytics\indicator; + +defined('MOODLE_INTERNAL') || die(); + +use \core_analytics\local\indicator\community_of_inquiry_activity; + +/** + * Potential cognitive depth indicator. + * + * It extends linear instead of discrete as there is a linear relation between + * the different cognitive levels activities can reach. + * + * @package core_course + * @copyright 2017 David Monllao {@link http://www.davidmonllao.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class potential_cognitive_depth extends \core_analytics\local\indicator\linear { + + /** + * get_name + * + * @return \lang_string + */ + public static function get_name() : \lang_string { + return new \lang_string('indicator:potentialcognitive', 'moodle'); + } + + /** + * Specify the required data to process this indicator. + * + * @return string[] + */ + public static function required_sample_data() { + // We require course because, although this indicator can also work with course_modules we can't + // calculate anything without the course. + return array('course'); + } + + /** + * calculate_sample + * + * @throws \coding_exception + * @param int $sampleid + * @param string $sampleorigin + * @param int|false $notusedstarttime + * @param int|false $notusedendtime + * @return float + */ + public function calculate_sample($sampleid, $sampleorigin, $notusedstarttime = false, $notusedendtime = false) { + + if ($sampleorigin === 'course_modules') { + $cm = $this->retrieve('course_modules', $sampleid); + $cminfo = \cm_info::create($cm); + + $cognitivedepthindicator = $this->get_cognitive_indicator($cminfo->modname); + $potentiallevel = $cognitivedepthindicator->get_cognitive_depth_level($cminfo); + if ($potentiallevel > community_of_inquiry_activity::MAX_COGNITIVE_LEVEL) { + throw new \coding_exception('Maximum cognitive depth level is ' . + community_of_inquiry_activity::MAX_COGNITIVE_LEVEL . ', ' . $potentiallevel . ' provided by ' . + get_class($this)); + } + + } else { + $course = $this->retrieve('course', $sampleid); + $modinfo = get_fast_modinfo($course); + + $cms = $modinfo->get_cms(); + if (!$cms) { + return self::get_min_value(); + } + + $potentiallevel = 0; + foreach ($cms as $cm) { + if (!$cognitivedepthindicator = $this->get_cognitive_indicator($cm->modname)) { + continue; + } + $level = $cognitivedepthindicator->get_cognitive_depth_level($cm); + if ($level > community_of_inquiry_activity::MAX_COGNITIVE_LEVEL) { + throw new \coding_exception('Maximum cognitive depth level is ' . + community_of_inquiry_activity::MAX_COGNITIVE_LEVEL . ', ' . $level . ' provided by ' . get_class($this)); + } + if ($level > $potentiallevel) { + $potentiallevel = $level; + } + } + } + + // Values from -1 to 1 range split in 5 parts (the max cognitive depth level). + // Note that we divide by 4 because we start from -1. + $levelscore = round((self::get_max_value() - self::get_min_value()) / 4, 2); + // We substract $levelscore because we want to start from the lower score and there is no cognitive depth level 0. + return self::get_min_value() + ($levelscore * $potentiallevel) - $levelscore; + } + + /** + * Returns the cognitive depth class of this indicator. + * + * @param string $modname + * @return \core_analytics\local\indicator\base|false + */ + protected function get_cognitive_indicator($modname) { + $indicators = \core_analytics\manager::get_all_indicators(); + foreach ($indicators as $indicator) { + if ($indicator instanceof community_of_inquiry_activity && + $indicator->get_indicator_type() === community_of_inquiry_activity::INDICATOR_COGNITIVE && + $indicator->get_activity_type() === $modname) { + return $indicator; + } + } + return false; + } +} diff --git a/course/classes/analytics/indicator/potential_social_breadth.php b/course/classes/analytics/indicator/potential_social_breadth.php new file mode 100644 index 00000000000..ac15780b604 --- /dev/null +++ b/course/classes/analytics/indicator/potential_social_breadth.php @@ -0,0 +1,142 @@ +. + +/** + * Potential social breadth indicator. + * + * @package core_course + * @copyright 2017 David Monllao {@link http://www.davidmonllao.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_course\analytics\indicator; + +defined('MOODLE_INTERNAL') || die(); + +use \core_analytics\local\indicator\community_of_inquiry_activity; + +/** + * Potential social breadth indicator. + * + * It extends linear instead of discrete as there is a linear relation between + * the different social levels activities can reach. + * + * @package core_course + * @copyright 2017 David Monllao {@link http://www.davidmonllao.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class potential_social_breadth extends \core_analytics\local\indicator\linear { + + /** + * get_name + * + * @return \lang_string + */ + public static function get_name() : \lang_string { + return new \lang_string('indicator:potentialsocial', 'moodle'); + } + + /** + * Specify the required data to process this indicator. + * + * @return string[] + */ + public static function required_sample_data() { + // We require course because, although this indicator can also work with course_modules we can't + // calculate anything without the course. + return array('course'); + } + + /** + * calculate_sample + * + * @param int $sampleid + * @param string $sampleorigin + * @param int|false $notusedstarttime + * @param int|false $notusedendtime + * @return float + */ + public function calculate_sample($sampleid, $sampleorigin, $notusedstarttime = false, $notusedendtime = false) { + + if ($sampleorigin === 'course_modules') { + $cm = $this->retrieve('course_modules', $sampleid); + $cminfo = \cm_info::create($cm); + + $socialbreadthindicator = $this->get_social_indicator($cminfo->modname); + $potentiallevel = $socialbreadthindicator->get_social_breadth_level($cminfo); + if ($potentiallevel > community_of_inquiry_activity::MAX_SOCIAL_LEVEL) { + $this->level_not_accepted($potentiallevel); + } + + } else { + $course = $this->retrieve('course', $sampleid); + $modinfo = get_fast_modinfo($course); + + $cms = $modinfo->get_cms(); + if (!$cms) { + return self::get_min_value(); + } + + $potentiallevel = 0; + foreach ($cms as $cm) { + if (!$socialbreadthindicator = $this->get_social_indicator($cm->modname)) { + continue; + } + $level = $socialbreadthindicator->get_social_breadth_level($cm); + if ($level > community_of_inquiry_activity::MAX_SOCIAL_LEVEL) { + $this->level_not_accepted($level); + } + if ($level > $potentiallevel) { + $potentiallevel = $level; + } + } + } + + // Supporting only social breadth level 1 and 2 the possible values are -1 or 1. + $levelscore = round(self::get_max_value() - self::get_min_value(), 2); + + // We substract $levelscore because we want to start from the lower socre and there is no cognitive depth level 0. + return self::get_min_value() + ($levelscore * $potentiallevel) - $levelscore; + } + + /** + * Returns the social breadth class of this indicator. + * + * @param string $modname + * @return \core_analytics\local\indicator\base|false + */ + protected function get_social_indicator($modname) { + $indicators = \core_analytics\manager::get_all_indicators(); + foreach ($indicators as $indicator) { + if ($indicator instanceof community_of_inquiry_activity && + $indicator->get_indicator_type() === community_of_inquiry_activity::INDICATOR_SOCIAL && + $indicator->get_activity_type() === $modname) { + return $indicator; + } + } + return false; + } + + /** + * Throw a \coding_exception. + * + * @param int $level + */ + protected function level_not_accepted($level) { + throw new \coding_exception('Although social breadth levels can go from 1 to 5 at the moment Moodle core can only accept' . + ' social breadth levels 1 and 2. Sorry for the inconvenience, this will change in future releases.'); + } +}