Revision as of 00:29, 16 August 2012 by Adam Olley (talk | contribs) (See also)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Moodle 2.2 This page describes the API used by the Engagement Analytics indicators and reporting mechanisms.

Main info

User documentation here:

IMPORTANT This page is a WIP and does not reflect the final state of the engagement analytics API!

The indicator's used by this plugin have been designed as sub-plugins to allow (and encourage) other developers to create their own indicators. Indicators could be developed to report on a wide range of things inside Moodle or even collect data from external systems to report on if desired.

Caching of raw data from different indicator plugins is automatically handled by the base indicator class so developers of new indicators don't need to worry about more expensive queries.


File Layout

Indicators live in a folder in mod/engagement/indicator. The layout inside this folder follows the typical layout for a Moodle plugin. For example, inside the mod/engagement/indicator/myind folder we would have:

Defines the indicator_myind class, which should extend the indicator base class.
This contains the definition of the engagementindicator_myind_renderer class, which should extend the engagementindicator_renderer base class.
Defines the engagementindicator_myind_thresholds_form which contains a function definition_inner for including on the report settings page.
English language strings for this indicator. You can, of course, include other languages too. The language file must define at least the string giving the indicator a name, for example $string['pluginname'] = 'My Indicator';
db/install.xml, db/upgrade.php 
For creating any database tables required, as normal. See #Database_tables below.
Defines any capabilities required by this question type. This is very rarely needed.


The indicator base class defines the following functions:

public function get_risk($userid, $courseid, $startdate = null, $enddate = null);
public function get_course_risks($startdate = null, $enddate = null);
private function get_risk_for_users($userids, $startdate, $enddate);
final private function get_cache();
final private function set_cache();
abstract protected function get_rawdata($startdate, $enddate);
abstract protected function calculate_risks(array $userids);
public function get_name();
protected function load_config();
public function save_config();

Except for the functions mentioned below, the rest of the ones mentioned above are not generally intended to be overridden in the indicators themselves.

For the development of any new indicator, the functions you must implement are the abstracted ones:

abstract protected function get_rawdata($startdate, $enddate);
abstract protected function calculate_risks(array $userids);

The get_rawdata function is intended to do the heavy lifting part of the indicator. It'll do the lookups into the database to find out the raw data for the courses users. For example, this collects the counts of read/new/total/replied posts in the forum indicator. This function is called on by the parent class and is put into a cache. The cache has a configurable lifetime set in Site administration / ► Plugins / ► Activity modules / ► Engagement analytics. The setting is engagement|cachettl which defaults to 5 minutes. Larger sites may want to consider setting this to a larger number depending on the set of indicators they're using.

The next step in the workflow takes that raw data (which comes from get_cache() unless there's no valid cache entry, which means get_rawdata is called for the data instead) and applies the course specific settings for that indicator. This is done in the calculate_risks function. This function will apply the settings set in the report settings page. This allows teachers to update the weightings / thresholds of indicators and see the new risk values without having to refetch raw data every time.

If you have any settings (and most indicators probably will), you'll probably need:

protected function load_config();

Which can be used to setup any default values you need for when a user hasn't input any on their own.



Return a random risk score for each user.

defined('MOODLE_INTERNAL') || die();
class indicator_random extends indicator {
    protected function get_rawdata($startdate, $enddate) {
        global $DB;
        $rawdata = array();
        $someusers = get_enrolled_users($this->context);
        foreach ($someusers as $user) {
            $rawdata[$user->id] = mt_rand(0,100);
        return $rawdata;
    protected function calculate_risks(array $userids) {
        $risks = array();
        foreach ($userids as $userid) {
            if (!isset($this->rawdata[$userid])) {
                $risk = new stdClass();
                $risk->risk = 0;
                $risk->info = 'No risk, user had no data collected.';
                $risks[$userid] = $risk;
            $risk = new stdClass();
            $value = $this->rawdata[$userid];
            if ($value > $this->config['max']) {
                $value = $this->config['max'];
            } else if ($value < $this->config['min']) {
                $value = $this->config['min'];
            $risk->risk = $value;
            $risk->info = 'Random risk calcualted.';
            $risks[$userid] = $risk;
        return $risks;
    protected function load_config() {
        $defaults = $this->get_defaults();
        foreach ($defaults as $setting => $value) {
            if (!isset($this->config[$setting])) {
                $this->config[$setting] = $value;
    public function get_defaults() {
        $defaults = array();
        $defaults['min'] = 5;
        $defaults['max'] = 20;
        return $defaults;

Helper Functions

Indicator Thresholds

Thresholds and other settings that get applied in the calculate_risks stage can be added to an indicator in the thresholds_form.php file.

The settings added to the definition_inner function should have a name of the format: "<indicatorname>_<setting>". i.e. for the setting "e_loginsperweek" setting of the "login" indicator, the name would be "login_e_loginsperweek".


thresholds_form.php :

defined('MOODLE_INTERNAL') || die();
class engagementindicator_random_thresholds_form {
    public function definition_inner(&$mform) {
        $defaults = indicator_login::get_defaults();
        $mform->addElement('text', 'random_min', get_string('minimum', 'engagementindicator_random'));
        $mform->setDefault("random_min", $defaults['min']);
        $mform->addElement('text', 'random_max', get_string('maximum', 'engagementindicator_random'));
        $mform->setDefault("random_max", $defaults['max']);

Indicator Renderer

The user report view which lists details from each indicator is defined in an indicators renderer file. If the user_report function is not overridden, the default renderer will simply display the risk score given by that indicator.


defined('MOODLE_INTERNAL') || die();
class engagementindicator_random_renderer extends engagementindicator_renderer {
    public function user_report($data) {
        $html = '';
        foreach ($data->info as $i) {
            $html .= html_writer::start_tag('strong');
            $html .= html_writer::tag('span', $i->title);
            $html .= html_writer::end_tag('strong');
            $html .= html_writer::empty_tag('br');
            $html .= $this->output->help_icon('localrisk', 'engagementindicator_random');
            $html .= html_writer::tag('span', 'Local risk: ' . $i->localrisk);
            $html .= html_writer::empty_tag('br');
        return $html;

For the above example to work, the random indicator would need to be returning valid data in the...<TODO>

See also

User documentation: